From 136023e0d2a1df774e51528802f856b3e8c9ad35 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Fri, 8 Oct 2021 13:53:48 +0100 Subject: [PATCH] New upstream version 1.55.0+dfsg1 --- Cargo.lock | 540 +- Cargo.toml | 2 + README.md | 9 +- RELEASES.md | 151 +- compiler/rustc_apfloat/tests/ieee.rs | 10 +- compiler/rustc_apfloat/tests/ppc.rs | 20 +- compiler/rustc_ast/src/ast.rs | 12 +- compiler/rustc_ast/src/entry.rs | 1 + compiler/rustc_ast/src/expand/allocator.rs | 2 +- compiler/rustc_ast/src/lib.rs | 1 - compiler/rustc_ast/src/mut_visit.rs | 12 +- compiler/rustc_ast/src/node_id.rs | 8 +- compiler/rustc_ast/src/util/comments/tests.rs | 10 +- compiler/rustc_ast_lowering/src/asm.rs | 16 + compiler/rustc_ast_lowering/src/expr.rs | 34 +- compiler/rustc_ast_lowering/src/item.rs | 68 +- compiler/rustc_ast_lowering/src/lib.rs | 150 +- compiler/rustc_ast_lowering/src/pat.rs | 28 +- compiler/rustc_ast_lowering/src/path.rs | 1 + .../rustc_ast_passes/src/ast_validation.rs | 77 +- compiler/rustc_ast_passes/src/feature_gate.rs | 18 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 10 +- compiler/rustc_ast_pretty/src/pprust/tests.rs | 8 +- compiler/rustc_attr/src/builtin.rs | 152 +- compiler/rustc_builtin_macros/src/asm.rs | 14 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 59 +- compiler/rustc_builtin_macros/src/derive.rs | 11 +- .../src/deriving/clone.rs | 11 +- .../src/deriving/encodable.rs | 7 +- .../src/deriving/generic/mod.rs | 2 +- .../src/deriving/generic/ty.rs | 10 +- compiler/rustc_builtin_macros/src/format.rs | 15 +- compiler/rustc_builtin_macros/src/lib.rs | 6 +- .../src/proc_macro_harness.rs | 85 +- .../rustc_builtin_macros/src/source_util.rs | 2 +- .../src/standard_library_imports.rs | 4 +- .../rustc_builtin_macros/src/test_harness.rs | 5 +- compiler/rustc_codegen_cranelift/.cirrus.yml | 2 +- .../.github/workflows/main.yml | 73 +- .../.github/workflows/rustc.yml | 4 +- .../.vscode/settings.json | 21 +- compiler/rustc_codegen_cranelift/Cargo.lock | 56 +- compiler/rustc_codegen_cranelift/Cargo.toml | 4 +- compiler/rustc_codegen_cranelift/Readme.md | 10 +- compiler/rustc_codegen_cranelift/build.sh | 89 - .../build_sysroot/Cargo.lock | 14 +- .../build_sysroot/build_sysroot.sh | 39 - .../build_sysroot/prepare_sysroot_src.sh | 39 - .../build_system/build_backend.rs | 40 + .../build_system/build_sysroot.rs | 216 + .../build_system/config.rs | 55 + .../build_system/prepare.rs | 133 + .../build_system/rustc_info.rs | 65 + .../build_system/utils.rs | 35 + compiler/rustc_codegen_cranelift/clean_all.sh | 3 +- compiler/rustc_codegen_cranelift/config.txt | 17 + .../rustc_codegen_cranelift/docs/usage.md | 11 +- .../example/mini_core_hello_world.rs | 6 +- .../example/std_example.rs | 2 - ...ins-Disable-128bit-atomic-operations.patch | 0 ...1-rand-Enable-c2-chacha-simd-feature.patch | 0 .../0002-rand-Disable-failing-test.patch | 0 ...sysroot-Disable-not-compiling-tests.patch} | 0 ...> 0023-sysroot-Ignore-failing-tests.patch} | 0 ...27-sysroot-128bit-atomic-operations.patch} | 0 compiler/rustc_codegen_cranelift/prepare.sh | 29 - .../rustc_codegen_cranelift/rust-toolchain | 2 +- .../rustc_codegen_cranelift/scripts/cargo.rs | 70 + .../rustc_codegen_cranelift/scripts/cargo.sh | 18 - .../rustc_codegen_cranelift/scripts/config.sh | 25 +- .../scripts/ext_config.sh | 7 +- .../scripts/filter_profile.rs | 5 +- .../rustc_codegen_cranelift/scripts/rustup.sh | 2 +- .../scripts/setup_rust_fork.sh | 6 +- .../scripts/test_rustc_tests.sh | 4 +- .../rustc_codegen_cranelift/scripts/tests.sh | 36 +- .../rustc_codegen_cranelift/src/allocator.rs | 2 +- compiler/rustc_codegen_cranelift/src/base.rs | 25 +- .../src/bin/cg_clif.rs | 25 +- .../rustc_codegen_cranelift/src/common.rs | 1 - .../src/compiler_builtins.rs | 2 +- .../rustc_codegen_cranelift/src/constant.rs | 150 +- .../src/debuginfo/line_info.rs | 2 +- .../src/debuginfo/mod.rs | 8 +- .../rustc_codegen_cranelift/src/driver/aot.rs | 7 +- .../rustc_codegen_cranelift/src/driver/jit.rs | 129 +- .../src/intrinsics/llvm.rs | 58 + .../src/intrinsics/mod.rs | 34 + compiler/rustc_codegen_cranelift/src/lib.rs | 21 +- .../src/optimize/mod.rs | 5 +- .../src/pretty_clif.rs | 19 +- .../rustc_codegen_cranelift/src/unsize.rs | 4 +- .../src/value_and_place.rs | 4 + .../rustc_codegen_cranelift/src/vtable.rs | 111 +- compiler/rustc_codegen_cranelift/test.sh | 4 +- compiler/rustc_codegen_cranelift/y.rs | 153 + compiler/rustc_codegen_llvm/Cargo.toml | 2 - compiler/rustc_codegen_llvm/src/asm.rs | 50 +- compiler/rustc_codegen_llvm/src/attributes.rs | 33 +- .../rustc_codegen_llvm/src/back/archive.rs | 27 +- compiler/rustc_codegen_llvm/src/builder.rs | 39 +- compiler/rustc_codegen_llvm/src/common.rs | 13 +- compiler/rustc_codegen_llvm/src/consts.rs | 9 +- compiler/rustc_codegen_llvm/src/context.rs | 33 +- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- .../src/debuginfo/metadata.rs | 162 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 27 +- .../src/debuginfo/namespace.rs | 21 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 55 +- compiler/rustc_codegen_llvm/src/lib.rs | 10 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 10 +- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 14 + compiler/rustc_codegen_llvm/src/va_arg.rs | 21 +- compiler/rustc_codegen_ssa/Cargo.toml | 5 +- compiler/rustc_codegen_ssa/src/back/link.rs | 292 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 201 +- compiler/rustc_codegen_ssa/src/back/rpath.rs | 19 +- .../rustc_codegen_ssa/src/back/rpath/tests.rs | 4 +- .../src/back/symbol_export.rs | 4 +- compiler/rustc_codegen_ssa/src/back/write.rs | 9 +- compiler/rustc_codegen_ssa/src/base.rs | 40 +- .../src/debuginfo/type_names.rs | 499 +- compiler/rustc_codegen_ssa/src/glue.rs | 7 +- compiler/rustc_codegen_ssa/src/lib.rs | 11 +- compiler/rustc_codegen_ssa/src/meth.rs | 64 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 167 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 20 +- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 2 +- .../rustc_codegen_ssa/src/mir/intrinsic.rs | 9 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 16 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 12 - .../rustc_codegen_ssa/src/traits/builder.rs | 12 +- .../rustc_codegen_ssa/src/traits/consts.rs | 2 + compiler/rustc_codegen_ssa/src/traits/misc.rs | 2 +- compiler/rustc_data_structures/Cargo.toml | 1 - .../rustc_data_structures/src/captures.rs | 2 - compiler/rustc_data_structures/src/lib.rs | 23 +- .../src/obligation_forest/mod.rs | 2 + .../rustc_data_structures/src/profiling.rs | 60 +- .../src/sorted_map/index_map.rs | 84 +- .../src/sorted_map/tests.rs | 6 +- compiler/rustc_data_structures/src/vec_map.rs | 49 +- compiler/rustc_driver/Cargo.toml | 2 - compiler/rustc_driver/src/lib.rs | 105 +- compiler/rustc_driver/src/pretty.rs | 30 +- compiler/rustc_error_codes/src/error_codes.rs | 16 +- .../src/error_codes/E0094.md | 2 +- .../src/error_codes/E0493.md | 2 +- .../src/error_codes/E0508.md | 13 + .../src/error_codes/E0542.md | 4 +- .../src/error_codes/E0545.md | 4 +- .../src/error_codes/E0547.md | 4 +- .../src/error_codes/E0632.md | 25 + .../src/error_codes/E0690.md | 10 +- .../src/error_codes/E0716.md | 6 +- .../src/error_codes/E0722.md | 31 + .../src/error_codes/E0757.md | 33 + .../src/annotate_snippet_emitter_writer.rs | 5 +- compiler/rustc_errors/src/diagnostic.rs | 9 +- compiler/rustc_errors/src/emitter.rs | 49 +- compiler/rustc_errors/src/json.rs | 14 +- compiler/rustc_errors/src/json/tests.rs | 7 +- compiler/rustc_errors/src/lib.rs | 37 +- compiler/rustc_expand/src/base.rs | 155 +- compiler/rustc_expand/src/build.rs | 2 +- compiler/rustc_expand/src/expand.rs | 153 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 73 +- compiler/rustc_expand/src/mbe/transcribe.rs | 6 +- compiler/rustc_expand/src/mut_visit/tests.rs | 6 +- compiler/rustc_expand/src/parse/tests.rs | 26 +- compiler/rustc_expand/src/proc_macro.rs | 10 +- .../rustc_expand/src/proc_macro_server.rs | 45 +- compiler/rustc_expand/src/tests.rs | 4 +- .../rustc_expand/src/tokenstream/tests.rs | 20 +- compiler/rustc_feature/src/active.rs | 92 +- compiler/rustc_feature/src/builtin_attrs.rs | 13 +- compiler/rustc_feature/src/lib.rs | 2 +- compiler/rustc_feature/src/removed.rs | 8 + compiler/rustc_graphviz/src/lib.rs | 22 +- compiler/rustc_hir/src/definitions.rs | 24 +- compiler/rustc_hir/src/hir.rs | 66 +- compiler/rustc_hir/src/lang_items.rs | 5 +- compiler/rustc_hir/src/lib.rs | 1 - compiler/rustc_hir/src/stable_hash_impls.rs | 13 +- compiler/rustc_hir/src/tests.rs | 13 +- compiler/rustc_hir_pretty/src/lib.rs | 6 +- compiler/rustc_incremental/src/persist/fs.rs | 19 +- .../rustc_incremental/src/persist/load.rs | 25 +- compiler/rustc_infer/Cargo.toml | 2 - .../src/infer/canonical/canonicalizer.rs | 48 +- .../src/infer/error_reporting/mod.rs | 24 +- .../infer/error_reporting/need_type_info.rs | 7 +- .../mismatched_static_lifetime.rs | 103 + .../error_reporting/nice_region_error/mod.rs | 2 + .../nice_region_error/static_impl_trait.rs | 42 +- .../error_reporting/nice_region_error/util.rs | 59 +- compiler/rustc_infer/src/infer/freshen.rs | 14 +- .../src/infer/lexical_region_resolve/mod.rs | 1 + compiler/rustc_infer/src/infer/mod.rs | 7 +- .../src/infer/region_constraints/mod.rs | 2 +- .../rustc_infer/src/infer/type_variable.rs | 1 + compiler/rustc_infer/src/traits/mod.rs | 7 +- compiler/rustc_interface/Cargo.toml | 1 - compiler/rustc_interface/src/interface.rs | 5 +- compiler/rustc_interface/src/passes.rs | 186 +- compiler/rustc_interface/src/queries.rs | 103 +- compiler/rustc_interface/src/tests.rs | 62 +- compiler/rustc_interface/src/util.rs | 53 +- compiler/rustc_lexer/src/lib.rs | 22 +- compiler/rustc_lint/src/array_into_iter.rs | 89 +- compiler/rustc_lint/src/builtin.rs | 34 +- compiler/rustc_lint/src/context.rs | 136 +- compiler/rustc_lint/src/early.rs | 22 +- compiler/rustc_lint/src/internal.rs | 98 +- compiler/rustc_lint/src/levels.rs | 117 +- compiler/rustc_lint/src/lib.rs | 12 +- compiler/rustc_lint/src/non_fmt_panic.rs | 27 +- compiler/rustc_lint/src/tests.rs | 26 + compiler/rustc_lint/src/traits.rs | 63 +- compiler/rustc_lint/src/unused.rs | 1 + compiler/rustc_lint_defs/Cargo.toml | 1 - compiler/rustc_lint_defs/src/builtin.rs | 216 +- compiler/rustc_lint_defs/src/lib.rs | 54 +- compiler/rustc_llvm/Cargo.toml | 2 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 7 +- compiler/rustc_macros/src/hash_stable.rs | 4 +- compiler/rustc_macros/src/query.rs | 2 +- compiler/rustc_macros/src/symbols.rs | 2 +- compiler/rustc_metadata/Cargo.toml | 1 - compiler/rustc_metadata/src/creader.rs | 78 +- .../rustc_metadata/src/dependency_format.rs | 26 +- compiler/rustc_metadata/src/dynamic_lib.rs | 7 +- compiler/rustc_metadata/src/locator.rs | 12 +- compiler/rustc_metadata/src/native_libs.rs | 72 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 164 +- .../src/rmeta/decoder/cstore_impl.rs | 48 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 78 +- compiler/rustc_metadata/src/rmeta/mod.rs | 11 +- compiler/rustc_middle/Cargo.toml | 1 - compiler/rustc_middle/src/hir/map/mod.rs | 79 +- compiler/rustc_middle/src/hir/mod.rs | 2 +- compiler/rustc_middle/src/ich/hcx.rs | 22 +- compiler/rustc_middle/src/ich/impls_hir.rs | 41 - compiler/rustc_middle/src/lib.rs | 3 +- compiler/rustc_middle/src/lint.rs | 171 +- .../src/middle/codegen_fn_attrs.rs | 4 + compiler/rustc_middle/src/middle/cstore.rs | 115 +- .../src/middle/exported_symbols.rs | 4 +- compiler/rustc_middle/src/middle/limits.rs | 48 +- compiler/rustc_middle/src/middle/mod.rs | 4 + compiler/rustc_middle/src/middle/stability.rs | 9 +- .../rustc_middle/src/mir/abstract_const.rs | 5 +- .../src/mir/interpret/allocation.rs | 159 +- .../rustc_middle/src/mir/interpret/error.rs | 93 +- .../rustc_middle/src/mir/interpret/mod.rs | 13 +- .../rustc_middle/src/mir/interpret/pointer.rs | 171 +- .../rustc_middle/src/mir/interpret/value.rs | 255 +- compiler/rustc_middle/src/mir/mod.rs | 10 +- compiler/rustc_middle/src/mir/mono.rs | 18 +- compiler/rustc_middle/src/query/mod.rs | 71 +- compiler/rustc_middle/src/thir.rs | 178 +- compiler/rustc_middle/src/traits/mod.rs | 50 +- compiler/rustc_middle/src/ty/assoc.rs | 2 +- compiler/rustc_middle/src/ty/closure.rs | 7 +- compiler/rustc_middle/src/ty/consts/int.rs | 11 +- compiler/rustc_middle/src/ty/consts/kind.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 268 +- compiler/rustc_middle/src/ty/fold.rs | 82 - compiler/rustc_middle/src/ty/instance.rs | 52 +- compiler/rustc_middle/src/ty/layout.rs | 23 +- compiler/rustc_middle/src/ty/list.rs | 12 +- compiler/rustc_middle/src/ty/mod.rs | 41 +- .../src/ty/normalize_erasing_regions.rs | 17 +- compiler/rustc_middle/src/ty/print/pretty.rs | 177 +- .../src/ty/{query/mod.rs => query.rs} | 29 +- compiler/rustc_middle/src/ty/relate.rs | 7 +- compiler/rustc_middle/src/ty/sty.rs | 18 +- compiler/rustc_middle/src/ty/trait_def.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 18 +- compiler/rustc_middle/src/ty/vtable.rs | 107 + .../diagnostics/conflict_errors.rs | 128 +- .../diagnostics/explain_borrow.rs | 26 +- .../diagnostics/mutability_errors.rs | 24 +- .../borrow_check/diagnostics/region_errors.rs | 10 +- .../src/borrow_check/member_constraints.rs | 5 - .../src/borrow_check/region_infer/mod.rs | 36 +- .../borrow_check/region_infer/opaque_types.rs | 47 +- .../borrow_check/type_check/input_output.rs | 2 - .../src/borrow_check/type_check/mod.rs | 239 +- compiler/rustc_mir/src/const_eval/error.rs | 15 +- .../rustc_mir/src/const_eval/eval_queries.rs | 67 +- compiler/rustc_mir/src/const_eval/machine.rs | 43 +- compiler/rustc_mir/src/const_eval/mod.rs | 6 +- compiler/rustc_mir/src/dataflow/mod.rs | 2 +- compiler/rustc_mir/src/interpret/cast.rs | 8 +- .../rustc_mir/src/interpret/eval_context.rs | 122 +- compiler/rustc_mir/src/interpret/intern.rs | 35 +- .../rustc_mir/src/interpret/intrinsics.rs | 70 +- .../interpret/intrinsics/caller_location.rs | 6 +- compiler/rustc_mir/src/interpret/machine.rs | 139 +- compiler/rustc_mir/src/interpret/memory.rs | 445 +- compiler/rustc_mir/src/interpret/operand.rs | 133 +- compiler/rustc_mir/src/interpret/operator.rs | 6 +- compiler/rustc_mir/src/interpret/place.rs | 229 +- compiler/rustc_mir/src/interpret/step.rs | 13 +- .../rustc_mir/src/interpret/terminator.rs | 26 +- compiler/rustc_mir/src/interpret/traits.rs | 142 +- compiler/rustc_mir/src/interpret/validity.rs | 79 +- compiler/rustc_mir/src/interpret/visitor.rs | 6 +- compiler/rustc_mir/src/lib.rs | 1 + .../rustc_mir/src/monomorphize/collector.rs | 58 +- compiler/rustc_mir/src/monomorphize/mod.rs | 1 + compiler/rustc_mir/src/monomorphize/util.rs | 73 + .../src/transform/add_call_guards.rs | 4 +- .../src/transform/check_consts/ops.rs | 25 +- .../src/transform/check_consts/validation.rs | 40 +- .../rustc_mir/src/transform/check_unsafety.rs | 31 +- .../rustc_mir/src/transform/const_prop.rs | 64 +- .../rustc_mir/src/transform/coverage/spans.rs | 7 +- .../rustc_mir/src/transform/coverage/tests.rs | 4 +- compiler/rustc_mir/src/transform/inline.rs | 7 +- .../rustc_mir/src/transform/inline/cycle.rs | 18 +- .../src/transform/lower_slice_len.rs | 100 + compiler/rustc_mir/src/transform/mod.rs | 2 + .../transform/simplify_comparison_integral.rs | 4 +- .../transform/uninhabited_enum_branching.rs | 12 +- compiler/rustc_mir/src/util/pretty.rs | 93 +- compiler/rustc_mir_build/src/build/block.rs | 23 +- .../src/build/expr/as_place.rs | 15 +- .../rustc_mir_build/src/build/expr/into.rs | 9 +- .../rustc_mir_build/src/build/expr/mod.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 13 +- .../rustc_mir_build/src/check_unsafety.rs | 304 +- compiler/rustc_mir_build/src/thir/constant.rs | 18 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 9 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 22 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 6 - .../src/thir/pattern/check_match.rs | 12 +- .../src/thir/pattern/const_to_pat.rs | 51 +- .../src/thir/pattern/deconstruct_pat.rs | 2 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 23 +- compiler/rustc_mir_build/src/thir/visit.rs | 72 +- compiler/rustc_parse/Cargo.toml | 1 - compiler/rustc_parse/src/lexer/mod.rs | 50 +- .../rustc_parse/src/lexer/unicode_chars.rs | 2 +- compiler/rustc_parse/src/parser/attr.rs | 9 +- compiler/rustc_parse/src/parser/expr.rs | 22 +- compiler/rustc_parse/src/parser/item.rs | 14 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- .../rustc_parse/src/parser/nonterminal.rs | 4 +- compiler/rustc_parse/src/parser/pat.rs | 119 +- compiler/rustc_parse/src/parser/ty.rs | 22 +- compiler/rustc_parse_format/src/tests.rs | 3 +- compiler/rustc_passes/Cargo.toml | 1 - compiler/rustc_passes/src/check_attr.rs | 101 +- compiler/rustc_passes/src/check_const.rs | 70 + compiler/rustc_passes/src/dead.rs | 54 + compiler/rustc_passes/src/diagnostic_items.rs | 2 +- compiler/rustc_passes/src/entry.rs | 45 +- compiler/rustc_passes/src/lang_items.rs | 5 +- compiler/rustc_passes/src/lib.rs | 1 + compiler/rustc_passes/src/stability.rs | 66 +- compiler/rustc_passes/src/weak_lang_items.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 3 +- compiler/rustc_query_impl/Cargo.toml | 5 +- compiler/rustc_query_impl/src/keys.rs | 194 +- compiler/rustc_query_impl/src/lib.rs | 11 +- .../src}/on_disk_cache.rs | 304 +- compiler/rustc_query_impl/src/plumbing.rs | 93 +- compiler/rustc_query_impl/src/stats.rs | 2 +- .../rustc_query_system/src/dep_graph/graph.rs | 28 +- .../rustc_query_system/src/query/config.rs | 10 +- .../rustc_query_system/src/query/plumbing.rs | 78 +- .../rustc_resolve/src/build_reduced_graph.rs | 43 +- compiler/rustc_resolve/src/def_collector.rs | 10 +- compiler/rustc_resolve/src/diagnostics.rs | 6 +- compiler/rustc_resolve/src/imports.rs | 15 +- .../rustc_resolve/src/late/diagnostics.rs | 2 + compiler/rustc_resolve/src/lib.rs | 121 +- compiler/rustc_resolve/src/macros.rs | 113 +- .../rustc_save_analysis/src/dump_visitor.rs | 7 +- compiler/rustc_save_analysis/src/lib.rs | 11 +- compiler/rustc_serialize/src/json.rs | 9 + compiler/rustc_serialize/tests/json.rs | 2 +- compiler/rustc_session/Cargo.toml | 1 - compiler/rustc_session/src/config.rs | 144 +- compiler/rustc_session/src/lib.rs | 5 + compiler/rustc_session/src/options.rs | 36 +- compiler/rustc_session/src/parse.rs | 3 + compiler/rustc_session/src/session.rs | 149 +- compiler/rustc_span/Cargo.toml | 4 +- .../rustc_span/src/crate_disambiguator.rs | 35 - compiler/rustc_span/src/def_id.rs | 84 +- compiler/rustc_span/src/hygiene.rs | 709 +-- compiler/rustc_span/src/lev_distance/tests.rs | 4 +- compiler/rustc_span/src/lib.rs | 161 +- compiler/rustc_span/src/source_map.rs | 10 +- compiler/rustc_span/src/span_encoding.rs | 3 +- compiler/rustc_span/src/symbol.rs | 48 +- compiler/rustc_span/src/symbol/tests.rs | 4 +- compiler/rustc_span/src/tests.rs | 21 +- compiler/rustc_symbol_mangling/Cargo.toml | 1 - compiler/rustc_symbol_mangling/src/legacy.rs | 5 +- compiler/rustc_symbol_mangling/src/lib.rs | 8 +- compiler/rustc_symbol_mangling/src/v0.rs | 14 +- compiler/rustc_target/src/abi/call/msp430.rs | 2 +- compiler/rustc_target/src/abi/call/nvptx.rs | 2 +- compiler/rustc_target/src/abi/call/nvptx64.rs | 2 +- compiler/rustc_target/src/abi/call/x86.rs | 2 +- compiler/rustc_target/src/abi/call/x86_64.rs | 2 +- compiler/rustc_target/src/abi/mod.rs | 6 +- compiler/rustc_target/src/asm/aarch64.rs | 86 +- compiler/rustc_target/src/asm/mod.rs | 6 + compiler/rustc_target/src/asm/riscv.rs | 34 + compiler/rustc_target/src/asm/x86.rs | 26 +- compiler/rustc_target/src/lib.rs | 3 + .../src/spec/aarch64_apple_darwin.rs | 8 +- .../src/spec/aarch64_apple_ios.rs | 7 +- .../src/spec/aarch64_apple_ios_macabi.rs | 7 +- .../src/spec/aarch64_apple_ios_sim.rs | 4 +- .../src/spec/aarch64_apple_tvos.rs | 7 +- .../src/spec/aarch64_be_unknown_linux_gnu.rs | 7 +- .../aarch64_be_unknown_linux_gnu_ilp32.rs | 2 +- .../rustc_target/src/spec/aarch64_fuchsia.rs | 10 +- .../src/spec/aarch64_linux_android.rs | 15 +- .../src/spec/aarch64_unknown_freebsd.rs | 5 +- .../src/spec/aarch64_unknown_linux_gnu.rs | 17 +- .../spec/aarch64_unknown_linux_gnu_ilp32.rs | 8 +- .../src/spec/aarch64_unknown_linux_musl.rs | 6 +- .../src/spec/aarch64_unknown_netbsd.rs | 10 +- .../src/spec/aarch64_unknown_none.rs | 1 - .../spec/aarch64_unknown_none_softfloat.rs | 2 +- .../src/spec/aarch64_unknown_openbsd.rs | 8 +- .../src/spec/aarch64_wrs_vxworks.rs | 5 +- compiler/rustc_target/src/spec/abi.rs | 83 +- compiler/rustc_target/src/spec/apple_base.rs | 4 +- .../rustc_target/src/spec/apple_sdk_base.rs | 10 + compiler/rustc_target/src/spec/arm_base.rs | 15 - .../src/spec/arm_linux_androideabi.rs | 13 +- .../src/spec/arm_unknown_linux_gnueabi.rs | 8 +- .../src/spec/arm_unknown_linux_gnueabihf.rs | 8 +- .../src/spec/arm_unknown_linux_musleabi.rs | 14 +- .../src/spec/arm_unknown_linux_musleabihf.rs | 14 +- .../src/spec/armebv7r_none_eabi.rs | 3 +- .../src/spec/armebv7r_none_eabihf.rs | 3 +- .../src/spec/armv4t_unknown_linux_gnueabi.rs | 6 +- .../src/spec/armv5te_unknown_linux_gnueabi.rs | 6 +- .../spec/armv5te_unknown_linux_musleabi.rs | 7 +- .../spec/armv5te_unknown_linux_uclibceabi.rs | 3 +- .../src/spec/armv6_unknown_freebsd.rs | 7 +- .../src/spec/armv6_unknown_netbsd_eabihf.rs | 9 +- .../rustc_target/src/spec/armv7_apple_ios.rs | 4 +- .../src/spec/armv7_linux_androideabi.rs | 10 +- .../src/spec/armv7_unknown_freebsd.rs | 7 +- .../src/spec/armv7_unknown_linux_gnueabi.rs | 6 +- .../src/spec/armv7_unknown_linux_gnueabihf.rs | 6 +- .../src/spec/armv7_unknown_linux_musleabi.rs | 5 +- .../spec/armv7_unknown_linux_musleabihf.rs | 5 +- .../src/spec/armv7_unknown_netbsd_eabihf.rs | 7 +- .../src/spec/armv7_wrs_vxworks_eabihf.rs | 5 +- .../rustc_target/src/spec/armv7a_none_eabi.rs | 2 +- .../src/spec/armv7a_none_eabihf.rs | 2 +- .../rustc_target/src/spec/armv7r_none_eabi.rs | 2 +- .../src/spec/armv7r_none_eabihf.rs | 2 +- .../rustc_target/src/spec/armv7s_apple_ios.rs | 4 +- compiler/rustc_target/src/spec/bpf_base.rs | 18 +- .../rustc_target/src/spec/freebsd_base.rs | 4 +- .../src/spec/i686_apple_darwin.rs | 4 +- .../src/spec/i686_linux_android.rs | 2 +- .../src/spec/i686_pc_windows_gnu.rs | 4 +- .../src/spec/i686_unknown_linux_musl.rs | 4 +- .../src/spec/i686_uwp_windows_gnu.rs | 4 +- .../rustc_target/src/spec/illumos_base.rs | 4 +- .../src/spec/linux_kernel_base.rs | 5 +- .../src/spec/mips64_unknown_linux_gnuabi64.rs | 1 + .../spec/mips64_unknown_linux_muslabi64.rs | 7 +- .../spec/mips64el_unknown_linux_gnuabi64.rs | 1 + .../spec/mips64el_unknown_linux_muslabi64.rs | 2 +- .../src/spec/mipsel_unknown_none.rs | 11 - .../mipsisa64r6_unknown_linux_gnuabi64.rs | 1 + .../mipsisa64r6el_unknown_linux_gnuabi64.rs | 1 + compiler/rustc_target/src/spec/mod.rs | 422 +- .../src/spec/nvptx64_nvidia_cuda.rs | 20 - .../rustc_target/src/spec/openbsd_base.rs | 4 +- .../src/spec/powerpc64le_unknown_freebsd.rs | 16 + .../src/spec/powerpc_unknown_linux_gnuspe.rs | 7 +- .../src/spec/powerpc_wrs_vxworks_spe.rs | 1 + .../src/spec/riscv32gc_unknown_linux_gnu.rs | 1 - .../src/spec/riscv32gc_unknown_linux_musl.rs | 1 - .../src/spec/riscv32i_unknown_none_elf.rs | 1 - .../src/spec/riscv32imac_unknown_none_elf.rs | 1 - .../src/spec/riscv32imc_unknown_none_elf.rs | 1 - .../src/spec/riscv64gc_unknown_linux_gnu.rs | 1 - .../src/spec/riscv64gc_unknown_linux_musl.rs | 1 - .../src/spec/riscv64gc_unknown_none_elf.rs | 1 - .../src/spec/riscv64imac_unknown_none_elf.rs | 1 - compiler/rustc_target/src/spec/riscv_base.rs | 22 - .../rustc_target/src/spec/tests/tests_impl.rs | 2 +- compiler/rustc_target/src/spec/thumb_base.rs | 6 +- .../src/spec/thumbv4t_none_eabi.rs | 1 + .../src/spec/thumbv6m_none_eabi.rs | 1 + .../src/spec/thumbv7a_pc_windows_msvc.rs | 10 +- .../src/spec/thumbv7a_uwp_windows_msvc.rs | 16 +- .../src/spec/thumbv7em_none_eabi.rs | 6 +- .../src/spec/thumbv7em_none_eabihf.rs | 1 + .../src/spec/thumbv7m_none_eabi.rs | 6 +- .../src/spec/thumbv7neon_linux_androideabi.rs | 10 +- .../thumbv7neon_unknown_linux_gnueabihf.rs | 6 +- .../thumbv7neon_unknown_linux_musleabihf.rs | 5 +- .../src/spec/thumbv8m_base_none_eabi.rs | 1 + .../src/spec/thumbv8m_main_none_eabi.rs | 6 +- .../src/spec/thumbv8m_main_none_eabihf.rs | 1 + .../src/spec/windows_uwp_gnu_base.rs | 1 + .../src/spec/windows_uwp_msvc_base.rs | 1 + .../src/spec/x86_64_apple_darwin.rs | 5 +- .../src/spec/x86_64_fortanix_unknown_sgx.rs | 1 + .../src/spec/x86_64_unknown_linux_gnux32.rs | 1 + .../src/spec/x86_64_unknown_uefi.rs | 8 +- compiler/rustc_target/src/tests.rs | 59 + .../rustc_trait_selection/src/autoderef.rs | 4 +- compiler/rustc_trait_selection/src/infer.rs | 52 +- .../rustc_trait_selection/src/opaque_types.rs | 63 +- .../src/traits/chalk_fulfill.rs | 13 +- .../src/traits/const_evaluatable.rs | 29 +- .../src/traits/error_reporting/mod.rs | 59 +- .../src/traits/error_reporting/suggestions.rs | 94 +- .../src/traits/fulfill.rs | 25 +- .../rustc_trait_selection/src/traits/mod.rs | 154 +- .../src/traits/object_safety.rs | 2 + .../src/traits/project.rs | 376 +- .../src/traits/query/evaluate_obligation.rs | 6 +- .../src/traits/query/normalize.rs | 97 +- .../src/traits/query/type_op/mod.rs | 5 +- .../src/traits/select/confirmation.rs | 19 +- .../src/traits/select/mod.rs | 42 +- .../src/traits/structural_match.rs | 6 +- .../rustc_trait_selection/src/traits/wf.rs | 5 +- compiler/rustc_traits/src/chalk/lowering.rs | 2 +- compiler/rustc_traits/src/dropck_outlives.rs | 2 +- compiler/rustc_traits/src/lib.rs | 1 - compiler/rustc_traits/src/type_op.rs | 3 +- compiler/rustc_ty_utils/src/instance.rs | 109 +- compiler/rustc_ty_utils/src/lib.rs | 1 + compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 22 +- compiler/rustc_typeck/src/astconv/mod.rs | 4 +- compiler/rustc_typeck/src/check/callee.rs | 13 +- compiler/rustc_typeck/src/check/cast.rs | 15 +- compiler/rustc_typeck/src/check/check.rs | 35 +- compiler/rustc_typeck/src/check/coercion.rs | 19 +- .../rustc_typeck/src/check/compare_method.rs | 79 +- compiler/rustc_typeck/src/check/demand.rs | 4 +- compiler/rustc_typeck/src/check/expr.rs | 53 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 82 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 30 +- .../rustc_typeck/src/check/fn_ctxt/mod.rs | 9 +- .../src/check/fn_ctxt/suggestions.rs | 16 +- .../rustc_typeck/src/check/gather_locals.rs | 24 +- compiler/rustc_typeck/src/check/inherited.rs | 21 +- compiler/rustc_typeck/src/check/intrinsic.rs | 74 +- .../rustc_typeck/src/check/method/confirm.rs | 10 +- compiler/rustc_typeck/src/check/method/mod.rs | 49 +- .../src/check/method/prelude2021.rs | 358 ++ .../rustc_typeck/src/check/method/probe.rs | 2 +- .../rustc_typeck/src/check/method/suggest.rs | 24 +- compiler/rustc_typeck/src/check/mod.rs | 221 +- compiler/rustc_typeck/src/check/pat.rs | 17 +- compiler/rustc_typeck/src/check/place_op.rs | 2 +- compiler/rustc_typeck/src/check/upvar.rs | 841 +-- compiler/rustc_typeck/src/check/wfcheck.rs | 126 +- compiler/rustc_typeck/src/check/writeback.rs | 71 +- compiler/rustc_typeck/src/check_unused.rs | 4 +- compiler/rustc_typeck/src/collect.rs | 177 +- compiler/rustc_typeck/src/collect/type_of.rs | 230 +- compiler/rustc_typeck/src/errors.rs | 12 +- compiler/rustc_typeck/src/expr_use_visitor.rs | 62 +- compiler/rustc_typeck/src/hir_wf_check.rs | 185 + compiler/rustc_typeck/src/lib.rs | 2 + config.toml.example | 6 +- git-commit-hash | 2 +- library/alloc/benches/btree/map.rs | 39 +- library/alloc/src/borrow.rs | 1 + library/alloc/src/boxed.rs | 3 - library/alloc/src/collections/binary_heap.rs | 1 - library/alloc/src/collections/btree/fix.rs | 2 +- library/alloc/src/collections/btree/map.rs | 51 +- .../alloc/src/collections/btree/map/entry.rs | 1 + .../alloc/src/collections/btree/navigate.rs | 124 +- library/alloc/src/collections/btree/node.rs | 2 +- library/alloc/src/collections/btree/set.rs | 31 +- library/alloc/src/collections/linked_list.rs | 144 +- .../src/collections/linked_list/tests.rs | 47 + library/alloc/src/collections/mod.rs | 1 + .../alloc/src/collections/vec_deque/iter.rs | 1 + .../src/collections/vec_deque/iter_mut.rs | 1 + .../alloc/src/collections/vec_deque/mod.rs | 1 - library/alloc/src/lib.rs | 8 +- library/alloc/src/macros.rs | 2 - library/alloc/src/raw_vec.rs | 1 - library/alloc/src/rc.rs | 6 + library/alloc/src/slice.rs | 2 +- library/alloc/src/str.rs | 2 +- library/alloc/src/string.rs | 35 +- library/alloc/src/sync.rs | 26 + library/alloc/src/vec/into_iter.rs | 1 + library/alloc/src/vec/mod.rs | 22 +- library/alloc/src/vec/source_iter_marker.rs | 4 + library/alloc/src/vec/spec_extend.rs | 2 + library/alloc/tests/str.rs | 10 +- library/alloc/tests/vec.rs | 10 +- library/core/benches/iter.rs | 2 +- library/core/src/alloc/global.rs | 67 +- library/core/src/alloc/layout.rs | 19 +- library/core/src/any.rs | 1 + library/core/src/array/equality.rs | 160 + library/core/src/array/mod.rs | 130 +- library/core/src/bool.rs | 2 +- library/core/src/cell.rs | 16 +- library/core/src/char/methods.rs | 10 +- library/core/src/char/mod.rs | 8 +- library/core/src/clone.rs | 2 +- library/core/src/cmp.rs | 91 +- library/core/src/convert/mod.rs | 2 + library/core/src/convert/num.rs | 2 +- library/core/src/fmt/float.rs | 9 +- library/core/src/fmt/mod.rs | 29 +- library/core/src/fmt/nofloat.rs | 15 + library/core/src/fmt/num.rs | 10 +- library/core/src/hash/mod.rs | 47 + library/core/src/intrinsics.rs | 199 +- library/core/src/iter/adapters/cloned.rs | 1 + library/core/src/iter/adapters/copied.rs | 1 + library/core/src/iter/adapters/enumerate.rs | 1 + library/core/src/iter/adapters/flatten.rs | 94 +- library/core/src/iter/adapters/fuse.rs | 255 +- library/core/src/iter/adapters/map.rs | 1 + library/core/src/iter/adapters/mod.rs | 2 +- library/core/src/iter/adapters/peekable.rs | 23 - library/core/src/iter/adapters/zip.rs | 13 +- library/core/src/iter/range.rs | 3 +- library/core/src/iter/sources/repeat.rs | 1 + library/core/src/iter/traits/accum.rs | 18 +- library/core/src/iter/traits/collect.rs | 2 + library/core/src/iter/traits/double_ended.rs | 10 +- library/core/src/iter/traits/exact_size.rs | 1 - library/core/src/iter/traits/iterator.rs | 104 +- library/core/src/lib.rs | 44 +- library/core/src/macros/mod.rs | 41 +- library/core/src/marker.rs | 1 - library/core/src/mem/maybe_uninit.rs | 156 +- library/core/src/mem/mod.rs | 12 +- library/core/src/num/dec2flt/algorithm.rs | 429 -- library/core/src/num/dec2flt/common.rs | 198 + library/core/src/num/dec2flt/decimal.rs | 351 ++ library/core/src/num/dec2flt/float.rs | 207 + library/core/src/num/dec2flt/fpu.rs | 89 + library/core/src/num/dec2flt/lemire.rs | 166 + library/core/src/num/dec2flt/mod.rs | 220 +- library/core/src/num/dec2flt/num.rs | 81 - library/core/src/num/dec2flt/number.rs | 86 + library/core/src/num/dec2flt/parse.rs | 304 +- library/core/src/num/dec2flt/rawfp.rs | 363 -- library/core/src/num/dec2flt/slow.rs | 109 + library/core/src/num/dec2flt/table.rs | 1937 +++---- library/core/src/num/error.rs | 23 +- library/core/src/num/flt2dec/decoder.rs | 2 +- library/core/src/num/flt2dec/mod.rs | 104 +- library/core/src/num/fmt.rs | 108 + library/core/src/num/int_log10.rs | 134 + library/core/src/num/int_macros.rs | 197 +- library/core/src/num/mod.rs | 18 +- library/core/src/num/nonzero.rs | 573 ++- library/core/src/num/uint_macros.rs | 193 +- library/core/src/ops/control_flow.rs | 54 +- library/core/src/ops/drop.rs | 2 +- library/core/src/ops/mod.rs | 11 - library/core/src/ops/range.rs | 3 +- library/core/src/ops/try.rs | 61 - library/core/src/ops/try_trait.rs | 13 +- library/core/src/option.rs | 383 +- library/core/src/prelude/mod.rs | 16 +- library/core/src/prelude/v1.rs | 22 +- library/core/src/ptr/metadata.rs | 2 +- library/core/src/ptr/mod.rs | 12 +- library/core/src/ptr/mut_ptr.rs | 5 +- library/core/src/ptr/non_null.rs | 2 +- library/core/src/raw.rs | 90 - library/core/src/result.rs | 266 +- library/core/src/slice/iter.rs | 26 +- library/core/src/slice/mod.rs | 24 +- library/core/src/slice/rotate.rs | 56 +- library/core/src/slice/sort.rs | 2 +- library/core/src/str/converts.rs | 2 +- library/core/src/str/error.rs | 5 +- library/core/src/str/iter.rs | 1 + library/core/src/str/mod.rs | 1 - library/core/src/str/traits.rs | 2 +- library/core/src/sync/atomic.rs | 8 +- library/core/src/task/poll.rs | 160 +- library/core/src/time.rs | 153 +- library/core/src/unicode/mod.rs | 2 +- library/core/src/unicode/printable.py | 2 +- library/core/tests/const_ptr.rs | 50 + library/core/tests/hash/mod.rs | 9 +- library/core/tests/iter/adapters/flatten.rs | 40 + library/core/tests/iter/adapters/zip.rs | 27 + library/core/tests/lib.rs | 7 +- library/core/tests/manually_drop.rs | 8 + library/core/tests/mem.rs | 22 - library/core/tests/num/dec2flt/float.rs | 33 + library/core/tests/num/dec2flt/lemire.rs | 53 + library/core/tests/num/dec2flt/mod.rs | 17 +- library/core/tests/num/dec2flt/parse.rs | 162 +- library/core/tests/num/dec2flt/rawfp.rs | 172 - library/core/tests/num/flt2dec/mod.rs | 3 +- library/core/tests/num/int_log.rs | 153 + library/core/tests/num/mod.rs | 1 + library/core/tests/result.rs | 1 - library/panic_unwind/src/dwarf/eh.rs | 8 +- library/panic_unwind/src/gcc.rs | 8 +- library/panic_unwind/src/lib.rs | 1 - library/panic_unwind/src/seh.rs | 4 +- library/proc_macro/src/bridge/buffer.rs | 29 - library/proc_macro/src/bridge/mod.rs | 1 + library/proc_macro/src/bridge/rpc.rs | 2 +- library/proc_macro/src/lib.rs | 41 +- library/profiler_builtins/Cargo.toml | 2 +- library/std/src/backtrace.rs | 5 +- library/std/src/collections/hash/map.rs | 4 +- library/std/src/collections/hash/set.rs | 3 +- library/std/src/env.rs | 4 +- library/std/src/error.rs | 3 + library/std/src/f32.rs | 40 +- library/std/src/f32/tests.rs | 63 + library/std/src/f64.rs | 40 +- library/std/src/f64/tests.rs | 55 + library/std/src/ffi/mod.rs | 4 +- library/std/src/ffi/os_str.rs | 1 - library/std/src/fs.rs | 51 +- library/std/src/fs/tests.rs | 21 +- library/std/src/io/buffered/bufreader.rs | 8 +- library/std/src/io/buffered/bufwriter.rs | 24 +- library/std/src/io/buffered/mod.rs | 6 +- library/std/src/io/cursor.rs | 63 +- library/std/src/io/error.rs | 185 +- library/std/src/io/mod.rs | 194 +- library/std/src/io/stdio.rs | 262 +- library/std/src/io/stdio/tests.rs | 119 + library/std/src/io/tests.rs | 70 +- library/std/src/io/util.rs | 27 +- library/std/src/keyword_docs.rs | 12 +- library/std/src/lib.rs | 26 +- library/std/src/macros.rs | 3 +- library/std/src/net/ip.rs | 43 +- library/std/src/net/ip/tests.rs | 12 +- library/std/src/net/tcp/tests.rs | 2 +- library/std/src/num.rs | 7 +- library/std/src/os/fortanix_sgx/arch.rs | 12 +- library/std/src/os/fortanix_sgx/ffi.rs | 5 +- library/std/src/os/hermit/ffi.rs | 5 +- .../std/src/os/unix/{ffi.rs => ffi/mod.rs} | 4 +- library/std/src/os/unix/ffi/os_str.rs | 68 + library/std/src/os/unix/fs.rs | 39 + library/std/src/os/unix/net/ancillary.rs | 110 +- library/std/src/os/unix/process.rs | 2 +- library/std/src/os/wasi/ffi.rs | 5 +- library/std/src/os/wasi/fs.rs | 5 +- library/std/src/os/wasi/io.rs | 2 +- library/std/src/os/windows/process.rs | 13 + library/std/src/panic.rs | 4 +- library/std/src/path.rs | 28 +- library/std/src/prelude/mod.rs | 32 +- library/std/src/prelude/v1.rs | 24 +- library/std/src/primitive_docs.rs | 4 +- library/std/src/process.rs | 17 +- library/std/src/process/tests.rs | 9 + library/std/src/rt.rs | 37 +- library/std/src/sync/mpsc/mod.rs | 53 +- library/std/src/sync/mpsc/mpsc_queue.rs | 4 +- library/std/src/sync/mpsc/spsc_queue.rs | 2 +- library/std/src/sync/mutex.rs | 40 +- library/std/src/sync/rwlock.rs | 14 +- library/std/src/sys/hermit/args.rs | 2 +- library/std/src/sys/hermit/fs.rs | 2 +- library/std/src/sys/hermit/mod.rs | 2 +- library/std/src/sys/hermit/mutex.rs | 2 +- library/std/src/sys/hermit/net.rs | 51 +- library/std/src/sys/hermit/os.rs | 2 +- library/std/src/sys/hermit/stdio.rs | 8 +- library/std/src/sys/hermit/thread.rs | 8 +- library/std/src/sys/sgx/abi/mem.rs | 4 +- library/std/src/sys/sgx/mod.rs | 6 +- library/std/src/sys/sgx/net.rs | 2 +- library/std/src/sys/sgx/stdio.rs | 2 +- library/std/src/sys/sgx/thread.rs | 6 + library/std/src/sys/unix/android.rs | 2 +- library/std/src/sys/unix/args.rs | 38 +- library/std/src/sys/unix/fs.rs | 56 +- library/std/src/sys/unix/kernel_copy.rs | 1 + library/std/src/sys/unix/mod.rs | 101 +- library/std/src/sys/unix/net.rs | 4 +- library/std/src/sys/unix/os.rs | 16 +- .../std/src/sys/unix/process/process_unix.rs | 8 + library/std/src/sys/unix/rand.rs | 4 + library/std/src/sys/unix/thread.rs | 85 + library/std/src/sys/unix/weak.rs | 13 +- library/std/src/sys/unsupported/common.rs | 2 +- library/std/src/sys/unsupported/thread.rs | 5 + library/std/src/sys/wasi/fs.rs | 5 +- library/std/src/sys/wasi/mod.rs | 4 +- library/std/src/sys/wasi/thread.rs | 5 + library/std/src/sys/wasm/atomics/thread.rs | 5 + library/std/src/sys/windows/c.rs | 84 +- library/std/src/sys/windows/c/errors.rs | 1883 +++++++ library/std/src/sys/windows/fs.rs | 7 +- library/std/src/sys/windows/mod.rs | 64 +- library/std/src/sys/windows/net.rs | 305 +- library/std/src/sys/windows/process.rs | 195 +- library/std/src/sys/windows/process/tests.rs | 89 +- library/std/src/sys/windows/thread.rs | 16 + .../std/src/sys/windows/thread_local_key.rs | 2 +- library/std/src/sys_common/bytestring.rs | 26 - .../std/src/sys_common/bytestring/tests.rs | 19 - library/std/src/sys_common/mod.rs | 1 - library/std/src/sys_common/os_str_bytes.rs | 97 +- .../std/src/sys_common/os_str_bytes/tests.rs | 10 + library/std/src/sys_common/process.rs | 10 +- library/std/src/sys_common/wtf8.rs | 3 +- library/std/src/sys_common/wtf8/tests.rs | 18 +- .../std/src/thread/available_concurrency.rs | 156 - library/std/src/thread/local.rs | 7 +- library/std/src/thread/local/tests.rs | 2 +- library/std/src/thread/mod.rs | 73 +- library/std/src/time.rs | 2 +- .../stdarch/crates/core_arch/src/x86/bt.rs | 8 +- .../stdarch/crates/core_arch/src/x86_64/bt.rs | 8 +- library/term/Cargo.toml | 9 - library/term/src/lib.rs | 194 - library/test/Cargo.toml | 1 - library/test/src/console.rs | 2 +- library/test/src/formatters/junit.rs | 8 +- library/test/src/formatters/pretty.rs | 1 + library/test/src/formatters/terse.rs | 1 + library/test/src/lib.rs | 3 +- library/test/src/stats.rs | 2 +- library/test/src/term.rs | 85 + .../src => test/src/term}/terminfo/mod.rs | 97 +- .../src => test/src/term}/terminfo/parm.rs | 43 +- .../src/term}/terminfo/parm/tests.rs | 22 +- .../src/term}/terminfo/parser/compiled.rs | 16 +- .../term}/terminfo/parser/compiled/tests.rs | 0 .../src/term}/terminfo/searcher.rs | 2 +- .../src/term}/terminfo/searcher/tests.rs | 0 library/{term/src => test/src/term}/win.rs | 58 +- library/test/src/tests.rs | 38 - library/test/src/types.rs | 8 - library/unwind/Cargo.toml | 2 +- src/bootstrap/Cargo.toml | 5 +- src/bootstrap/bootstrap.py | 62 +- src/bootstrap/builder.rs | 30 +- src/bootstrap/builder/tests.rs | 5 + src/bootstrap/check.rs | 4 +- src/bootstrap/compile.rs | 8 +- src/bootstrap/config.rs | 23 +- src/bootstrap/configure.py | 3 + src/bootstrap/dist.rs | 24 +- src/bootstrap/doc.rs | 206 +- src/bootstrap/flags.rs | 9 +- src/bootstrap/job.rs | 20 +- src/bootstrap/lib.rs | 111 +- src/bootstrap/native.rs | 5 +- src/bootstrap/test.rs | 118 +- src/bootstrap/tool.rs | 11 +- src/build_helper/lib.rs | 1 + src/ci/cpu-usage-over-time.py | 7 +- .../docker/host-x86_64/armhf-gnu/Dockerfile | 2 +- .../dist-x86_64-dragonfly/build-toolchain.sh | 2 +- .../dist-arm-linux/arm-linux-gnueabi.config | 2 +- .../arm-linux-gnueabihf.config | 2 +- .../armv7-linux-gnueabihf.config | 4 +- .../host-x86_64/dist-i686-linux/Dockerfile | 4 +- .../riscv64-unknown-linux-gnu.config | 5 +- .../host-x86_64/dist-various-2/Dockerfile | 2 +- ...d-x86_64-fortanix-unknown-sgx-toolchain.sh | 2 +- .../host-x86_64/dist-x86_64-linux/Dockerfile | 4 +- .../dist-x86_64-linux/build-binutils.sh | 10 +- .../dist-x86_64-linux/build-clang.sh | 4 +- .../dist-x86_64-linux/build-cmake.sh | 2 +- .../dist-x86_64-linux/build-curl.sh | 2 +- .../dist-x86_64-linux/build-gcc.sh | 3 +- .../dist-x86_64-linux/build-openssl.sh | 2 +- .../dist-x86_64-linux/build-python.sh | 2 +- .../docker/host-x86_64/mingw-check/Dockerfile | 4 +- .../host-x86_64/x86_64-gnu-aux/Dockerfile | 3 +- .../host-x86_64/x86_64-gnu-tools/Dockerfile | 3 +- src/ci/github-actions/ci.yml | 4 + src/ci/pgo.sh | 10 +- src/ci/scripts/collect-cpu-stats.sh | 2 +- src/ci/scripts/should-skip-this.sh | 62 +- src/ci/shared.sh | 2 +- src/doc/book/ferris.js | 4 - .../listing-02-02/Cargo.toml | 1 - .../no-listing-01-cargo-new/Cargo.toml | 1 - .../listing-04-09/src/main.rs | 9 +- .../src/main.rs | 2 +- .../listing-14-03/src/lib.rs | 4 +- .../add/adder/Cargo.toml | 1 - .../add/add-one/Cargo.toml | 1 - .../add/adder/Cargo.toml | 1 - .../add/add-one/Cargo.toml | 1 - .../listing-19-14/src/main.rs | 2 +- .../listing-19-31/hello_macro/Cargo.toml | 1 - .../hello_macro/hello_macro_derive/Cargo.toml | 1 - .../pancakes/Cargo.toml | 1 - src/doc/book/nostarch/chapter02.md | 1008 ++++ src/doc/book/src/appendix-02-operators.md | 8 +- src/doc/book/src/appendix-06-translation.md | 3 + src/doc/book/src/ch00-00-introduction.md | 11 +- src/doc/book/src/ch01-01-installation.md | 22 +- src/doc/book/src/ch01-02-hello-world.md | 3 +- src/doc/book/src/ch01-03-hello-cargo.md | 13 +- .../src/ch02-00-guessing-game-tutorial.md | 80 +- src/doc/book/src/ch03-02-data-types.md | 12 +- src/doc/book/src/ch04-03-slices.md | 19 +- src/doc/book/src/ch06-01-defining-an-enum.md | 4 +- .../book/src/ch07-01-packages-and-crates.md | 4 +- ...g-paths-into-scope-with-the-use-keyword.md | 9 +- src/doc/book/src/ch08-02-strings.md | 3 +- src/doc/book/src/ch08-03-hash-maps.md | 8 +- src/doc/book/src/ch10-02-traits.md | 7 +- src/doc/book/src/ch11-03-test-organization.md | 10 +- ...2-04-testing-the-librarys-functionality.md | 6 +- ...2-05-working-with-environment-variables.md | 2 +- src/doc/book/src/ch13-04-performance.md | 6 +- .../src/ch14-02-publishing-to-crates-io.md | 6 +- src/doc/book/src/ch15-02-deref.md | 2 +- src/doc/book/src/ch15-04-rc.md | 6 +- src/doc/book/src/ch17-02-trait-objects.md | 4 +- src/doc/book/src/ch19-01-unsafe-rust.md | 21 +- src/doc/book/src/ch19-03-advanced-traits.md | 10 +- src/doc/book/src/ch19-04-advanced-types.md | 11 +- src/doc/book/src/ch19-06-macros.md | 4 +- src/doc/book/src/ch20-02-multithreaded.md | 10 +- src/doc/book/src/img/ferris/unsafe.svg | 291 -- src/doc/book/tools/src/bin/convert_quotes.rs | 2 +- src/doc/book/tools/src/bin/link2print.rs | 28 +- .../book/tools/src/bin/remove_hidden_lines.rs | 2 +- src/doc/book/tools/src/bin/remove_links.rs | 2 +- src/doc/book/tools/src/bin/remove_markup.rs | 10 +- src/doc/edition-guide/src/SUMMARY.md | 1 + .../src/editions/advanced-migrations.md | 210 + ...ng-an-existing-project-to-a-new-edition.md | 138 +- .../src/rust-2021/IntoIterator-for-arrays.md | 67 +- .../src/rust-2021/default-cargo-resolver.md | 157 +- .../rust-2021/disjoint-capture-in-closures.md | 149 +- .../src/rust-2021/or-patterns-macro-rules.md | 62 +- .../src/rust-2021/panic-macro-consistency.md | 46 +- .../edition-guide/src/rust-2021/prelude.md | 143 +- .../src/rust-2021/reserving-syntax.md | 7 +- .../rust-2021/warnings-promoted-to-error.md | 50 +- src/doc/edition-guide/triagebot.toml | 4 + .../embedded-book/src/collections/index.md | 2 +- .../src/interoperability/c-with-rust.md | 8 +- src/doc/embedded-book/src/start/hardware.md | 8 +- src/doc/embedded-book/src/start/qemu.md | 10 +- .../embedded-book/src/start/semihosting.md | 2 +- .../src/unsorted/speed-vs-size.md | 4 +- src/doc/nomicon/README.md | 20 +- src/doc/nomicon/book.toml | 28 + src/doc/nomicon/src/README.md | 56 - src/doc/nomicon/src/SUMMARY.md | 106 +- src/doc/nomicon/src/aliasing.md | 17 +- .../src/{ => arc-mutex}/arc-and-mutex.md | 4 +- .../nomicon/src/{ => arc-mutex}/arc-base.md | 12 +- .../nomicon/src/{ => arc-mutex}/arc-clone.md | 20 +- .../nomicon/src/{ => arc-mutex}/arc-drop.md | 20 +- .../nomicon/src/{ => arc-mutex}/arc-final.md | 1 + .../nomicon/src/{ => arc-mutex}/arc-layout.md | 15 +- src/doc/nomicon/src/{ => arc-mutex}/arc.md | 2 +- src/doc/nomicon/src/atomics.md | 44 +- src/doc/nomicon/src/beneath-std.md | 8 +- src/doc/nomicon/src/casts.md | 78 +- src/doc/nomicon/src/coercions.md | 78 +- src/doc/nomicon/src/conversions.md | 1 - src/doc/nomicon/src/destructors.md | 1 + src/doc/nomicon/src/dropck.md | 20 +- src/doc/nomicon/src/exception-safety.md | 11 +- src/doc/nomicon/src/exotic-sizes.md | 33 +- src/doc/nomicon/src/ffi.md | 56 +- src/doc/nomicon/src/hrtb.md | 2 + src/doc/nomicon/src/intro.md | 43 + src/doc/nomicon/src/leaking.md | 13 +- src/doc/nomicon/src/lifetime-elision.md | 3 +- src/doc/nomicon/src/lifetime-mismatch.md | 10 +- src/doc/nomicon/src/lifetimes.md | 29 +- src/doc/nomicon/src/other-reprs.md | 50 +- src/doc/nomicon/src/ownership.md | 5 +- src/doc/nomicon/src/panic-handler.md | 19 +- src/doc/nomicon/src/phantom-data.md | 14 +- src/doc/nomicon/src/repr-rust.md | 1 + src/doc/nomicon/src/subtyping.md | 39 +- src/doc/nomicon/src/transmutes.md | 7 +- src/doc/nomicon/src/unbounded-lifetimes.md | 2 +- src/doc/nomicon/src/unchecked-uninit.md | 14 +- src/doc/nomicon/src/{ => vec}/vec-alloc.md | 15 +- src/doc/nomicon/src/{ => vec}/vec-dealloc.md | 1 + src/doc/nomicon/src/{ => vec}/vec-deref.md | 2 + src/doc/nomicon/src/{ => vec}/vec-drain.md | 6 +- src/doc/nomicon/src/{ => vec}/vec-final.md | 0 .../src/{ => vec}/vec-insert-remove.md | 2 + .../nomicon/src/{ => vec}/vec-into-iter.md | 6 +- src/doc/nomicon/src/{ => vec}/vec-layout.md | 5 +- src/doc/nomicon/src/{ => vec}/vec-push-pop.md | 2 + src/doc/nomicon/src/{ => vec}/vec-raw.md | 3 + src/doc/nomicon/src/{ => vec}/vec-zsts.md | 9 +- src/doc/nomicon/src/{ => vec}/vec.md | 0 src/doc/nomicon/src/what-unsafe-does.md | 32 +- src/doc/nomicon/src/working-with-unsafe.md | 2 +- src/doc/nomicon/theme/nomicon.css | 40 + src/doc/reference.md | 2 +- src/doc/reference/book.toml | 5 +- src/doc/reference/src/attributes/codegen.md | 16 +- src/doc/reference/src/destructors.md | 2 +- .../reference/src/dynamically-sized-types.md | 9 +- src/doc/reference/src/expressions.md | 20 +- .../reference/src/expressions/array-expr.md | 9 +- .../reference/src/expressions/block-expr.md | 2 +- .../reference/src/expressions/grouped-expr.md | 9 +- src/doc/reference/src/expressions/if-expr.md | 3 +- .../reference/src/expressions/loop-expr.md | 4 +- .../reference/src/expressions/match-expr.md | 5 +- .../src/expressions/operator-expr.md | 16 +- .../reference/src/expressions/struct-expr.md | 10 +- .../reference/src/expressions/tuple-expr.md | 9 +- src/doc/reference/src/introduction.md | 2 + .../reference/src/items/associated-items.md | 2 + src/doc/reference/src/items/functions.md | 8 +- src/doc/reference/src/items/generics.md | 19 +- src/doc/reference/src/items/static-items.md | 48 + src/doc/reference/src/items/traits.md | 5 +- src/doc/reference/src/items/type-aliases.md | 7 +- .../reference/src/items/use-declarations.md | 2 +- src/doc/reference/src/macro-ambiguity.md | 22 +- src/doc/reference/src/macros.md | 5 +- src/doc/reference/src/names/namespaces.md | 16 + src/doc/reference/src/paths.md | 14 +- .../reference/src/special-types-and-traits.md | 9 +- src/doc/reference/src/statements.md | 3 +- src/doc/reference/src/trait-bounds.md | 50 +- src/doc/reference/src/type-layout.md | 6 +- src/doc/reference/src/types/closure.md | 8 +- .../reference/src/visibility-and-privacy.md | 4 +- .../rust-by-example/.github/workflows/rbe.yml | 42 + .../src/custom_types/structs.md | 3 +- .../match/destructuring/destructure_tuple.md | 2 +- src/doc/rust-by-example/src/fn/methods.md | 29 +- .../src/std_misc/file/create.md | 2 +- .../rust-by-example/src/std_misc/file/open.md | 2 +- src/doc/rust-by-example/src/std_misc/path.md | 2 +- .../src/testing/integration_testing.md | 4 +- src/doc/rust-by-example/src/trait.md | 6 +- src/doc/rust.css | 117 +- src/doc/rustc-dev-guide/README.md | 3 + src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + .../rustc-dev-guide/src/about-this-guide.md | 32 +- .../rustc-dev-guide/src/appendix/glossary.md | 179 +- src/doc/rustc-dev-guide/src/ast-validation.md | 2 +- .../rustc-dev-guide/src/backend/inline-asm.md | 5 +- .../src/backend/libs-and-metadata.md | 29 +- .../rustc-dev-guide/src/building/suggested.md | 5 + src/doc/rustc-dev-guide/src/compiler-src.md | 9 - src/doc/rustc-dev-guide/src/contributing.md | 6 +- src/doc/rustc-dev-guide/src/crates-io.md | 4 +- .../src/debugging-support-in-rustc.md | 3 +- src/doc/rustc-dev-guide/src/diagnostics.md | 72 +- .../src/diagnostics/lintstore.md | 67 +- .../rustc-dev-guide/src/feature-gate-ck.md | 2 +- src/doc/rustc-dev-guide/src/feature-gates.md | 9 + src/doc/rustc-dev-guide/src/git.md | 55 +- src/doc/rustc-dev-guide/src/hir-debugging.md | 2 +- src/doc/rustc-dev-guide/src/identifiers.md | 2 +- src/doc/rustc-dev-guide/src/lang-items.md | 67 + .../rustc-dev-guide/src/macro-expansion.md | 4 +- src/doc/rustc-dev-guide/src/miri.md | 7 +- .../rustc-dev-guide/src/name-resolution.md | 2 +- src/doc/rustc-dev-guide/src/overview.md | 14 +- src/doc/rustc-dev-guide/src/parallel-rustc.md | 2 +- src/doc/rustc-dev-guide/src/query.md | 2 +- src/doc/rustc-dev-guide/src/salsa.md | 2 +- src/doc/rustc-dev-guide/src/stability.md | 43 +- src/doc/rustc-dev-guide/src/tests/running.md | 14 + src/doc/rustc-dev-guide/src/type-checking.md | 2 +- src/doc/rustc-dev-guide/src/type-inference.md | 5 +- src/doc/rustc-dev-guide/src/walkthrough.md | 2 +- src/doc/rustc/src/platform-support.md | 1 + src/doc/rustdoc/src/SUMMARY.md | 1 + src/doc/rustdoc/src/command-line-arguments.md | 7 + src/doc/rustdoc/src/website-features.md | 25 + .../{force-warns.md => force-warn.md} | 6 +- .../exclusive-range-pattern.md | 26 + .../half-open-range-patterns.md | 27 + .../impl-trait-in-bindings.md | 28 - .../unstable-book/src/library-features/asm.md | 13 +- .../src/library-features/try-trait.md | 50 - src/etc/dec2flt_table.py | 199 +- src/etc/gdb_lookup.py | 6 +- src/etc/gdb_providers.py | 55 +- src/etc/installer/README.md | 2 +- src/etc/lldb_commands | 4 +- src/etc/natvis/intrinsic.natvis | 56 +- src/etc/natvis/liballoc.natvis | 17 + src/etc/natvis/libcore.natvis | 158 +- src/etc/natvis/libstd.natvis | 20 +- src/etc/rust_types.py | 4 +- src/etc/test-float-parse/Cargo.toml | 13 + src/etc/test-float-parse/runtests.py | 37 +- .../{ => src/bin}/few-ones.rs | 4 +- .../{ => src/bin}/huge-pow10.rs | 4 +- .../{ => src/bin}/long-fractions.rs | 4 +- .../{ => src/bin}/many-digits.rs | 4 +- .../{ => src/bin}/rand-f64.rs | 4 +- .../{ => src/bin}/short-decimals.rs | 4 +- .../test-float-parse/{ => src/bin}/subnorm.rs | 4 +- .../{ => src/bin}/tiny-pow10.rs | 4 +- .../{ => src/bin}/u32-small.rs | 4 +- .../{ => src/bin}/u64-pow2.rs | 4 +- .../{_common.rs => src/lib.rs} | 0 src/librustdoc/Cargo.toml | 1 + src/librustdoc/clean/auto_trait.rs | 20 +- src/librustdoc/clean/blanket_impl.rs | 4 +- src/librustdoc/clean/cfg/tests.rs | 18 +- src/librustdoc/clean/inline.rs | 98 +- src/librustdoc/clean/mod.rs | 225 +- src/librustdoc/clean/simplify.rs | 28 +- src/librustdoc/clean/types.rs | 132 +- src/librustdoc/clean/utils.rs | 118 +- src/librustdoc/config.rs | 35 +- src/librustdoc/core.rs | 12 +- src/librustdoc/doctest.rs | 94 +- src/librustdoc/externalfiles.rs | 4 +- src/librustdoc/formats/cache.rs | 52 +- src/librustdoc/html/format.rs | 154 +- src/librustdoc/html/highlight.rs | 2 +- src/librustdoc/html/highlight/tests.rs | 6 +- src/librustdoc/html/layout.rs | 214 +- src/librustdoc/html/markdown.rs | 109 +- src/librustdoc/html/markdown/tests.rs | 4 +- src/librustdoc/html/render/cache.rs | 42 +- src/librustdoc/html/render/context.rs | 16 +- src/librustdoc/html/render/mod.rs | 396 +- src/librustdoc/html/render/print_item.rs | 216 +- src/librustdoc/html/render/write_shared.rs | 15 +- src/librustdoc/html/sources.rs | 1 + src/librustdoc/html/static/COPYRIGHT.txt | 14 +- src/librustdoc/html/static/css/normalize.css | 2 + .../html/static/{ => css}/noscript.css | 0 .../html/static/{ => css}/rustdoc.css | 135 +- .../html/static/{ => css}/settings.css | 0 .../html/static/{ => css}/themes/ayu.css | 12 +- .../html/static/{ => css}/themes/dark.css | 8 +- .../html/static/{ => css}/themes/light.css | 13 +- .../static/{ => fonts}/FiraSans-LICENSE.txt | 4 +- .../static/{ => fonts}/FiraSans-Medium.woff | Bin .../static/{ => fonts}/FiraSans-Medium.woff2 | Bin .../static/{ => fonts}/FiraSans-Regular.woff | Bin .../static/{ => fonts}/FiraSans-Regular.woff2 | Bin .../{ => fonts}/SourceCodePro-It.ttf.woff | Bin .../static/fonts/SourceCodePro-It.ttf.woff2 | Bin 0 -> 44896 bytes .../{ => fonts}/SourceCodePro-LICENSE.txt | 0 .../SourceCodePro-Regular.ttf.woff | Bin .../fonts/SourceCodePro-Regular.ttf.woff2 | Bin 0 -> 52228 bytes .../SourceCodePro-Semibold.ttf.woff | Bin .../fonts/SourceCodePro-Semibold.ttf.woff2 | Bin 0 -> 52348 bytes .../{ => fonts}/SourceSerif4-Bold.ttf.woff | Bin .../static/fonts/SourceSerif4-Bold.ttf.woff2 | Bin 0 -> 81320 bytes .../{ => fonts}/SourceSerif4-It.ttf.woff | Bin .../static/fonts/SourceSerif4-It.ttf.woff2 | Bin 0 -> 59860 bytes .../{ => fonts}/SourceSerif4-LICENSE.md | 0 .../{ => fonts}/SourceSerif4-Regular.ttf.woff | Bin .../fonts/SourceSerif4-Regular.ttf.woff2 | Bin 0 -> 76180 bytes .../html/static/{ => images}/brush.svg | 0 .../html/static/{ => images}/clipboard.svg | 0 .../html/static/{ => images}/down-arrow.svg | 0 .../static/{ => images}/favicon-16x16.png | Bin .../static/{ => images}/favicon-32x32.png | Bin .../html/static/{ => images}/favicon.svg | 0 .../html/static/{ => images}/rust-logo.png | Bin .../html/static/{ => images}/wheel.svg | 0 src/librustdoc/html/static/{ => js}/main.js | 34 +- src/librustdoc/html/static/{ => js}/search.js | 112 +- .../html/static/{ => js}/settings.js | 0 .../html/static/{ => js}/source-script.js | 0 .../html/static/{ => js}/storage.js | 2 + src/librustdoc/html/static/normalize.css | 2 - ...oto-sans-kr-v13-korean-regular-LICENSE.txt | 93 - .../noto-sans-kr-v13-korean-regular.woff | Bin 287068 -> 0 bytes src/librustdoc/html/static_files.rs | 97 +- src/librustdoc/html/templates/STYLE.md | 37 + src/librustdoc/html/templates/page.html | 119 + src/librustdoc/json/conversions.rs | 73 +- src/librustdoc/json/mod.rs | 20 +- src/librustdoc/lib.rs | 51 +- src/librustdoc/lint.rs | 2 +- src/librustdoc/markdown.rs | 13 +- .../passes/calculate_doc_coverage.rs | 4 +- .../passes/check_code_block_syntax.rs | 4 +- .../passes/collect_intra_doc_links.rs | 185 +- src/librustdoc/passes/collect_trait_impls.rs | 19 +- src/librustdoc/passes/doc_test_lints.rs | 9 +- src/librustdoc/passes/strip_hidden.rs | 6 +- src/librustdoc/passes/strip_private.rs | 4 +- src/librustdoc/passes/stripper.rs | 8 +- .../passes/unindent_comments/tests.rs | 4 +- src/librustdoc/theme/tests.rs | 2 +- src/stage0.txt | 6 +- src/test/assembly/asm/mips-types.rs | 3 +- src/test/assembly/asm/powerpc-types.rs | 3 +- src/test/assembly/asm/riscv-types.rs | 3 +- src/test/assembly/asm/x86-modifiers.rs | 2 + src/test/assembly/asm/x86-types.rs | 2 + src/test/assembly/static-relocation-model.rs | 4 +- src/test/codegen/abi-efiapi.rs | 7 +- src/test/codegen/align-fn.rs | 9 + src/test/codegen/array-equality.rs | 57 + src/test/codegen/asm-clobbers.rs | 19 + src/test/codegen/asm-options.rs | 7 + src/test/codegen/asm-sanitize-llvm.rs | 3 +- src/test/codegen/async-fn-debug-msvc.rs | 6 +- src/test/codegen/async-fn-debug.rs | 2 +- src/test/codegen/consts.rs | 2 +- src/test/codegen/default-requires-uwtable.rs | 3 +- src/test/codegen/fn-impl-trait-self.rs | 3 +- src/test/codegen/frame-pointer.rs | 35 + src/test/codegen/generator-debug-msvc.rs | 6 +- src/test/codegen/generator-debug.rs | 2 +- .../codegen/i686-macosx-deployment-target.rs | 1 + .../i686-no-macosx-deployment-target.rs | 1 + src/test/codegen/pgo-instrumentation.rs | 3 +- src/test/codegen/remap_path_prefix/main.rs | 2 +- src/test/codegen/slice-ref-equality.rs | 19 +- src/test/codegen/sparc-struct-abi.rs | 3 +- .../codegen/unwind-abis/stdcall-unwind-abi.rs | 13 +- .../unwind-abis/thiscall-unwind-abi.rs | 14 +- .../x86_64-macosx-deployment-target.rs | 1 + .../x86_64-no-macosx-deployment-target.rs | 1 + src/test/debuginfo/basic-types.rs | 44 +- src/test/debuginfo/duration-type.rs | 22 + src/test/debuginfo/fixed-sized-array.rs | 39 + src/test/debuginfo/function-names.rs | 201 + src/test/debuginfo/generator-objects.rs | 16 +- src/test/debuginfo/generic-struct.rs | 21 + src/test/debuginfo/issue-57822.rs | 8 +- src/test/debuginfo/marker-types.rs | 49 + src/test/debuginfo/msvc-pretty-enums.rs | 61 +- src/test/debuginfo/mutable-locs.rs | 104 + src/test/debuginfo/mutex.rs | 38 + src/test/debuginfo/numeric-types.rs | 206 + src/test/debuginfo/pretty-huge-vec.rs | 2 +- src/test/debuginfo/pretty-slices.rs | 46 + .../debuginfo/pretty-std-collections-hash.rs | 9 +- src/test/debuginfo/pretty-std.rs | 58 +- src/test/debuginfo/range-types.rs | 49 + src/test/debuginfo/rc_arc.rs | 43 +- src/test/debuginfo/result-types.rs | 28 + src/test/debuginfo/rwlock-read.rs | 35 + src/test/debuginfo/rwlock-write.rs | 27 + src/test/debuginfo/simple-tuple.rs | 14 +- src/test/debuginfo/thread.rs | 31 + src/test/debuginfo/tuple-in-tuple.rs | 42 +- src/test/debuginfo/type-names.cdb.js | 17 + src/test/debuginfo/type-names.rs | 293 +- .../var-captured-in-nested-closure.rs | 2 +- src/test/incremental/issue-86753.rs | 50 + ...main.SimplifyCfg-elaborate-drops.after.mir | 6 +- ..._allocation.main.ConstProp.after.32bit.mir | 40 +- ..._allocation.main.ConstProp.after.64bit.mir | 44 +- ...allocation2.main.ConstProp.after.32bit.mir | 38 +- ...allocation2.main.ConstProp.after.64bit.mir | 40 +- ...allocation3.main.ConstProp.after.32bit.mir | 24 +- ...allocation3.main.ConstProp.after.64bit.mir | 22 +- ...d[0].SimplifyCfg-elaborate-drops.after.mir | 8 +- ...motion_extern_static.BAR.PromoteTemps.diff | 10 +- ...d[0].SimplifyCfg-elaborate-drops.after.mir | 8 +- ...motion_extern_static.FOO.PromoteTemps.diff | 10 +- ...e_oob_for_slices.main.ConstProp.32bit.diff | 2 +- ...e_oob_for_slices.main.ConstProp.64bit.diff | 2 +- .../checked_add.main.ConstProp.diff | 3 - ..._prop_fails_gracefully.main.ConstProp.diff | 2 +- .../const_prop/indirect.main.ConstProp.diff | 3 - .../issue_67019.main.ConstProp.diff | 3 - ...ble_variable_aggregate.main.ConstProp.diff | 3 - ...table_variable_no_prop.main.ConstProp.diff | 8 +- ...es_into_variable.main.ConstProp.32bit.diff | 3 - ...es_into_variable.main.ConstProp.64bit.diff | 3 - .../read_immutable_static.main.ConstProp.diff | 14 +- .../const_prop/ref_deref.main.ConstProp.diff | 2 +- .../ref_deref.main.PromoteTemps.diff | 2 +- .../ref_deref_project.main.ConstProp.diff | 2 +- .../ref_deref_project.main.PromoteTemps.diff | 2 +- .../return_place.add.ConstProp.diff | 3 - .../slice_len.main.ConstProp.32bit.diff | 2 +- .../slice_len.main.ConstProp.64bit.diff | 2 +- ...le_literal_propagation.main.ConstProp.diff | 3 - .../deaggregator_test.bar.Deaggregator.diff | 3 - ...anup.main-{closure#0}.generator_drop.0.mir | 2 +- ...main-{closure#0}.StateTransform.before.mir | 2 +- ...ny.main-{closure#0}.generator_resume.0.mir | 6 +- ...opt_floats.SimplifyComparisonIntegral.diff | 3 - .../inline/inline_generator.main.Inline.diff | 16 +- .../inline/inline_retag.bar.Inline.after.mir | 4 +- .../issue_73223.main.PreCodegen.32bit.diff | 2 +- .../issue_73223.main.PreCodegen.64bit.diff | 2 +- ..._73223.main.SimplifyArmIdentity.32bit.diff | 2 +- ..._73223.main.SimplifyArmIdentity.64bit.diff | 2 +- ...trinsics.discriminant.LowerIntrinsics.diff | 6 +- ...er_slice_len.bound.LowerSliceLenCalls.diff | 63 + src/test/mir-opt/lower_slice_len.rs | 14 + ...s.full_tested_match.PromoteTemps.after.mir | 2 +- ...asts.SimplifyCfg-elaborate-drops.after.mir | 2 +- ...main.SimplifyCfg-elaborate-drops.after.mir | 4 +- ...ves_unused_consts.main.SimplifyLocals.diff | 3 - ...after-uninhabited-enum-branching.after.mir | 106 + ...nching2.main.UninhabitedEnumBranching.diff | 160 + .../mir-opt/uninhabited_enum_branching2.rs | 34 + src/test/pretty/ast-stmt-expr-attr.rs | 2 +- src/test/pretty/block-comment-wchar.pp | 2 +- src/test/pretty/block-comment-wchar.rs | 2 +- src/test/pretty/cast-lt.pp | 2 +- src/test/pretty/delimited-token-groups.rs | 2 +- src/test/pretty/hir-pretty-loop.pp | 9 + src/test/pretty/hir-pretty-loop.rs | 9 + src/test/pretty/macro.rs | 2 +- src/test/pretty/macro_rules.rs | 6 +- src/test/pretty/stmt_expr_attributes.rs | 3 +- .../core-no-fp-fmt-parse/Makefile | 4 + .../coverage-reports/Makefile | 14 +- .../extern-fn-with-packed-struct/test.c | 2 +- .../hotplug_codegen_backend/the_backend.rs | 4 +- .../pgo-branch-weights/Makefile | 14 - .../run-make-fulldeps/pgo-gen-lto/Makefile | 8 - .../pgo-gen-no-imp-symbols/Makefile | 8 - src/test/run-make-fulldeps/pgo-gen/Makefile | 8 - .../pgo-indirect-call-promotion/Makefile | 14 - src/test/run-make-fulldeps/pgo-use/Makefile | 8 - src/test/run-make-fulldeps/print-cfg/Makefile | 2 + .../rustdoc-target-spec-json-path/target.json | 1 - .../run-make-fulldeps/rustdoc-themes/Makefile | 2 +- .../run-make-fulldeps/target-specs/Makefile | 2 + .../definitely-not-builtin-target.json | 7 + .../target-specs/mismatching-data-layout.json | 6 + src/test/run-make/emit-path-unhashed/Makefile | 37 + src/test/run-make/emit-path-unhashed/foo.rs | 1 + .../raw-dylib-alt-calling-convention/Makefile | 18 + .../driver.rs | 5 + .../raw-dylib-alt-calling-convention/extern.c | 123 + .../raw-dylib-alt-calling-convention/lib.rs | 71 + .../output.txt | 18 + .../{raw-dylib => raw-dylib-c}/Makefile | 3 +- .../{raw-dylib => raw-dylib-c}/driver.rs | 0 .../{raw-dylib => raw-dylib-c}/extern_1.c | 0 .../{raw-dylib => raw-dylib-c}/extern_2.c | 0 .../{raw-dylib => raw-dylib-c}/lib.rs | 0 .../{raw-dylib => raw-dylib-c}/output.txt | 0 .../run-make/track-path-dep-info/Makefile | 13 + .../run-make/track-path-dep-info/emojis.txt | 1 + .../run-make/track-path-dep-info/macro_def.rs | 11 + .../run-make/track-path-dep-info/macro_use.rs | 6 + .../run-make/unstable-flag-required/Makefile | 2 +- .../{force-warns.stderr => force-warn.stderr} | 2 +- src/test/rustdoc-gui/README.md | 12 + .../auto-hide-trait-implementations.goml | 13 + src/test/rustdoc-gui/ayu-code-tag-colors.goml | 13 + src/test/rustdoc-gui/basic-code.goml | 3 + src/test/rustdoc-gui/basic.goml | 4 + .../rustdoc-gui/check_info_sign_position.goml | 9 + .../rustdoc-gui/code-blocks-overflow.goml | 8 + src/test/rustdoc-gui/code-sidebar-toggle.goml | 6 + src/test/rustdoc-gui/default-settings.goml | 8 + .../rustdoc-gui/docblock-table-overflow.goml | 9 + src/test/rustdoc-gui/escape-key.goml | 34 + src/test/rustdoc-gui/font-weight.goml | 20 + src/test/rustdoc-gui/hash-item-expansion.goml | 15 + .../rustdoc-gui/impl-default-expansion.goml | 3 + src/test/rustdoc-gui/implementors.goml | 16 + src/test/rustdoc-gui/item-info-width.goml | 7 + src/test/rustdoc-gui/item-summary-table.goml | 6 + .../rustdoc-gui/label-next-to-symbol.goml | 36 + src/test/rustdoc-gui/list_code_block.goml | 3 + src/test/rustdoc-gui/module-items-font.goml | 4 + src/test/rustdoc-gui/search-filter.goml | 17 + src/test/rustdoc-gui/search-input-mobile.goml | 11 + src/test/rustdoc-gui/search-result-color.goml | 41 + .../rustdoc-gui/search-result-colors.goml | 14 + .../search-result-description.goml | 5 + .../rustdoc-gui/search-result-display.goml | 12 + .../search-result-go-to-first.goml | 20 + .../rustdoc-gui/search-result-keyword.goml | 10 + ...rch-tab-selection-if-current-is-empty.goml | 21 + src/test/rustdoc-gui/shortcuts.goml | 26 + src/test/rustdoc-gui/sidebar-mobile.goml | 20 + src/test/rustdoc-gui/sidebar.goml | 60 + src/test/rustdoc-gui/source-code-page.goml | 15 + src/test/rustdoc-gui/src/lib2.rs | 11 - src/test/rustdoc-gui/src/lib2/Cargo.lock | 14 + src/test/rustdoc-gui/src/lib2/Cargo.toml | 10 + .../src/lib2/implementors/Cargo.lock | 7 + .../src/lib2/implementors/Cargo.toml | 7 + .../rustdoc-gui/src/lib2/implementors/lib.rs | 11 + src/test/rustdoc-gui/src/lib2/lib.rs | 77 + .../src/settings/.cargo/config.toml | 2 + .../rustdoc-gui/src/settings/.package-cache | 0 src/test/rustdoc-gui/src/settings/Cargo.lock | 7 + src/test/rustdoc-gui/src/settings/Cargo.toml | 7 + src/test/rustdoc-gui/src/settings/lib.rs | 1 + src/test/rustdoc-gui/src/test_docs/Cargo.lock | 7 + src/test/rustdoc-gui/src/test_docs/Cargo.toml | 7 + .../rustdoc-gui/src/{ => test_docs}/lib.rs | 15 + src/test/rustdoc-gui/theme-change.goml | 10 + src/test/rustdoc-gui/toggle-docs-mobile.goml | 21 + src/test/rustdoc-gui/toggle-docs.goml | 10 + src/test/rustdoc-gui/toggle-implementors.goml | 4 + .../toggled-open-implementations.goml | 5 + .../rustdoc-gui/trait-sidebar-item-order.goml | 7 + .../rustdoc-gui/type-declation-overflow.goml | 8 + src/test/rustdoc-gui/type-weight.rs | 2 - src/test/rustdoc-js-std/alias-4.js | 7 + src/test/rustdoc-js-std/typed-query.js | 12 + src/test/rustdoc-js/generics-trait.js | 23 + src/test/rustdoc-js/generics-trait.rs | 8 + src/test/rustdoc-js/generics.js | 44 + src/test/rustdoc-js/generics.rs | 21 + src/test/rustdoc-js/summaries.js | 2 +- src/test/rustdoc-js/summaries.rs | 6 +- src/test/rustdoc-ui/intra-doc/field-ice.rs | 11 + .../rustdoc-ui/intra-doc/field-ice.stderr | 15 + src/test/rustdoc-ui/nocapture-fail.rs | 12 + src/test/rustdoc-ui/nocapture-fail.stderr | 18 + src/test/rustdoc-ui/nocapture-fail.stdout | 6 + src/test/rustdoc-ui/nocapture.rs | 10 + src/test/rustdoc-ui/nocapture.stderr | 1 + src/test/rustdoc-ui/nocapture.stdout | 7 + .../rustdoc-ui/renamed-lint-still-applies.rs | 3 +- .../renamed-lint-still-applies.stderr | 21 +- src/test/rustdoc-ui/unknown-renamed-lints.rs | 3 +- .../rustdoc-ui/unknown-renamed-lints.stderr | 14 +- src/test/rustdoc/attributes.rs | 8 - .../cross-crate-hidden-impl-parameter.rs | 5 + src/test/rustdoc/auxiliary/issue-85454.rs | 17 + src/test/rustdoc/auxiliary/issue-86620-1.rs | 11 + src/test/rustdoc/auxiliary/reexports.rs | 42 + src/test/rustdoc/cap-lints.rs | 3 +- src/test/rustdoc/const-display.rs | 20 +- .../const-evaluatable-checked.rs | 7 + .../cross-crate-hidden-impl-parameter.rs | 35 + src/test/rustdoc/decl_macro.rs | 12 +- src/test/rustdoc/default-theme.rs | 7 + src/test/rustdoc/deprecated.rs | 6 +- src/test/rustdoc/doc-cfg.rs | 6 +- src/test/rustdoc/duplicate-cfg.rs | 5 +- src/test/rustdoc/duplicate-flags.rs | 4 + src/test/rustdoc/ensure-src-link.rs | 2 +- src/test/rustdoc/extern-default-method.rs | 2 + src/test/rustdoc/for-lifetime.rs | 12 - .../rustdoc/higher-ranked-trait-bounds.rs | 61 + src/test/rustdoc/inline_cross/macros.rs | 6 +- src/test/rustdoc/internal.rs | 8 +- .../intra-doc/macros-disambiguators.rs | 25 + src/test/rustdoc/intra-doc/type-alias.rs | 19 + src/test/rustdoc/issue-19055.rs | 20 - src/test/rustdoc/issue-32374.rs | 10 +- src/test/rustdoc/issue-46377.rs | 2 +- src/test/rustdoc/issue-55364.rs | 8 +- src/test/rustdoc/issue-85454.rs | 14 +- src/test/rustdoc/issue-86620.rs | 9 + src/test/rustdoc/macro_rules-matchers.rs | 45 + src/test/rustdoc/macros.rs | 8 +- src/test/rustdoc/must-use.rs | 11 - src/test/rustdoc/recursive-deref-sidebar.rs | 22 + src/test/rustdoc/recursive-deref.rs | 22 + src/test/rustdoc/reexport-check.rs | 6 +- src/test/rustdoc/reexports-priv.rs | 53 + src/test/rustdoc/reexports.rs | 47 + src/test/rustdoc/safe-intrinsic.rs | 20 + .../same-crate-hidden-impl-parameter.rs | 36 + src/test/rustdoc/short-docblock-codeblock.rs | 6 +- src/test/rustdoc/short-docblock.rs | 25 + src/test/rustdoc/short-dockblock.rs | 25 - src/test/rustdoc/toggle-item-contents.rs | 45 +- src/test/rustdoc/trait-attributes.rs | 21 - .../trait-impl-items-links-and-anchors.rs | 15 +- .../internal-lints/default_hash_types.rs | 17 +- .../internal-lints/default_hash_types.stderr | 30 +- .../ui-fulldeps/mod_dir_path_canonicalized.rs | 2 +- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 2 +- .../ui-fulldeps/session-derive-errors.stderr | 5 + src/test/ui/abi/unsupported.aarch64.stderr | 58 + src/test/ui/abi/unsupported.i686.stderr | 39 + src/test/ui/abi/unsupported.rs | 48 + src/test/ui/abi/unsupported.x64.stderr | 58 + src/test/ui/allocator/not-an-allocator.stderr | 32 +- src/test/ui/allocator/two-allocators.stderr | 1 + .../anon-params/anon-params-deprecated.fixed | 6 +- .../ui/anon-params/anon-params-deprecated.rs | 6 +- .../anon-params/anon-params-deprecated.stderr | 6 +- src/test/ui/array-slice-vec/slice-panic-1.rs | 2 +- src/test/ui/array-slice-vec/slice-panic-2.rs | 2 +- src/test/ui/array-slice-vec/slice.rs | 16 +- src/test/ui/asm/bad-options.stderr | 24 +- src/test/ui/asm/bad-reg.rs | 19 +- src/test/ui/asm/bad-reg.stderr | 60 +- src/test/ui/asm/inline-syntax.arm.stderr | 12 +- src/test/ui/asm/inline-syntax.rs | 4 +- src/test/ui/asm/inline-syntax.x86_64.stderr | 14 +- src/test/ui/{issues => asm}/issue-82869.rs | 0 .../ui/{issues => asm}/issue-82869.stderr | 0 src/test/ui/asm/parse-error.stderr | 20 +- .../associated-const-array-len.stderr | 9 +- .../associated-const-private-impl.stderr | 3 + .../ui/associated-consts/issue-63496.stderr | 16 +- .../ui/associated-item/issue-48027.stderr | 7 +- .../assoc-type-eq-with-dyn-atb-fail.rs | 1 - .../assoc-type-eq-with-dyn-atb-fail.stderr | 8 +- .../duplicate.full_tait.stderr | 202 +- .../duplicate.min_tait.stderr | 203 +- .../ui/associated-type-bounds/duplicate.rs | 21 - .../ui/associated-type-bounds/dyn-lcsit.rs | 69 - .../associated-type-bounds/dyn-lcsit.stderr | 11 - src/test/ui/associated-type-bounds/lcsit.rs | 78 - .../ui/associated-type-bounds/lcsit.stderr | 11 - .../associated-types-bound-failure.stderr | 8 +- .../associated-types-for-unimpl-trait.stderr | 7 +- .../associated-types-no-suitable-bound.stderr | 7 +- ...ated-types-no-suitable-supertrait-2.stderr | 7 +- ...ciated-types-no-suitable-supertrait.stderr | 14 +- ...ted-trait-in-method-without-default.stderr | 7 +- .../associated-types-unconstrained.stderr | 8 +- .../ui/associated-types/defaults-wf.stderr | 4 +- .../hr-associated-type-projection-1.rs | 2 +- .../hr-associated-type-projection-1.stderr | 8 +- .../issue-20005.rs | 0 .../issue-20005.stderr | 0 .../ui/associated-types/issue-44153.stderr | 8 +- .../normalization-debruijn-1.rs | 36 + .../normalization-debruijn-2.rs | 31 + .../normalization-debruijn-3.rs | 41 + .../normalization-generality.rs | 36 + .../async-await/async-fn-path-elision.stderr | 2 + .../2015-edition-error-various-positions.rs | 20 +- ...015-edition-error-various-positions.stderr | 20 +- .../await-keyword/2015-edition-warning.fixed | 12 +- .../await-keyword/2015-edition-warning.rs | 12 +- .../await-keyword/2015-edition-warning.stderr | 12 +- src/test/ui/async-await/issue-61076.stderr | 12 +- src/test/ui/async-await/issue-68112.stderr | 8 +- src/test/ui/async-await/issue-70594.stderr | 6 +- src/test/ui/async-await/issue-84841.rs | 16 + src/test/ui/async-await/issue-84841.stderr | 36 + src/test/ui/async-await/issue-86507.rs | 25 + src/test/ui/async-await/issue-86507.stderr | 23 + .../async-await/issues/issue-62009-1.stderr | 6 +- .../ui/async-await/issues/issue-67893.stderr | 4 +- .../ret-impl-trait-one.nll.stderr | 16 +- .../async-await/pin-needed-to-poll-2.stderr | 6 +- .../async-await/try-on-option-in-async.stderr | 18 +- .../ui/attributes/nonterminal-expansion.rs | 5 +- .../attributes/nonterminal-expansion.stderr | 4 +- src/test/ui/bastion-of-the-turbofish.rs | 3 + src/test/ui/binop/issue-77910-1.stderr | 5 - ...k-assign-to-andmut-in-aliasable-loc.stderr | 4 +- ...orrow-mut-base-ptr-in-aliasable-loc.stderr | 2 +- .../ui/borrowck/borrowck-issue-14498.stderr | 2 +- .../ui/{ => borrowck}/fsu-moves-and-copies.rs | 0 ...issue-69789-iterator-mut-suggestion.stderr | 2 +- .../issue-83309-ice-immut-in-for-loop.rs | 2 +- .../issue-83309-ice-immut-in-for-loop.stderr | 2 +- src/test/ui/borrowck/issue-83760.rs | 40 + src/test/ui/borrowck/issue-83760.stderr | 62 + src/test/ui/borrowck/issue-85581.rs | 15 + src/test/ui/borrowck/issue-85581.stderr | 17 + src/test/ui/borrowck/issue-85765.rs | 7 + src/test/ui/borrowck/issue-85765.stderr | 14 +- src/test/ui/borrowck/mutability-errors.stderr | 8 +- ...-phase-reservation-sharing-interference.rs | 4 +- src/test/ui/bound-suggestions.stderr | 6 - src/test/ui/box/into-boxed-slice-fail.stderr | 12 +- src/test/ui/c-variadic/issue-86053-1.rs | 12 + src/test/ui/c-variadic/issue-86053-1.stderr | 101 + src/test/ui/c-variadic/issue-86053-2.rs | 11 + src/test/ui/c-variadic/issue-86053-2.stderr | 16 + src/test/ui/c-variadic/variadic-ffi-1.rs | 9 +- src/test/ui/c-variadic/variadic-ffi-1.stderr | 26 +- .../ui/cast/cast-ptr-to-int-const.mir.stderr | 19 - src/test/ui/cast/cast-ptr-to-int-const.rs | 19 - .../ui/cast/cast-ptr-to-int-const.thir.stderr | 19 - src/test/ui/cast/fat-ptr-cast-rpass.rs | 17 +- ...eature-gate-const_raw_ptr_to_usize_cast.rs | 13 - ...re-gate-const_raw_ptr_to_usize_cast.stderr | 30 - src/test/ui/cfg/cfg-target-abi.rs | 10 + src/test/ui/chalkify/type_wf.stderr | 8 +- .../arrays-completely-captured.rs | 5 +- .../arrays-completely-captured.stderr | 21 +- .../2229_closure_analysis/by_value.rs | 11 +- .../2229_closure_analysis/by_value.stderr | 32 +- .../capture-analysis-1.rs | 6 +- .../capture-analysis-1.stderr | 29 +- .../capture-analysis-2.rs | 6 +- .../capture-analysis-2.stderr | 23 +- .../capture-analysis-3.rs | 6 +- .../capture-analysis-3.stderr | 23 +- .../capture-analysis-4.rs | 6 +- .../capture-analysis-4.stderr | 23 +- .../capture-disjoint-field-struct.rs | 6 +- .../capture-disjoint-field-struct.stderr | 21 +- .../capture-disjoint-field-tuple.rs | 6 +- .../capture-disjoint-field-tuple.stderr | 21 +- .../2229_closure_analysis/capture-enums.rs | 6 +- .../capture-enums.stderr | 39 +- .../deep-multilevel-struct.rs | 6 +- .../deep-multilevel-struct.stderr | 25 +- .../deep-multilevel-tuple.rs | 5 +- .../deep-multilevel-tuple.stderr | 25 +- .../destructure_patterns.rs | 6 +- .../destructure_patterns.stderr | 53 +- .../diagnostics/arrays.rs | 5 +- .../diagnostics/arrays.stderr | 25 +- .../diagnostics/borrowck/borrowck-1.rs | 3 +- .../diagnostics/borrowck/borrowck-1.stderr | 13 +- .../diagnostics/borrowck/borrowck-2.rs | 3 +- .../diagnostics/borrowck/borrowck-2.stderr | 13 +- .../diagnostics/borrowck/borrowck-3.rs | 3 +- .../diagnostics/borrowck/borrowck-3.stderr | 13 +- .../diagnostics/borrowck/borrowck-4.rs | 3 +- .../diagnostics/borrowck/borrowck-4.stderr | 15 +- .../borrowck/borrowck-closures-mut-and-imm.rs | 4 +- .../borrowck-closures-mut-and-imm.stderr | 11 +- .../2229_closure_analysis/diagnostics/box.rs | 5 +- .../diagnostics/box.stderr | 17 +- .../diagnostics/cant-mutate-imm-borrow.rs | 9 +- .../diagnostics/cant-mutate-imm-borrow.stderr | 17 +- .../diagnostics/cant-mutate-imm.rs | 3 +- .../diagnostics/cant-mutate-imm.stderr | 15 +- .../closure-origin-array-diagnostics.rs | 5 +- .../closure-origin-array-diagnostics.stderr | 13 +- ...losure-origin-multi-variant-diagnostics.rs | 6 +- ...re-origin-multi-variant-diagnostics.stderr | 15 +- ...osure-origin-single-variant-diagnostics.rs | 6 +- ...e-origin-single-variant-diagnostics.stderr | 15 +- .../closure-origin-struct-diagnostics.rs | 5 +- .../closure-origin-struct-diagnostics.stderr | 15 +- .../closure-origin-tuple-diagnostics-1.rs | 5 +- .../closure-origin-tuple-diagnostics-1.stderr | 15 +- .../closure-origin-tuple-diagnostics.rs | 6 +- .../closure-origin-tuple-diagnostics.stderr | 13 +- .../diagnostics/liveness.rs | 4 +- .../diagnostics/liveness.stderr | 11 +- .../liveness_unintentional_copy.rs | 4 +- .../liveness_unintentional_copy.stderr | 11 +- .../diagnostics/multilevel-path.rs | 4 +- .../diagnostics/multilevel-path.stderr | 11 +- .../diagnostics/mut_ref.rs | 5 +- .../diagnostics/mut_ref.stderr | 15 +- .../diagnostics/repr_packed.rs | 5 +- .../diagnostics/repr_packed.stderr | 13 +- .../diagnostics/simple-struct-min-capture.rs | 5 +- .../simple-struct-min-capture.stderr | 13 +- .../feature-gate-capture_disjoint_fields.rs | 6 +- ...eature-gate-capture_disjoint_fields.stderr | 21 +- .../filter-on-struct-member.rs | 6 +- .../filter-on-struct-member.stderr | 19 +- .../2229_closure_analysis/issue-87097.rs | 35 + .../2229_closure_analysis/issue-87097.stderr | 33 + .../migrations/auto_traits.fixed | 27 +- .../migrations/auto_traits.rs | 27 +- .../migrations/auto_traits.stderr | 75 +- .../migrations/insignificant_drop.fixed | 59 +- .../migrations/insignificant_drop.rs | 59 +- .../migrations/insignificant_drop.stderr | 214 +- .../insignificant_drop_attr_migrations.fixed | 17 +- .../insignificant_drop_attr_migrations.rs | 17 +- .../insignificant_drop_attr_migrations.stderr | 54 +- .../insignificant_drop_attr_no_migrations.rs | 2 +- .../migrations/issue-78720.rs | 4 +- .../migrations/issue-86753.rs | 34 + .../migrations/migrations_rustfix.fixed | 12 +- .../migrations/migrations_rustfix.rs | 12 +- .../migrations/migrations_rustfix.stderr | 41 +- .../migrations/mir_calls_to_shims.fixed | 21 +- .../migrations/mir_calls_to_shims.rs | 21 +- .../migrations/mir_calls_to_shims.stderr | 26 +- .../migrations/multi_diagnostics.fixed | 138 + .../migrations/multi_diagnostics.rs | 138 + .../migrations/multi_diagnostics.stderr | 134 + .../migrations/no_migrations.rs | 5 +- .../migrations/old_name.rs | 9 + .../migrations/old_name.stderr | 10 + .../migrations/precise.fixed | 25 +- .../migrations/precise.rs | 25 +- .../migrations/precise.stderr | 69 +- .../migrations/precise_no_migrations.rs | 5 +- .../migrations/significant_drop.fixed | 100 +- .../migrations/significant_drop.rs | 100 +- .../migrations/significant_drop.stderr | 252 +- .../migrations/unpin_no_migration.rs | 13 + .../2229_closure_analysis/move_closure.rs | 103 +- .../2229_closure_analysis/move_closure.stderr | 280 +- .../multilevel-path-1.rs | 6 +- .../multilevel-path-1.stderr | 21 +- .../multilevel-path-2.rs | 6 +- .../multilevel-path-2.stderr | 21 +- .../2229_closure_analysis/nested-closure.rs | 6 +- .../nested-closure.stderr | 39 +- .../optimization/edge_case.rs | 34 + .../optimization/edge_case.stderr | 36 + .../optimization/edge_case_run_pass.rs | 27 + .../path-with-array-access.rs | 6 +- .../path-with-array-access.stderr | 21 +- .../pattern-matching-should-fail.rs | 6 +- .../pattern-matching-should-fail.stderr | 27 +- .../patterns-capture-analysis.rs | 6 +- .../patterns-capture-analysis.stderr | 55 +- .../2229_closure_analysis/repr_packed.rs | 5 +- .../2229_closure_analysis/repr_packed.stderr | 47 +- .../2229_closure_analysis/run_pass/box.rs | 7 +- .../2229_closure_analysis/run_pass/box.stderr | 11 - .../run_pass/by_value.rs | 4 +- .../run_pass/by_value.stderr | 11 - .../run_pass/capture-disjoint-field-struct.rs | 6 +- .../capture-disjoint-field-struct.stderr | 11 - .../capture-disjoint-field-tuple-mut.rs | 5 +- .../capture-disjoint-field-tuple-mut.stderr | 11 - .../run_pass/capture-disjoint-field-tuple.rs | 5 +- .../capture-disjoint-field-tuple.stderr | 11 - .../run_pass/capture_with_wildcard_match.rs | 3 +- .../capture_with_wildcard_match.stderr | 11 - ...tructure-pattern-closure-within-closure.rs | 5 +- ...ture-pattern-closure-within-closure.stderr | 17 +- .../run_pass/destructure_patterns.rs | 5 +- .../run_pass/destructure_patterns.stderr | 29 +- .../disjoint-capture-in-same-closure.rs | 6 +- .../disjoint-capture-in-same-closure.stderr | 11 - .../run_pass/drop_then_use_fake_reads.rs | 5 +- .../run_pass/drop_then_use_fake_reads.stderr | 11 - .../2229_closure_analysis/run_pass/edition.rs | 23 + .../run_pass/filter-on-struct-member.rs | 6 +- .../run_pass/filter-on-struct-member.stderr | 11 - .../run_pass/fru_syntax.rs | 6 +- .../run_pass/fru_syntax.stderr | 11 - .../lit-pattern-matching-with-methods.rs | 3 +- .../lit-pattern-matching-with-methods.stderr | 11 - .../run_pass/move_closure.rs | 15 +- .../run_pass/move_closure.stderr | 11 - .../run_pass/multilevel-path-1.rs | 5 +- .../run_pass/multilevel-path-1.stderr | 11 - .../run_pass/multilevel-path-2.rs | 5 +- .../run_pass/multilevel-path-2.stderr | 11 - .../run_pass/multilevel-path-3.rs | 5 +- .../run_pass/multilevel-path-3.stderr | 11 - .../2229_closure_analysis/run_pass/mut_ref.rs | 4 +- .../run_pass/mut_ref.stderr | 11 - .../run_pass/mut_ref_struct_mem.rs | 4 +- .../run_pass/mut_ref_struct_mem.stderr | 11 - .../run_pass/nested-closure.rs | 6 +- .../run_pass/nested-closure.stderr | 11 - .../struct-pattern-matching-with-methods.rs | 3 +- ...truct-pattern-matching-with-methods.stderr | 11 - ...le-struct-pattern-matching-with-methods.rs | 3 +- ...truct-pattern-matching-with-methods.stderr | 11 - .../run_pass/unsafe_ptr.rs | 4 +- .../run_pass/unsafe_ptr.stderr | 11 - .../use_of_mutable_borrow_and_fake_reads.rs | 3 +- ...se_of_mutable_borrow_and_fake_reads.stderr | 11 - .../simple-struct-min-capture.rs | 6 +- .../simple-struct-min-capture.stderr | 23 +- .../2229_closure_analysis/unsafe_ptr.rs | 7 +- .../2229_closure_analysis/unsafe_ptr.stderr | 31 +- .../2229_closure_analysis/wild_patterns.rs | 6 +- .../wild_patterns.stderr | 41 +- src/test/ui/closures/issue-41366.stderr | 2 +- .../params-on-registers.rs | 16 +- .../cmse-nonsecure-call/params-on-stack.rs | 18 +- .../wrong-abi-location-1.rs | 8 +- .../wrong-abi-location-1.stderr | 8 +- .../wrong-abi-location-2.rs | 8 +- .../wrong-abi-location-2.stderr | 4 +- .../cmse-nonsecure-entry/issue-83475.rs | 9 + .../cmse-nonsecure-entry/issue-83475.stderr | 11 + .../params-on-registers.rs | 14 +- .../cmse-nonsecure-entry/params-on-stack.rs | 16 +- .../cmse-nonsecure-entry/wrong-abi.rs | 13 +- .../cmse-nonsecure-entry/wrong-abi.stderr | 4 +- ...issue-88043-bb-does-not-have-terminator.rs | 35 + .../ui/{issues => coercion}/issue-37655.rs | 0 ...erence-fn-covariant-bound-vs-static.stderr | 4 +- .../{ => conditional-compilation}/test-cfg.rs | 0 .../test-cfg.stderr | 0 src/test/ui/conflicting-repr-hints.rs | 11 + src/test/ui/conflicting-repr-hints.stderr | 16 +- .../abstract-const-as-cast-1.rs | 18 + .../abstract-const-as-cast-2.rs | 20 + .../abstract-const-as-cast-2.stderr | 26 + .../abstract-const-as-cast-3.rs | 47 + .../abstract-const-as-cast-3.stderr | 139 + .../abstract-const-as-cast-4.rs | 29 + .../object-safety-err-ret.stderr | 4 +- .../unused-complex-default-expr.rs | 6 + .../complex-generic-default-expr.full.stderr | 18 - .../complex-generic-default-expr.min.stderr | 2 +- .../defaults/complex-generic-default-expr.rs | 7 +- ...fault-const-param-cannot-reference-self.rs | 16 + ...t-const-param-cannot-reference-self.stderr | 21 + .../dont-evaluate-array-len-on-err-1.stderr | 7 +- .../exhaustive-value.full.stderr | 8 +- .../exhaustive-value.min.stderr | 8 +- ...mpl-trait-with-const-arguments.full.stderr | 1 + ...impl-trait-with-const-arguments.min.stderr | 1 + .../{ => issues}/auxiliary/impl-const.rs | 0 .../ui/const-generics/issues/issue-61432.rs | 4 +- .../issue-61522-array-len-succ.full.stderr | 0 .../issue-61522-array-len-succ.min.stderr | 0 .../issue-61522-array-len-succ.rs | 0 ...96-impl-trait-for-str-const-arg.min.stderr | 0 ...ssue-66596-impl-trait-for-str-const-arg.rs | 0 .../{ => issues}/issue-67375.full.stderr | 0 .../{ => issues}/issue-67375.min.stderr | 0 .../{ => issues}/issue-67375.rs | 0 .../{ => issues}/issue-67945-1.full.stderr | 0 .../{ => issues}/issue-67945-1.min.stderr | 0 .../{ => issues}/issue-67945-1.rs | 0 .../{ => issues}/issue-67945-2.full.stderr | 0 .../{ => issues}/issue-67945-2.min.stderr | 0 .../{ => issues}/issue-67945-2.rs | 0 .../{ => issues}/issue-67945-3.full.stderr | 0 .../{ => issues}/issue-67945-3.min.stderr | 0 .../{ => issues}/issue-67945-3.rs | 0 .../issue-68104-print-stack-overflow.rs | 0 .../{ => issues}/issue-70180-1-stalled_on.rs | 0 .../{ => issues}/issue-70180-2-stalled_on.rs | 0 .../{ => issues}/issue-71202.rs | 0 .../{ => issues}/issue-71986.rs | 0 .../{ => issues}/issue-73899.rs | 0 .../{ => issues}/issue-74906.rs | 0 .../{ => issues}/issue-75763.rs | 0 ...9518-default_trait_method_normalization.rs | 0 ...-default_trait_method_normalization.stderr | 0 .../issue-80561-incorrect-param-env.rs | 0 .../ui/const-generics/issues/issue-83765.rs | 38 + .../const-generics/issues/issue-83765.stderr | 29 + .../ui/const-generics/issues/issue-85848.rs | 31 + .../const-generics/issues/issue-85848.stderr | 44 + .../ui/const-generics/issues/issue-86820.rs | 25 + .../const-generics/issues/issue-86820.stderr | 15 + .../ui/const-generics/issues/issue-87076.rs | 20 + ...const-expression-suggest-missing-braces.rs | 2 +- ...t-expression-suggest-missing-braces.stderr | 2 +- .../occurs-check/unused-substs-1.stderr | 16 +- src/test/ui/const-ptr/out_of_bounds_read.rs | 16 + .../ui/const-ptr/out_of_bounds_read.stderr | 70 + src/test/ui/const-ptr/ptr_to_usize_cast.rs | 13 - .../ui/const-ptr/ptr_to_usize_cast.stderr | 14 - ...inter-values-in-various-types.64bit.stderr | 28 +- src/test/ui/consts/const-eval/const_panic.rs | 22 +- .../ui/consts/const-eval/const_panic.stderr | 60 +- .../const-eval/const_panic_libcore_bin.rs | 6 +- .../const-eval/const_panic_libcore_bin.stderr | 18 +- .../const-eval/const_panic_track_caller.rs | 23 + .../const_panic_track_caller.stderr | 15 + .../consts/const-eval/const_raw_ptr_ops2.rs | 20 +- .../const-eval/const_raw_ptr_ops2.stderr | 37 +- src/test/ui/consts/const-eval/dangling.rs | 3 +- src/test/ui/consts/const-eval/dangling.stderr | 17 +- .../const-eval/heap/alloc_intrinsic_errors.rs | 3 +- .../heap/alloc_intrinsic_errors.stderr | 10 +- .../heap/alloc_intrinsic_uninit.32bit.stderr | 4 +- .../heap/alloc_intrinsic_uninit.64bit.stderr | 4 +- src/test/ui/consts/const-eval/issue-49296.rs | 3 +- .../ui/consts/const-eval/issue-49296.stderr | 11 +- src/test/ui/consts/const-eval/issue-52442.rs | 4 - .../ui/consts/const-eval/issue-52442.stderr | 12 - .../consts/const-eval/match-test-ptr-null.rs | 2 +- .../const-eval/match-test-ptr-null.stderr | 7 +- .../const-eval/panic-assoc-never-type.rs | 2 +- .../const-eval/panic-assoc-never-type.stderr | 6 +- .../ui/consts/const-eval/panic-never-type.rs | 2 +- .../consts/const-eval/panic-never-type.stderr | 6 +- .../consts/const-eval/promoted_raw_ptr_ops.rs | 2 +- .../const-eval/ref_to_int_match.32bit.stderr | 4 +- .../const-eval/ref_to_int_match.64bit.stderr | 4 +- .../ui/consts/const-eval/ub-enum.32bit.stderr | 36 +- .../ui/consts/const-eval/ub-enum.64bit.stderr | 36 +- .../ub-incorrect-vtable.32bit.stderr | 39 + .../ub-incorrect-vtable.64bit.stderr | 39 + .../consts/const-eval/ub-incorrect-vtable.rs | 31 +- .../const-eval/ub-incorrect-vtable.stderr | 27 - .../const-eval/ub-int-array.32bit.stderr | 6 +- .../const-eval/ub-int-array.64bit.stderr | 6 +- src/test/ui/consts/const-eval/ub-int-array.rs | 6 +- .../consts/const-eval/ub-nonnull.32bit.stderr | 33 +- .../consts/const-eval/ub-nonnull.64bit.stderr | 33 +- src/test/ui/consts/const-eval/ub-nonnull.rs | 3 +- .../consts/const-eval/ub-ref-ptr.32bit.stderr | 20 +- .../consts/const-eval/ub-ref-ptr.64bit.stderr | 20 +- .../const-eval/ub-uninhabit.32bit.stderr | 4 +- .../const-eval/ub-uninhabit.64bit.stderr | 4 +- .../consts/const-eval/ub-upvars.32bit.stderr | 4 +- .../consts/const-eval/ub-upvars.64bit.stderr | 4 +- .../const-eval/ub-wide-ptr.32bit.stderr | 24 +- .../const-eval/ub-wide-ptr.64bit.stderr | 24 +- .../ui/consts/const-eval/union-ice.stderr | 4 +- src/test/ui/consts/const-eval/unwind-abort.rs | 2 +- .../ui/consts/const-eval/unwind-abort.stderr | 5 +- .../validate_uninhabited_zsts.32bit.stderr | 21 +- .../validate_uninhabited_zsts.64bit.stderr | 21 +- .../const-eval/validate_uninhabited_zsts.rs | 3 +- .../const-extern-fn-min-const-fn.rs | 2 +- .../const-extern-fn-min-const-fn.stderr | 6 +- src/test/ui/consts/const-float-classify.rs | 4 +- src/test/ui/consts/const-int-unchecked.rs | 147 +- src/test/ui/consts/const-int-unchecked.stderr | 539 +- .../const-mut-refs/issue-76510.32bit.stderr | 36 + .../const-mut-refs/issue-76510.64bit.stderr | 36 + .../ui/consts/const-mut-refs/issue-76510.rs | 18 + .../mut_ref_in_final_dynamic_check.rs | 4 +- .../mut_ref_in_final_dynamic_check.stderr | 12 +- .../const-points-to-static.32bit.stderr | 2 +- .../const-points-to-static.64bit.stderr | 2 +- src/test/ui/consts/const-unwrap.rs | 5 +- src/test/ui/consts/const-unwrap.stderr | 17 +- .../ui/consts/const_unsafe_unreachable_ub.rs | 7 +- .../consts/const_unsafe_unreachable_ub.stderr | 38 +- .../control-flow/assert.const_panic.stderr | 6 +- src/test/ui/consts/control-flow/assert.rs | 2 +- src/test/ui/consts/copy-intrinsic.rs | 52 + src/test/ui/consts/copy-intrinsic.stderr | 27 + src/test/ui/consts/issue-17458.rs | 2 +- src/test/ui/consts/issue-17458.stderr | 7 +- src/test/ui/{issues => consts}/issue-17756.rs | 0 src/test/ui/consts/issue-39161-bogus-error.rs | 13 + src/test/ui/consts/issue-51559.rs | 8 - src/test/ui/consts/issue-51559.stderr | 14 - .../issue-52023-array-size-pointer-cast.rs | 2 +- ...issue-52023-array-size-pointer-cast.stderr | 7 +- src/test/ui/consts/issue-52432.rs | 10 - src/test/ui/consts/issue-52432.stderr | 28 - src/test/ui/consts/issue-63952.32bit.stderr | 2 +- src/test/ui/consts/issue-63952.64bit.stderr | 2 +- src/test/ui/{issues => consts}/issue-69532.rs | 0 src/test/ui/consts/issue-79690.64bit.stderr | 4 +- src/test/ui/consts/issue-83182.32bit.stderr | 4 +- src/test/ui/consts/issue-83182.64bit.stderr | 4 +- src/test/ui/consts/issue-83182.rs | 2 +- src/test/ui/consts/issue-87046.rs | 34 + src/test/ui/consts/issue-87046.stderr | 8 + src/test/ui/consts/large_const_alloc.rs | 18 + src/test/ui/consts/large_const_alloc.stderr | 15 + .../ui/consts/min_const_fn/min_const_fn.rs | 8 +- .../consts/min_const_fn/min_const_fn.stderr | 24 +- .../const_refers_to_static2.32bit.stderr | 4 +- .../const_refers_to_static2.64bit.stderr | 4 +- ..._refers_to_static_cross_crate.32bit.stderr | 4 +- ..._refers_to_static_cross_crate.64bit.stderr | 4 +- .../mutable_references_err.32bit.stderr | 10 +- .../mutable_references_err.64bit.stderr | 10 +- .../ui/consts/miri_unleashed/ptr_arith.rs | 13 +- .../ui/consts/miri_unleashed/ptr_arith.stderr | 17 +- src/test/ui/consts/miri_unleashed/tls.stderr | 4 +- src/test/ui/consts/offset_from_ub.rs | 20 +- src/test/ui/consts/offset_from_ub.stderr | 128 +- src/test/ui/consts/offset_ub.rs | 3 + src/test/ui/consts/offset_ub.stderr | 136 +- src/test/ui/consts/ptr_comparisons.rs | 12 +- src/test/ui/consts/ptr_comparisons.stderr | 31 +- .../rustc-const-stability-require-const.rs | 47 + ...rustc-const-stability-require-const.stderr | 86 + .../ui/consts/rustc-impl-const-stability.rs | 20 + src/test/ui/consts/std/alloc.32bit.stderr | 2 +- src/test/ui/consts/std/alloc.64bit.stderr | 2 +- .../consts/validate_never_arrays.32bit.stderr | 6 +- .../consts/validate_never_arrays.64bit.stderr | 6 +- .../ui/crate-loading/auxiliary/proc-macro.rs | 12 + .../cross-compiled-proc-macro.rs | 8 + src/test/ui/crate-loading/missing-std.rs | 1 + src/test/ui/crate-loading/missing-std.stderr | 2 +- .../ui/custom_test_frameworks/mismatch.stderr | 2 + ...duplicate-diagnostics-2.deduplicate.stderr | 30 - ...deduplicate-diagnostics-2.duplicate.stderr | 39 - src/test/ui/deduplicate-diagnostics-2.rs | 17 - .../ui/deprecation/deprecation-lint-3.stderr | 5 +- .../ui/deprecation/deprecation-lint.stderr | 108 +- src/test/ui/deprecation/suggestion.fixed | 14 + src/test/ui/deprecation/suggestion.rs | 14 + src/test/ui/deprecation/suggestion.stderr | 16 +- .../derive-on-trait-item-or-impl-item.rs | 4 +- .../derive-on-trait-item-or-impl-item.stderr | 14 +- ...ives-span-Clone-enum-struct-variant.stderr | 9 +- .../ui/derives/derives-span-Clone-enum.stderr | 9 +- .../derives/derives-span-Clone-struct.stderr | 9 +- .../derives-span-Clone-tuple-struct.stderr | 9 +- ...ives-span-Debug-enum-struct-variant.stderr | 7 +- .../ui/derives/derives-span-Debug-enum.stderr | 7 +- .../derives/derives-span-Debug-struct.stderr | 7 +- .../derives-span-Debug-tuple-struct.stderr | 7 +- .../derives-span-Default-struct.stderr | 9 +- .../derives-span-Default-tuple-struct.stderr | 9 +- ...derives-span-Eq-enum-struct-variant.stderr | 3 + .../ui/derives/derives-span-Eq-enum.stderr | 3 + .../ui/derives/derives-span-Eq-struct.stderr | 3 + .../derives-span-Eq-tuple-struct.stderr | 3 + ...rives-span-Hash-enum-struct-variant.stderr | 3 + .../ui/derives/derives-span-Hash-enum.stderr | 3 + .../derives/derives-span-Hash-struct.stderr | 3 + .../derives-span-Hash-tuple-struct.stderr | 3 + ...erives-span-Ord-enum-struct-variant.stderr | 9 +- .../ui/derives/derives-span-Ord-enum.stderr | 9 +- .../ui/derives/derives-span-Ord-struct.stderr | 9 +- .../derives-span-Ord-tuple-struct.stderr | 9 +- ...-span-PartialEq-enum-struct-variant.stderr | 6 + .../derives-span-PartialEq-enum.stderr | 6 + .../derives-span-PartialEq-struct.stderr | 6 + ...derives-span-PartialEq-tuple-struct.stderr | 6 + ...span-PartialOrd-enum-struct-variant.stderr | 9 +- .../derives-span-PartialOrd-enum.stderr | 9 +- .../derives-span-PartialOrd-struct.stderr | 9 +- ...erives-span-PartialOrd-tuple-struct.stderr | 9 +- src/test/ui/derives/deriving-copyclone.stderr | 21 +- ...eriving-no-inner-impl-error-message.stderr | 15 +- src/test/ui/derives/deriving-non-type.rs | 18 +- src/test/ui/derives/deriving-non-type.stderr | 54 +- src/test/ui/deriving/deriving-with-helper.rs | 36 + src/test/ui/did_you_mean/bad-assoc-ty.rs | 20 +- src/test/ui/did_you_mean/bad-assoc-ty.stderr | 20 +- src/test/ui/did_you_mean/issue-39544.rs | 2 +- src/test/ui/did_you_mean/issue-39544.stderr | 2 +- .../issue-39802-show-5-trait-impls.stderr | 24 +- src/test/ui/dyn-drop/dyn-drop.rs | 16 + src/test/ui/dyn-drop/dyn-drop.stderr | 38 + .../dyn-2015-edition-keyword-ident-lint.fixed | 31 +- .../dyn-2015-edition-keyword-ident-lint.rs | 31 +- ...dyn-2015-edition-keyword-ident-lint.stderr | 58 +- ...dyn-2015-idents-in-decl-macros-unlinted.rs | 5 +- .../dyn-2015-idents-in-macros-unlinted.rs | 5 +- .../dyn-2015-no-warnings-without-lints.rs | 5 +- .../ui/dyn-keyword/dyn-2018-edition-lint.rs | 6 +- .../dyn-keyword/dyn-2018-edition-lint.stderr | 6 +- .../issue-56327-dyn-trait-in-macro-is-okay.rs | 4 +- .../ui/dynamically-sized-types/dst-index.rs | 2 +- src/test/ui/editions/edition-feature-ok.rs | 2 +- .../edition-imports-virtual-2015-ambiguity.rs | 2 +- .../edition-keywords-2015-2015-expansion.rs | 2 +- .../edition-keywords-2018-2015-expansion.rs | 2 +- .../edition-raw-pointer-method-2015.rs | 2 +- .../edition-raw-pointer-method-2015.stderr | 2 +- ...orted_main_const_fn_item_type_forbidden.rs | 4 +- ...d_main_const_fn_item_type_forbidden.stderr | 25 +- src/test/ui/error-codes/E0038.stderr | 4 +- src/test/ui/error-codes/E0121.rs | 3 +- src/test/ui/error-codes/E0121.stderr | 4 +- src/test/ui/error-codes/E0283.stderr | 8 +- src/test/ui/error-codes/E0389.rs | 2 +- src/test/ui/error-codes/E0389.stderr | 2 +- src/test/ui/error-codes/E0396-fixed.rs | 3 +- src/test/ui/error-codes/E0396-fixed.stderr | 11 +- src/test/ui/error-codes/E0565.rs | 5 +- src/test/ui/error-codes/E0565.stderr | 8 +- src/test/ui/error-codes/E0624.stderr | 3 + src/test/ui/error-codes/E0777.stderr | 4 +- src/test/ui/explore-issue-38412.stderr | 30 + src/test/ui/extern/extern-main-issue-86110.rs | 7 + .../ui/extern/extern-main-issue-86110.stderr | 8 + src/test/ui/extern/extern-methods.rs | 4 +- src/test/ui/extern/extern-thiscall.rs | 4 +- .../extern/extern-types-distinct-types.stderr | 2 + src/test/ui/extern/extern-vectorcall.rs | 6 +- .../feature-gate-abi-avr-interrupt.rs | 50 +- .../feature-gate-abi-avr-interrupt.stderr | 123 +- .../feature-gate-abi-msp430-interrupt.rs | 37 +- .../feature-gate-abi-msp430-interrupt.stderr | 60 +- .../feature-gate-abi-x86-interrupt.rs | 28 + .../feature-gate-abi-x86-interrupt.stderr | 66 + src/test/ui/feature-gates/feature-gate-abi.rs | 64 +- .../ui/feature-gates/feature-gate-abi.stderr | 495 +- .../feature-gate-abi_amdgpu_kernel.rs | 30 + .../feature-gate-abi_amdgpu_kernel.stderr | 97 + .../ui/feature-gates/feature-gate-abi_ptx.rs | 26 + .../feature-gates/feature-gate-abi_ptx.stderr | 66 + .../feature-gate-associated_type_bounds.rs | 6 +- ...feature-gate-associated_type_bounds.stderr | 12 +- .../feature-gate-cfg-target-abi.rs | 11 + .../feature-gate-cfg-target-abi.stderr | 39 + .../ui/feature-gates/feature-gate-fn_align.rs | 4 + .../feature-gate-fn_align.stderr | 12 + .../feature-gate-impl_trait_in_bindings.rs | 11 - ...feature-gate-impl_trait_in_bindings.stderr | 25 - ...ture-gate-min_type_alias_impl_trait.stderr | 2 +- .../feature-gate-more-qualified-paths.stderr | 6 +- ...ature-gate-object_safe_for_dispatch.stderr | 8 +- .../feature-gate-optimize_attribute.stderr | 3 +- .../feature-gate-type_alias_impl_trait.rs | 2 +- .../feature-gate-type_alias_impl_trait.stderr | 15 +- .../feature-gates/feature-gate-vectorcall.rs | 31 + .../feature-gate-vectorcall.stderr | 59 + .../ui/feature-gates/feature-gate-wasm_abi.rs | 27 +- .../feature-gate-wasm_abi.stderr | 60 +- .../issue-43106-gating-of-derive.rs | 10 +- .../issue-43106-gating-of-derive.stderr | 43 +- src/test/ui/ffi_const2.stderr | 1 + src/test/ui/fmt/format-args-capture.rs | 16 +- src/test/ui/fmt/format-concat-span.rs | 15 + src/test/ui/fmt/format-concat-span.stderr | 11 + src/test/ui/fmt/ifmt-unimpl.stderr | 6 +- src/test/ui/fmt/issue-86085.rs | 6 + src/test/ui/fmt/issue-86085.stderr | 11 + src/test/ui/fn/issue-80179.rs | 4 +- src/test/ui/fn/issue-80179.stderr | 4 +- src/test/ui/for/for-c-in-str.stderr | 6 +- src/test/ui/for/for-loop-bogosity.stderr | 6 +- ...function-pointer-comparison-issue-54685.rs | 31 + src/test/ui/future-incompatible-lint-group.rs | 14 +- .../ui/future-incompatible-lint-group.stderr | 25 +- src/test/ui/generator/issue-68112.stderr | 4 +- .../generator/layout-error.full_tait.stderr | 18 +- .../ui/generator/layout-error.min_tait.stderr | 27 +- src/test/ui/generator/layout-error.rs | 6 +- ...ata-sufficient-for-layout.full_tait.stderr | 14 +- ...data-sufficient-for-layout.min_tait.stderr | 26 +- .../metadata-sufficient-for-layout.rs | 11 +- src/test/ui/generator/not-send-sync.stderr | 4 +- .../print/generator-print-verbose-1.stderr | 10 +- .../too-live-local-in-immovable-gen.rs | 2 +- .../too-live-local-in-immovable-gen.stderr | 2 +- src/test/ui/generator/yield-in-initializer.rs | 2 +- ...yield-outside-generator-issue-78653.stderr | 6 +- .../collections-project-default.rs | 3 +- .../collections-project-default.stderr | 2 +- .../generic-associated-types/collections.rs | 3 +- ...nst-generics-gat-in-trait-return-type-1.rs | 1 - ...nst-generics-gat-in-trait-return-type-2.rs | 1 - ...nst-generics-gat-in-trait-return-type-3.rs | 1 - .../constraint-assoc-type-suggestion.rs | 1 - .../constraint-assoc-type-suggestion.stderr | 13 +- .../construct_with_other_type.rs | 1 - .../empty_generics.rs | 1 - .../empty_generics.stderr | 2 +- .../gat-in-trait-path-undeclared-lifetime.rs | 1 - ...t-in-trait-path-undeclared-lifetime.stderr | 15 +- .../gat-in-trait-path.rs | 1 - .../gat-in-trait-path.stderr | 17 +- .../gat-incomplete-warning.rs | 1 - .../gat-incomplete-warning.stderr | 11 - .../gat-trait-path-generic-type-arg.rs | 1 - .../gat-trait-path-generic-type-arg.stderr | 15 +- .../gat-trait-path-missing-lifetime.rs | 1 - .../gat-trait-path-missing-lifetime.stderr | 19 +- .../gat-trait-path-parenthesised-args.rs | 3 +- .../gat-trait-path-parenthesised-args.stderr | 27 +- .../generic-associated-type-bounds.rs | 1 - .../generic-associated-types-where.rs | 1 - .../generic-associated-types-where.stderr | 4 +- ...ic_associated_type_undeclared_lifetimes.rs | 1 - ...ssociated_type_undeclared_lifetimes.stderr | 4 +- .../generic-associated-types/impl_bounds.rs | 1 - .../impl_bounds.stderr | 44 +- .../impl_bounds_ok.rs | 1 - .../issue-47206-where-clause.rs | 1 - .../issue-47206-where-clause.stderr | 2 +- .../issue-58694-parameter-out-of-range.rs | 1 - .../issue-62326-parameter-out-of-range.rs | 1 - .../issue-67510-pass.rs | 1 - .../issue-67510-pass.stderr | 17 +- .../generic-associated-types/issue-67510.rs | 1 - .../issue-67510.stderr | 15 +- .../issue-68641-check-gat-bounds.rs | 1 - .../issue-68641-check-gat-bounds.stderr | 13 +- .../issue-68642-broken-llvm-ir.rs | 1 - .../issue-68642-broken-llvm-ir.stderr | 13 +- .../issue-68643-broken-mir.rs | 1 - .../issue-68643-broken-mir.stderr | 13 +- .../issue-68644-codegen-selection.rs | 1 - .../issue-68644-codegen-selection.stderr | 13 +- .../issue-68645-codegen-fulfillment.rs | 1 - .../issue-68645-codegen-fulfillment.stderr | 13 +- .../generic-associated-types/issue-68648-1.rs | 1 - .../issue-68648-1.stderr | 11 - .../generic-associated-types/issue-68648-2.rs | 1 - .../issue-68648-2.stderr | 13 +- .../issue-68649-pass.rs | 1 - .../issue-68649-pass.stderr | 11 - .../generic-associated-types/issue-68653.rs | 1 - .../issue-68656-unsized-values.rs | 1 - .../issue-68656-unsized-values.stderr | 13 +- .../generic-associated-types/issue-70303.rs | 1 - .../generic-associated-types/issue-70304.rs | 1 - .../issue-70304.stderr | 2 +- .../generic-associated-types/issue-71176.rs | 1 - .../issue-71176.stderr | 4 +- .../generic-associated-types/issue-74684-1.rs | 1 - .../issue-74684-1.stderr | 13 +- .../generic-associated-types/issue-74684-2.rs | 1 - .../issue-74684-2.stderr | 13 +- .../generic-associated-types/issue-74816.rs | 1 - .../issue-74816.stderr | 4 +- .../generic-associated-types/issue-74824.rs | 1 - .../issue-74824.stderr | 4 +- .../generic-associated-types/issue-76407.rs | 27 + .../generic-associated-types/issue-76535.rs | 1 - .../issue-76535.stderr | 23 +- .../generic-associated-types/issue-76826.rs | 44 + ...e-78113-lifetime-mismatch-dyn-trait-box.rs | 40 + ...113-lifetime-mismatch-dyn-trait-box.stderr | 87 + .../generic-associated-types/issue-78671.rs | 1 - .../issue-78671.stderr | 8 +- .../generic-associated-types/issue-79422.rs | 1 - .../issue-79422.stderr | 12 +- .../generic-associated-types/issue-79636-1.rs | 1 - .../issue-79636-1.stderr | 4 +- .../generic-associated-types/issue-79636-2.rs | 1 - .../issue-79636-2.stderr | 4 +- .../issue-80433-reduced.rs | 1 - .../generic-associated-types/issue-80433.rs | 1 - .../issue-80433.stderr | 4 +- .../generic-associated-types/issue-81487.rs | 19 + .../issue-81712-cyclic-traits.rs | 1 - .../issue-81712-cyclic-traits.stderr | 4 +- .../generic-associated-types/issue-81862.rs | 1 - .../issue-81862.stderr | 4 +- .../generic-associated-types/issue-86483.rs | 14 + .../issue-86483.stderr | 36 + .../ui/generic-associated-types/iterable.rs | 1 - .../method-unsatified-assoc-type-predicate.rs | 3 - ...hod-unsatified-assoc-type-predicate.stderr | 13 +- .../missing_lifetime_args.rs | 1 - .../missing_lifetime_args.stderr | 23 +- .../missing_lifetime_const.rs | 1 - .../missing_lifetime_const.stderr | 15 +- .../parameter_number_and_kind.rs | 1 - .../parameter_number_and_kind.stderr | 12 +- .../parameter_number_and_kind_impl.rs | 1 - .../parameter_number_and_kind_impl.stderr | 12 +- .../parse/trait-path-expected-token.rs | 1 - .../parse/trait-path-expected-token.stderr | 13 +- .../parse/trait-path-expressions.rs | 1 - .../parse/trait-path-expressions.stderr | 15 +- .../parse/trait-path-missing-gen_arg.rs | 1 - .../parse/trait-path-missing-gen_arg.stderr | 21 +- .../parse/trait-path-segments.rs | 1 - .../parse/trait-path-segments.stderr | 17 +- .../trait-path-type-error-once-implemented.rs | 1 - ...it-path-type-error-once-implemented.stderr | 19 +- .../parse/trait-path-types.rs | 1 - .../parse/trait-path-types.stderr | 17 +- .../pointer_family.rs | 1 - .../projection-bound-cycle-generic.rs | 1 - .../projection-bound-cycle-generic.stderr | 13 +- .../projection-bound-cycle.rs | 1 - .../projection-bound-cycle.stderr | 13 +- .../projection-type-lifetime-mismatch.rs | 1 - .../projection-type-lifetime-mismatch.stderr | 6 +- .../ui/generic-associated-types/shadowing.rs | 1 - .../generic-associated-types/shadowing.stderr | 8 +- .../streaming_iterator.rs | 1 - .../generic-associated-types/trait-objects.rs | 1 - .../trait-objects.stderr | 6 +- .../unsatified-item-lifetime-bound.rs | 1 - .../unsatified-item-lifetime-bound.stderr | 20 +- .../unsatisfied-outlives-bound.rs | 1 - .../unsatisfied-outlives-bound.stderr | 8 +- .../variance_constraints.rs | 1 - ...efault-type-param-cannot-reference-self.rs | 12 +- ...lt-type-param-cannot-reference-self.stderr | 24 +- .../feature-gate-half-open-range-patterns.rs | 8 +- ...ature-gate-half-open-range-patterns.stderr | 33 +- .../range_pat_interactions0.rs | 32 + .../range_pat_interactions1.rs | 29 + .../range_pat_interactions1.stderr | 36 + .../range_pat_interactions2.rs | 21 + .../range_pat_interactions2.stderr | 17 + .../range_pat_interactions3.rs | 24 + .../range_pat_interactions3.stderr | 57 + .../slice_pattern_syntax_problem0.rs | 16 + .../slice_pattern_syntax_problem0.stderr | 9 + .../slice_pattern_syntax_problem1.rs | 9 + .../slice_pattern_syntax_problem1.stderr | 39 + .../slice_pattern_syntax_problem2.rs | 10 + src/test/ui/hygiene/unpretty-debug.stdout | 10 +- .../path-elided.stderr | 2 + .../trait-elided.stderr | 2 + src/test/ui/impl-trait/auto-trait-leak.rs | 1 - src/test/ui/impl-trait/auto-trait-leak.stderr | 34 +- .../ui/impl-trait/binding-without-value.rs | 9 - .../impl-trait/binding-without-value.stderr | 16 - src/test/ui/impl-trait/bindings-opaque.rs | 17 - src/test/ui/impl-trait/bindings-opaque.stderr | 30 - src/test/ui/impl-trait/bindings.rs | 30 - src/test/ui/impl-trait/bindings.stderr | 44 - .../ui/impl-trait/bound-normalization-fail.rs | 15 +- .../bound-normalization-fail.stderr | 33 +- .../bound-normalization-pass.default.stderr | 11 - .../ui/impl-trait/bound-normalization-pass.rs | 36 +- .../bound-normalization-pass.sa.stderr | 11 - .../impl-trait-in-bindings-issue-73003.rs | 8 - .../impl-trait-in-bindings-issue-73003.stderr | 11 - .../ui/impl-trait/impl-trait-in-bindings.rs | 49 - .../impl-trait/impl-trait-in-bindings.stderr | 11 - src/test/ui/impl-trait/issue-57200.rs | 15 - src/test/ui/impl-trait/issue-57200.stderr | 8 - src/test/ui/impl-trait/issue-57201.rs | 15 - src/test/ui/impl-trait/issue-57201.stderr | 8 - src/test/ui/impl-trait/issue-60473.rs | 15 - src/test/ui/impl-trait/issue-60473.stderr | 15 - src/test/ui/impl-trait/issue-67166.rs | 11 - src/test/ui/impl-trait/issue-67166.stderr | 15 - src/test/ui/impl-trait/issue-69840.rs | 16 - src/test/ui/impl-trait/issue-86465.rs | 10 + src/test/ui/impl-trait/issue-86465.stderr | 14 + src/test/ui/impl-trait/issues/issue-54600.rs | 7 + .../ui/impl-trait/issues/issue-54600.stderr | 9 + src/test/ui/impl-trait/issues/issue-54840.rs | 7 + .../ui/impl-trait/issues/issue-54840.stderr | 9 + src/test/ui/impl-trait/issues/issue-58504.rs | 12 + .../ui/impl-trait/issues/issue-58504.stderr | 9 + src/test/ui/impl-trait/issues/issue-58956.rs | 14 + .../ui/impl-trait/issues/issue-58956.stderr | 15 + .../issues/issue-70877.full_tait.stderr | 2 +- .../issues/issue-70877.min_tait.stderr | 2 +- src/test/ui/impl-trait/issues/issue-70877.rs | 1 - src/test/ui/impl-trait/issues/issue-70971.rs | 4 + .../ui/impl-trait/issues/issue-70971.stderr | 9 + src/test/ui/impl-trait/issues/issue-78721.rs | 15 - .../ui/impl-trait/issues/issue-78721.stderr | 31 - .../issues/issue-78722.full_tait.stderr | 41 +- .../issues/issue-78722.min_tait.stderr | 42 +- src/test/ui/impl-trait/issues/issue-78722.rs | 5 +- src/test/ui/impl-trait/issues/issue-79099.rs | 10 + .../ui/impl-trait/issues/issue-79099.stderr | 20 + ...sue-83929-impl-trait-in-generic-default.rs | 4 +- ...83929-impl-trait-in-generic-default.stderr | 4 +- src/test/ui/impl-trait/issues/issue-84919.rs | 9 + .../ui/impl-trait/issues/issue-84919.stderr | 9 + src/test/ui/impl-trait/issues/issue-86201.rs | 13 + .../ui/impl-trait/issues/issue-86201.stderr | 21 + src/test/ui/impl-trait/issues/issue-86642.rs | 8 + .../ui/impl-trait/issues/issue-86642.stderr | 9 + src/test/ui/impl-trait/issues/issue-87295.rs | 18 + .../ui/impl-trait/issues/issue-87295.stderr | 9 + .../issues/universal-issue-48703.stderr | 1 + ...sal-turbofish-in-method-issue-50950.stderr | 1 + ...t_outlive_least_region_or_bound.nll.stderr | 4 +- .../ui/impl-trait/nested_impl_trait.stderr | 4 +- .../recursive-impl-trait-type-indirect.stderr | 4 +- .../static-return-lifetime-infered.nll.stderr | 4 +- src/test/ui/impl-trait/where-allowed.rs | 82 +- src/test/ui/impl-trait/where-allowed.stderr | 84 +- ...infer-async-enabled-impl-trait-bindings.rs | 17 - ...r-async-enabled-impl-trait-bindings.stderr | 21 - .../inference-variable-behind-raw-pointer.rs | 2 +- ...ference-variable-behind-raw-pointer.stderr | 2 +- src/test/ui/inference/issue-70703.rs | 26 + .../intrinsic-raw_eq-const-padding.rs | 11 + .../intrinsic-raw_eq-const-padding.stderr | 9 + .../ui/intrinsics/intrinsic-raw_eq-const.rs | 27 + .../ui/{ => intrinsics}/non-integer-atomic.rs | 0 .../non-integer-atomic.stderr | 0 .../codegen-option-without-group.rs | 1 + .../codegen-option-without-group.stderr | 2 + .../debug-option-without-group.rs | 1 + .../debug-option-without-group.stderr | 2 + src/test/ui/issues/issue-10412.stderr | 2 + src/test/ui/issues/issue-12997-2.stderr | 2 + src/test/ui/issues/issue-17651.stderr | 6 +- src/test/ui/issues/issue-18294.rs | 2 +- src/test/ui/issues/issue-18294.stderr | 7 +- src/test/ui/issues/issue-18611.stderr | 11 +- src/test/ui/issues/issue-18959.stderr | 4 +- src/test/ui/issues/issue-19380.stderr | 4 +- src/test/ui/issues/issue-20427.rs | 1 - src/test/ui/issues/issue-20605.stderr | 6 +- src/test/ui/issues/issue-20644.rs | 4 +- .../ui/issues/issue-20831-debruijn.stderr | 8 +- src/test/ui/issues/issue-21160.stderr | 2 + src/test/ui/issues/issue-21202.stderr | 5 + src/test/ui/issues/issue-22992.rs | 1 - .../issue-23338-ensure-param-drop-order.rs | 2 - .../ui/issues/issue-27401-dropflag-reinit.rs | 1 - src/test/ui/issues/issue-27895.rs | 10 - src/test/ui/issues/issue-27895.stderr | 9 - src/test/ui/issues/issue-28098.stderr | 36 +- src/test/ui/issues/issue-29147.stderr | 8 +- src/test/ui/issues/issue-31109.rs | 6 - src/test/ui/issues/issue-31109.stderr | 8 - src/test/ui/issues/issue-32709.stderr | 6 +- src/test/ui/issues/issue-3290.rs | 1 + src/test/ui/issues/issue-33941.stderr | 12 +- src/test/ui/issues/issue-34229.stderr | 10 +- src/test/ui/issues/issue-3763.stderr | 6 + src/test/ui/issues/issue-39970.stderr | 8 +- src/test/ui/issues/issue-41255.rs | 24 - src/test/ui/issues/issue-41255.stderr | 132 +- src/test/ui/issues/issue-43023.rs | 6 +- src/test/ui/issues/issue-43023.stderr | 22 +- src/test/ui/issues/issue-43205.rs | 2 +- src/test/ui/issues/issue-43623.stderr | 2 +- src/test/ui/issues/issue-43988.rs | 4 +- src/test/ui/issues/issue-43988.stderr | 18 +- src/test/ui/issues/issue-47412.mir.stderr | 2 +- src/test/ui/issues/issue-47412.rs | 3 +- src/test/ui/issues/issue-47412.thir.stderr | 12 +- src/test/ui/issues/issue-47715.stderr | 8 +- src/test/ui/issues/issue-49934.rs | 10 +- src/test/ui/issues/issue-49934.stderr | 30 +- src/test/ui/issues/issue-51244.rs | 2 +- src/test/ui/issues/issue-51244.stderr | 2 +- src/test/ui/issues/issue-51515.rs | 4 +- src/test/ui/issues/issue-51515.stderr | 4 +- src/test/ui/issues/issue-51714.rs | 16 +- src/test/ui/issues/issue-51714.stderr | 60 +- src/test/ui/issues/issue-5280.rs | 2 +- src/test/ui/issues/issue-53498.stderr | 3 + src/test/ui/issues/issue-54696.rs | 4 +- src/test/ui/issues/issue-58022.stderr | 8 +- src/test/ui/issues/issue-59488.stderr | 5 - src/test/ui/issues/issue-60283.stderr | 2 +- src/test/ui/issues/issue-66353.stderr | 9 +- src/test/ui/issues/issue-6804.rs | 4 - src/test/ui/issues/issue-6804.stderr | 22 +- .../issue-69396-const-no-type-in-macro.rs | 2 +- .../issue-69396-const-no-type-in-macro.stderr | 4 +- ...70724-add_type_neq_err_label-unwrap.stderr | 5 - src/test/ui/issues/issue-72690.stderr | 42 +- src/test/ui/issues/issue-73886.stderr | 4 +- src/test/ui/issues/issue-87199.rs | 20 + src/test/ui/issues/issue-87199.stderr | 36 + src/test/ui/iterators/integral.stderr | 72 +- .../ui/iterators/into-iter-on-arrays-2018.rs | 12 +- .../iterators/into-iter-on-arrays-2018.stderr | 58 +- .../iterators/into-iter-on-arrays-lint.fixed | 49 +- .../ui/iterators/into-iter-on-arrays-lint.rs | 49 +- .../iterators/into-iter-on-arrays-lint.stderr | 304 +- src/test/ui/iterators/ranges.stderr | 12 +- src/test/ui/iterators/string.stderr | 12 +- .../keyword-self-as-type-param.rs} | 2 + .../keyword-self-as-type-param.stderr} | 6 +- src/test/ui/lang-items/issue-86238.rs | 16 + src/test/ui/lang-items/issue-86238.stderr | 10 + ...ssue-69485-var-size-diffs-too-large.stderr | 4 +- src/test/ui/lint/bare-trait-objects-path.rs | 6 +- .../ui/lint/bare-trait-objects-path.stderr | 6 +- .../lint/cli-lint-override.forbid_warn.stderr | 11 + .../cli-lint-override.force_warn_deny.stderr | 11 + src/test/ui/lint/cli-lint-override.rs | 17 + .../lint/cli-lint-override.warn_deny.stderr | 11 + src/test/ui/lint/cli-unknown-force-warn.rs | 7 + .../ui/lint/cli-unknown-force-warn.stderr | 15 + .../lint/command-line-register-lint-tool.rs | 7 + ...command-line-register-unknown-lint-tool.rs | 4 + ...and-line-register-unknown-lint-tool.stderr | 11 + src/test/ui/lint/dead-code/self-assign.rs | 52 + src/test/ui/lint/dead-code/self-assign.stderr | 44 + .../force-allowed-by-default-lint.rs | 2 +- .../force-allowed-by-default-lint.stderr | 2 +- .../force-allowed-deny-by-default-lint.rs | 2 +- .../force-allowed-deny-by-default-lint.stderr | 2 +- .../lint/force-warn/force-allowed-warning.rs | 2 +- .../force-warn/force-allowed-warning.stderr | 2 +- .../force-warn/force-deny-by-default-lint.rs | 2 +- .../force-deny-by-default-lint.stderr | 2 +- .../force-lint-allow-all-warnings.rs | 2 +- .../force-lint-allow-all-warnings.stderr | 2 +- .../force-lint-group-allow-all-warnings.rs | 2 +- ...force-lint-group-allow-all-warnings.stderr | 2 +- .../force-warn/force-lint-in-allowed-group.rs | 4 +- .../force-lint-in-allowed-group.stderr | 4 +- .../force-warn/force-warn-cap-lints-allow.rs | 10 + .../force-warn-cap-lints-allow.stderr | 12 + .../force-warn/force-warn-cap-lints-warn.rs | 15 + .../force-warn-cap-lints-warn.stderr | 12 + .../force-warn-group-allow-warning.rs | 4 +- .../force-warn-group-allow-warning.stderr | 4 +- .../ui/lint/force-warn/force-warn-group.rs | 4 +- .../lint/force-warn/force-warn-group.stderr | 4 +- src/test/ui/lint/future-incompat-test.rs | 10 + src/test/ui/lint/future-incompat-test.stderr | 9 + .../lint/inclusive-range-pattern-syntax.fixed | 4 +- .../ui/lint/inclusive-range-pattern-syntax.rs | 4 +- .../inclusive-range-pattern-syntax.stderr | 4 +- .../issue-78660-cap-lints-future-compat.rs | 10 - ...issue-78660-cap-lints-future-compat.stderr | 11 - src/test/ui/lint/issue-83477.rs | 3 +- src/test/ui/lint/issue-83477.stderr | 6 +- src/test/ui/lint/issue-86600-lint-twice.rs | 15 + .../ui/lint/issue-86600-lint-twice.stderr | 12 + src/test/ui/lint/issue-87274-paren-parent.rs | 9 + .../ui/lint/issue-87274-paren-parent.stderr | 10 + .../lint-pre-expansion-extern-module.stderr | 2 +- .../ui/lint/lint-stability-deprecated.stderr | 112 +- src/test/ui/lint/lint-stability3.stderr | 5 +- src/test/ui/lint/lint-unknown-lint.rs | 4 + src/test/ui/lint/lint-unknown-lint.stderr | 8 +- src/test/ui/lint/missing-doc-private-macro.rs | 43 + .../ui/lint/missing-doc-private-macro.stderr | 20 + .../semicolon-in-expressions-from-macros.rs | 24 +- ...emicolon-in-expressions-from-macros.stderr | 29 +- src/test/ui/lint/unused-borrows.rs | 33 + src/test/ui/lint/unused-borrows.stderr | 44 + src/test/ui/lto-duplicate-symbols.stderr | 2 +- src/test/ui/macros/assert-macro-owned.rs | 2 +- src/test/ui/macros/auxiliary/or-pattern.rs | 6 + src/test/ui/{issues => macros}/issue-52169.rs | 0 ...e-84632-eager-expansion-recursion-limit.rs | 16 + ...632-eager-expansion-recursion-limit.stderr | 14 + .../ui/macros/macro-comma-behavior-rpass.rs | 17 +- .../macro-or-patterns-back-compat.fixed | 25 +- .../macros/macro-or-patterns-back-compat.rs | 25 +- .../macro-or-patterns-back-compat.stderr | 25 +- src/test/ui/macros/trace_faulty_macros.rs | 2 +- src/test/ui/macros/trace_faulty_macros.stderr | 6 +- src/test/ui/mir/issue-75053.full_tait.stderr | 12 +- .../ui/mir/issue-75053.in_bindings.stderr | 23 +- src/test/ui/mir/issue-75053.min_tait.stderr | 12 +- src/test/ui/mir/issue-75053.rs | 7 +- .../issue-83499-input-output-iteration-ice.rs | 2 +- ...ue-83499-input-output-iteration-ice.stderr | 2 +- ...ased-on-type-no-recursive-stack-closure.rs | 2 +- src/test/ui/mut/mutable-class-fields-2.stderr | 2 +- ...535-allow-mutable-borrow-in-match-guard.rs | 0 src/test/ui/{issues => nll}/issue-45157.rs | 0 .../ui/{issues => nll}/issue-45157.stderr | 0 src/test/ui/nll/issue-47388.stderr | 2 +- .../ui/nll/issue-50461-used-mut-from-moves.rs | 1 + src/test/ui/nll/issue-51244.rs | 2 +- src/test/ui/nll/issue-51244.stderr | 2 +- src/test/ui/nll/issue-57989.rs | 2 +- src/test/ui/nll/issue-57989.stderr | 2 +- .../ui/nll/normalization-bounds-error.stderr | 8 +- src/test/ui/non-constant-in-const-path.rs | 7 - src/test/ui/non-constant-in-const-path.stderr | 9 - src/test/ui/non-fmt-panic.stderr | 38 +- src/test/ui/nullable-pointer-iotareduction.rs | 2 +- .../ui/on-unimplemented/multiple-impls.stderr | 24 +- src/test/ui/on-unimplemented/no-debug.stderr | 6 +- src/test/ui/on-unimplemented/on-impl.stderr | 8 +- .../ui/{issues => packed}/issue-27060-2.rs | 0 .../{issues => packed}/issue-27060-2.stderr | 0 .../{issues => packed}/issue-27060-rpass.rs | 0 src/test/ui/{issues => packed}/issue-27060.rs | 0 .../ui/{issues => packed}/issue-27060.stderr | 0 .../ui/panic-runtime/incompatible-type.rs | 24 + src/test/ui/panics/explicit-panic-msg.rs | 2 +- src/test/ui/panics/panic-macro-any-wrapped.rs | 2 +- src/test/ui/panics/panic-macro-any.rs | 2 +- src/test/ui/parser/expr-as-stmt.fixed | 1 + src/test/ui/parser/expr-as-stmt.rs | 1 + src/test/ui/parser/expr-as-stmt.stderr | 18 +- src/test/ui/parser/float-literals.rs | 9 + .../impl-item-type-no-body-semantic-fail.rs | 1 - ...mpl-item-type-no-body-semantic-fail.stderr | 31 +- .../ui/{issues => parser}/issue-48636.fixed | 0 src/test/ui/{issues => parser}/issue-48636.rs | 0 .../ui/{issues => parser}/issue-48636.stderr | 0 .../ui/{issues => parser}/issue-54521-1.rs | 0 .../ui/{issues => parser}/issue-54521-2.fixed | 0 .../ui/{issues => parser}/issue-54521-2.rs | 0 .../{issues => parser}/issue-54521-2.stderr | 0 .../issue-54521-3.fixed} | 0 .../issue-54521-3.rs} | 0 .../issue-54521-3.stderr} | 8 +- src/test/ui/parser/issue-68890-2.rs | 2 +- src/test/ui/parser/issue-68890-2.stderr | 2 +- .../parser/issue-73568-lifetime-after-mut.rs | 4 +- .../issue-73568-lifetime-after-mut.stderr | 4 +- src/test/ui/parser/issue-86895.rs | 3 + src/test/ui/parser/issue-86895.stderr | 8 + .../ui/parser/issue-87086-colon-path-sep.rs | 66 + .../parser/issue-87086-colon-path-sep.stderr | 68 + .../macro/trait-object-macro-matcher.rs | 2 +- .../macro/trait-object-macro-matcher.stderr | 2 +- .../ui/parser/parser-unicode-whitespace.rs | 2 +- .../ui/parser/range-inclusive-extra-equals.rs | 10 + .../range-inclusive-extra-equals.stderr | 10 + src/test/ui/parser/recover-range-pats.rs | 18 +- src/test/ui/parser/recover-range-pats.stderr | 18 +- src/test/ui/parser/recover-ref-dyn-mut.rs | 9 + src/test/ui/parser/recover-ref-dyn-mut.stderr | 15 + .../ui/parser/struct-literal-in-for.stderr | 6 +- .../ui/parser/trait-object-trait-parens.rs | 6 +- .../parser/trait-object-trait-parens.stderr | 6 +- .../variadic-ffi-semantic-restrictions.rs | 40 +- .../variadic-ffi-semantic-restrictions.stderr | 40 +- .../issue-68394-let-pat-runtime-value.rs | 5 - .../issue-68394-let-pat-runtime-value.stderr | 9 - .../ui/pattern/issue-68396-let-float-bug.rs | 7 - .../pattern/issue-68396-let-float-bug.stderr | 15 - ...opaquely-typed-constant-used-in-pattern.rs | 10 - ...uely-typed-constant-used-in-pattern.stderr | 8 - .../borrowck-move-ref-pattern.rs | 4 +- .../borrowck-move-ref-pattern.stderr | 4 +- .../ui/pattern/non-constant-in-const-path.rs | 18 + .../pattern/non-constant-in-const-path.stderr | 28 + src/test/ui/privacy/privacy1.stderr | 15 + .../ui/privacy/private-impl-method.stderr | 3 + .../privacy/private-method-cross-crate.stderr | 5 + .../privacy/private-method-inherited.stderr | 3 + src/test/ui/privacy/private-method.stderr | 3 + src/test/ui/privacy/restricted/test.stderr | 16 + .../proc-macro/attributes-on-modules-fail.rs | 2 +- .../attributes-on-modules-fail.stderr | 6 +- .../proc-macro/auxiliary/call-deprecated.rs | 19 + src/test/ui/proc-macro/call-deprecated.rs | 34 + src/test/ui/proc-macro/call-deprecated.stderr | 16 + .../group-compat-hack.stderr | 10 +- .../issue-73933-procedural-masquerade.stderr | 2 +- .../proc-macro/issue-86781-bad-inner-doc.rs | 11 + .../issue-86781-bad-inner-doc.stderr | 11 + .../ui/proc-macro/macros-in-extern-derive.rs | 2 +- .../proc-macro/macros-in-extern-derive.stderr | 6 +- .../ui/proc-macro/meta-macro-hygiene.stdout | 36 +- .../nonterminal-token-hygiene.stdout | 36 +- .../ui/proc-macro/span-from-proc-macro.stderr | 12 +- .../process-termination-blocking-io.rs | 2 +- src/test/ui/range/range-1.stderr | 6 +- .../range-inclusive-pattern-precedence.fixed | 2 +- .../range-inclusive-pattern-precedence.rs | 2 +- .../range-inclusive-pattern-precedence.stderr | 2 +- .../range-inclusive-pattern-precedence2.rs | 2 +- ...range-inclusive-pattern-precedence2.stderr | 2 +- src/test/ui/range/range_traits-1.stderr | 108 +- src/test/ui/recursion_limit/empty.rs | 2 + src/test/ui/recursion_limit/empty.stderr | 10 +- src/test/ui/recursion_limit/invalid_digit.rs | 3 +- .../ui/recursion_limit/invalid_digit.stderr | 10 +- src/test/ui/recursion_limit/overflow.rs | 2 + src/test/ui/recursion_limit/overflow.stderr | 10 +- src/test/ui/repr/issue-83505-repr-simd.rs | 10 + src/test/ui/repr/issue-83505-repr-simd.stderr | 30 + src/test/ui/repr/issue-83921-ice.rs | 34 + src/test/ui/repr/issue-83921-ice.stderr | 46 + .../ui/repr/issue-83921-pretty.normal.stderr | 9 + .../ui/repr/issue-83921-pretty.pretty.stdout | 19 + src/test/ui/repr/issue-83921-pretty.rs | 14 + src/test/ui/repr/repr-disallow-on-variant.rs | 2 +- .../ui/repr/repr-disallow-on-variant.stderr | 4 +- src/test/ui/repr/repr-transparent.rs | 32 +- src/test/ui/repr/repr-transparent.stderr | 82 +- .../ui/resolve/use_suggestion_placement.fixed | 39 + .../ui/resolve/use_suggestion_placement.rs | 9 +- .../resolve/use_suggestion_placement.stderr | 6 +- src/test/ui/retslot-cast.stderr | 3 + .../issue-86188-return-not-in-fn-body.rs | 41 + .../issue-86188-return-not-in-fn-body.stderr | 52 + .../ui/return/return-match-array-const.rs | 15 +- .../ui/return/return-match-array-const.stderr | 55 +- .../match-forbidden-without-eq.rs | 2 - .../match-forbidden-without-eq.stderr | 11 +- .../termination-trait-test-wrong-type.stderr | 2 + .../ui/rfc-2005-default-binding-mode/enum.rs | 6 +- .../rfc-2005-default-binding-mode/enum.stderr | 6 +- .../explicit-mut.rs | 6 +- .../explicit-mut.stderr | 6 +- .../tracked-trait-obj.rs | 56 +- .../dbg-macro-requires-debug.stderr | 4 +- .../disallowed-positions.stderr | 54 +- .../multiple-declarations.rs | 19 + .../multiple-declarations.stderr | 17 + .../ui/rfc-2627-raw-dylib/unsupported-abi.rs | 13 + .../rfc-2627-raw-dylib/unsupported-abi.stderr | 8 + .../rfc-2632-const-trait-impl/assoc-type.rs | 1 - .../rfc-2632-const-trait-impl/attr-misuse.rs | 13 + .../attr-misuse.stderr | 32 + .../auxiliary/cross-crate.rs | 21 + .../auxiliary/staged-api.rs | 21 + .../call-const-trait-method-fail.rs | 1 - .../call-const-trait-method-fail.stderr | 2 +- .../call-const-trait-method-pass.rs | 4 +- .../call-generic-in-impl.rs | 15 + .../call-generic-method-chain.rs | 4 +- .../call-generic-method-dup-bound.rs | 3 + .../call-generic-method-nonconst.rs | 1 - .../call-generic-method-pass.rs | 4 +- .../const-and-non-const-impl.rs | 1 - .../const-and-non-const-impl.stderr | 6 +- .../const-check-fns-in-const-impl.rs | 1 - .../const-check-fns-in-const-impl.stderr | 2 +- .../const-default-method-bodies.rs | 30 + .../const-default-method-bodies.stderr | 9 + .../const-impl-norecover.rs | 1 - .../const-impl-norecover.stderr | 2 +- .../const-impl-recovery.rs | 1 - .../const-impl-recovery.stderr | 4 +- .../cross-crate.gated.stderr | 9 + .../rfc-2632-const-trait-impl/cross-crate.rs | 21 + .../cross-crate.stock.stderr | 15 + .../feature-gate.gated.stderr | 2 +- .../rfc-2632-const-trait-impl/feature-gate.rs | 1 - .../feature-gate.stock.stderr | 2 +- .../generic-bound.rs | 1 - .../hir-const-check.rs | 1 - .../hir-const-check.stderr | 2 +- .../impl-with-default-fn.rs | 37 + .../impl-with-default-fn.stderr | 33 + .../ui/rfc-2632-const-trait-impl/stability.rs | 1 - .../stability.stderr | 4 +- .../rfc-2632-const-trait-impl/staged-api.rs | 39 + .../staged-api.staged.stderr | 10 + .../staged-api.stock.stderr | 18 + .../ui/rfc-2632-const-trait-impl/syntax.rs | 1 - src/test/ui/rt-explody-panic-payloads.rs | 30 + src/test/ui/rust-2018/async-ident-allowed.rs | 2 +- .../ui/rust-2018/async-ident-allowed.stderr | 2 +- src/test/ui/rust-2018/async-ident.fixed | 30 +- src/test/ui/rust-2018/async-ident.rs | 30 +- src/test/ui/rust-2018/async-ident.stderr | 30 +- src/test/ui/rust-2018/dyn-keyword.fixed | 2 +- src/test/ui/rust-2018/dyn-keyword.rs | 2 +- src/test/ui/rust-2018/dyn-keyword.stderr | 2 +- .../edition-lint-fully-qualified-paths.fixed | 7 +- .../edition-lint-fully-qualified-paths.rs | 7 +- .../edition-lint-fully-qualified-paths.stderr | 8 +- .../edition-lint-nested-empty-paths.fixed | 6 +- .../edition-lint-nested-empty-paths.rs | 6 +- .../edition-lint-nested-empty-paths.stderr | 6 +- .../rust-2018/edition-lint-nested-paths.fixed | 4 +- .../ui/rust-2018/edition-lint-nested-paths.rs | 4 +- .../edition-lint-nested-paths.stderr | 4 +- .../ui/rust-2018/edition-lint-paths.fixed | 27 +- src/test/ui/rust-2018/edition-lint-paths.rs | 29 +- .../ui/rust-2018/edition-lint-paths.stderr | 32 +- .../ui/rust-2018/extern-crate-rename.fixed | 2 +- src/test/ui/rust-2018/extern-crate-rename.rs | 2 +- .../ui/rust-2018/extern-crate-rename.stderr | 2 +- .../ui/rust-2018/extern-crate-submod.fixed | 2 +- src/test/ui/rust-2018/extern-crate-submod.rs | 2 +- .../ui/rust-2018/extern-crate-submod.stderr | 2 +- src/test/ui/rust-2018/try-ident.fixed | 4 +- src/test/ui/rust-2018/try-ident.rs | 4 +- src/test/ui/rust-2018/try-ident.stderr | 4 +- src/test/ui/rust-2018/try-macro.fixed | 4 +- src/test/ui/rust-2018/try-macro.rs | 4 +- src/test/ui/rust-2018/try-macro.stderr | 2 +- .../auxiliary/reserved-prefixes-macro-2018.rs | 25 + .../auxiliary/reserved-prefixes-macro-2021.rs | 25 + .../future-prelude-collision-imported.fixed | 59 + .../future-prelude-collision-imported.rs | 59 + .../future-prelude-collision-imported.stderr | 34 + .../future-prelude-collision-shadow.rs | 32 + .../future-prelude-collision-shadow.stderr | 40 + .../future-prelude-collision-unneeded.rs | 60 + .../rust-2021/future-prelude-collision.fixed | 98 + .../ui/rust-2021/future-prelude-collision.rs | 98 + .../rust-2021/future-prelude-collision.stderr | 79 + .../ui/rust-2021/generic-type-collision.fixed | 18 + .../ui/rust-2021/generic-type-collision.rs | 18 + .../rust-2021/generic-type-collision.stderr | 16 + .../ui/rust-2021/inherent-dyn-collision.fixed | 53 + .../ui/rust-2021/inherent-dyn-collision.rs | 53 + .../rust-2021/inherent-dyn-collision.stderr | 16 + .../ui/rust-2021/inherent-method-collision.rs | 15 + .../reserved-prefixes-migration.fixed | 38 + .../rust-2021/reserved-prefixes-migration.rs | 38 + .../reserved-prefixes-migration.stderr | 72 + .../reserved-prefixes-via-macro-2.rs | 21 + .../reserved-prefixes-via-macro-2.stderr | 29 + .../rust-2021/reserved-prefixes-via-macro.rs | 12 + src/test/ui/rust-2021/reserved-prefixes.rs | 36 + .../ui/rust-2021/reserved-prefixes.stderr | 110 + .../rustdoc/check-doc-alias-attr-location.rs | 7 +- .../check-doc-alias-attr-location.stderr | 8 +- src/test/ui/rustdoc/doc_keyword.rs | 8 + src/test/ui/rustdoc/doc_keyword.stderr | 8 +- src/test/ui/sanitize/crt-static.rs | 1 + src/test/ui/sanitize/incompatible.rs | 1 + src/test/ui/sanitize/unsupported-target.rs | 1 + ...s_pin_lifetime_impl_trait-async.nll.stderr | 6 +- ...f_types_pin_lifetime_impl_trait.nll.stderr | 2 +- src/test/ui/self/self-infer.rs | 4 +- src/test/ui/self/self-infer.stderr | 4 +- src/test/ui/self/self-re-assign.rs | 1 + src/test/ui/simd-intrinsic/issue-85855.rs | 19 + src/test/ui/simd-intrinsic/issue-85855.stderr | 21 + .../one-use-in-fn-argument-in-band.stderr | 24 +- src/test/ui/span/issue-29595.stderr | 9 +- src/test/ui/span/missing-unit-argument.rs | 2 +- src/test/ui/span/missing-unit-argument.stderr | 2 +- .../deafult-generic-associated-type-bound.rs | 1 - ...afult-generic-associated-type-bound.stderr | 12 +- .../repeated_projection_type.stderr | 2 +- .../generics-default-stability.stderr | 52 +- .../ui/static/static-method-privacy.stderr | 3 + .../structs/struct-path-alias-bounds.stderr | 9 +- src/test/ui/suggestions/const-no-type.rs | 8 +- src/test/ui/suggestions/const-no-type.stderr | 8 +- .../expected-boxed-future-isnt-pinned.stderr | 12 +- src/test/ui/suggestions/issue-61963.rs | 4 +- src/test/ui/suggestions/issue-61963.stderr | 4 +- src/test/ui/suggestions/issue-68049-1.stderr | 2 +- src/test/ui/suggestions/issue-68049-2.stderr | 4 +- src/test/ui/suggestions/issue-72766.stderr | 6 +- src/test/ui/suggestions/issue-84973.stderr | 7 +- src/test/ui/suggestions/issue-86667.rs | 16 + src/test/ui/suggestions/issue-86667.stderr | 27 + ...ait-object-nested-in-impl-trait.nll.stderr | 4 +- .../mut-borrow-needed-by-trait.stderr | 6 +- ...object-unsafe-trait-references-self.stderr | 8 +- ...unsafe-trait-should-use-where-sized.stderr | 4 +- src/test/ui/suggestions/path-display.stderr | 2 - .../ui/suggestions/suggest-change-mut.stderr | 6 +- ...gest-full-enum-variant-for-local-module.rs | 10 + ...-full-enum-variant-for-local-module.stderr | 16 + .../suggest-mut-method-for-loop.stderr | 2 +- .../ui/suggestions/suggest-ref-mut.stderr | 8 +- .../suggestions/suggest-remove-refs-1.stderr | 6 +- .../suggestions/suggest-remove-refs-2.stderr | 6 +- .../suggestions/suggest-remove-refs-3.stderr | 6 +- .../try-operator-dont-suggest-semicolon.rs | 27 + ...try-operator-dont-suggest-semicolon.stderr | 33 + src/test/ui/suggestions/unnamable-types.rs | 39 + .../ui/suggestions/unnamable-types.stderr | 66 + .../suggestions/use-placement-resolve.fixed | 13 + .../ui/suggestions/use-placement-resolve.rs | 11 + .../suggestions/use-placement-resolve.stderr | 14 + .../ui/suggestions/use-placement-typeck.fixed | 22 + .../ui/suggestions/use-placement-typeck.rs | 20 + .../suggestions/use-placement-typeck.stderr | 21 + src/test/ui/symbol-names/basic.legacy.stderr | 4 +- src/test/ui/symbol-names/basic.rs | 4 +- src/test/ui/symbol-names/basic.v0.stderr | 4 +- .../symbol-names/const-generics-demangling.rs | 16 +- .../const-generics-demangling.stderr | 16 +- src/test/ui/symbol-names/impl1.rs | 12 +- src/test/ui/symbol-names/impl1.v0.stderr | 12 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- src/test/ui/symbol-names/issue-60925.rs | 4 +- .../ui/symbol-names/issue-60925.v0.stderr | 4 +- src/test/ui/symbol-names/issue-75326.rs | 4 +- .../ui/symbol-names/issue-75326.v0.stderr | 4 +- .../ui/symbol-names/trait-objects.v0.stderr | 6 +- src/test/ui/synthetic-param.stderr | 1 + .../test-panic-abort-disabled.rs | 0 .../test-panic-abort-disabled.stderr | 0 .../test-panic-abort-nocapture.rs | 0 .../test-panic-abort-nocapture.run.stderr | 0 .../test-panic-abort-nocapture.run.stdout | 0 .../ui/{ => test-attrs}/test-panic-abort.rs | 0 .../test-panic-abort.run.stdout | 0 .../test-panic-while-printing.rs | 0 .../ui/{ => test-attrs}/test-passed-wasm.rs | 0 .../test-passed-wasm.run.stdout | 0 src/test/ui/{ => test-attrs}/test-passed.rs | 0 .../{ => test-attrs}/test-passed.run.stdout | 0 .../{ => test-attrs}/test-thread-capture.rs | 0 .../test-thread-capture.run.stdout | 0 .../{ => test-attrs}/test-thread-nocapture.rs | 0 .../test-thread-nocapture.run.stderr | 0 .../test-thread-nocapture.run.stdout | 0 src/test/ui/thir-unsafeck-issue-85871.rs | 20 + src/test/ui/thread-local-static.rs | 1 - src/test/ui/thread-local-static.stderr | 10 +- .../thread-local/thread-local-issue-37508.rs | 36 + src/test/ui/traits/bad-sized.stderr | 6 +- src/test/ui/traits/bound/not-on-bare-trait.rs | 2 +- .../ui/traits/bound/not-on-bare-trait.stderr | 2 +- .../bound/on-structs-and-enums-locals.stderr | 9 +- .../bound/on-structs-and-enums-xc1.stderr | 6 +- .../ui/traits/cycle-cache-err-60010.stderr | 8 +- .../repeated-supertrait-ambig.stderr | 17 +- src/test/ui/traits/issue-71136.stderr | 9 +- src/test/ui/traits/issue-77982.stderr | 6 +- src/test/ui/traits/issue-78632.rs | 59 + src/test/ui/traits/issue-79458.stderr | 9 +- .../issue-83538-tainted-cache-after-cycle.rs | 18 +- ...sue-83538-tainted-cache-after-cycle.stderr | 12 +- src/test/ui/traits/item-privacy.stderr | 9 + src/test/ui/traits/method-private.stderr | 3 + .../negated-auto-traits-error.stderr | 8 +- .../object/issue-33140-traitobject-crate.rs | 1 + .../issue-33140-traitobject-crate.stderr | 6 +- .../operator-overloading-issue-52025.rs | 57 + .../ui/traits/reservation-impl/no-use.stderr | 8 +- .../traits/reservation-impl/non-lattice-ok.rs | 2 +- .../static-method-generic-inference.stderr | 8 +- .../ui/traits/suggest-where-clause.stderr | 18 +- .../trivial-bounds/trivial-bounds-leak.stderr | 9 +- .../ui/try-block/try-block-bad-type.stderr | 18 +- .../ui/try-block/try-block-in-while.stderr | 6 +- .../ui/try-trait/bad-interconversion.stderr | 48 +- src/test/ui/try-trait/option-to-result.stderr | 12 +- .../try-on-option-diagnostics.stderr | 24 +- src/test/ui/try-trait/try-on-option.stderr | 12 +- .../ui/try-trait/try-operator-on-main.stderr | 24 +- .../associated-type-lifetime-ice.rs | 33 - .../associated-type-lifetime-ice.stderr | 13 - ..._not_live_long_enough.full_tait.nll.stderr | 2 +- ...does_not_live_long_enough.full_tait.stderr | 11 +- ...s_not_live_long_enough.min_tait.nll.stderr | 2 +- ..._does_not_live_long_enough.min_tait.stderr | 11 +- .../generic_type_does_not_live_long_enough.rs | 1 - .../issue-53096.full_tait.stderr | 16 +- .../issue-53096.min_tait.stderr | 12 +- .../ui/type-alias-impl-trait/issue-53096.rs | 10 +- ...78-generator-and-const-fn.full_tait.stderr | 18 +- ...678-generator-and-const-fn.min_tait.stderr | 12 +- .../issue-53678-generator-and-const-fn.rs | 7 +- ...sue-57611-trait-alias.full_tait.nll.stderr | 6 +- .../issue-57611-trait-alias.full_tait.stderr | 49 +- ...ssue-57611-trait-alias.min_tait.nll.stderr | 6 +- .../issue-57611-trait-alias.min_tait.stderr | 49 +- .../issue-57611-trait-alias.rs | 4 - .../ui/type-alias-impl-trait/issue-60371.rs | 1 - .../type-alias-impl-trait/issue-60371.stderr | 16 +- .../issue-60407.full_tait.stderr | 14 +- .../issue-60407.min_tait.stderr | 26 +- .../ui/type-alias-impl-trait/issue-60407.rs | 10 +- .../ui/type-alias-impl-trait/issue-63355.rs | 50 + .../type-alias-impl-trait/issue-63355.stderr | 14 + .../ui/type-alias-impl-trait/issue-65384.rs | 16 + .../type-alias-impl-trait/issue-65384.stderr | 14 + ...-opaque-ty-from-val-twice.full_tait.stderr | 14 +- ...sue-65679-inst-opaque-ty-from-val-twice.rs | 6 +- .../issue-69323.full.stderr | 11 + .../ui/type-alias-impl-trait/issue-69323.rs | 19 + .../ui/type-alias-impl-trait/issue-74761-2.rs | 19 + .../issue-74761-2.stderr | 34 + .../ui/type-alias-impl-trait/issue-78450.rs | 27 + .../type-alias-impl-trait/issue-78450.stderr | 11 + .../issue-87455-static-lifetime-ice.rs | 73 + .../multiple-def-uses-in-one-fn2.rs | 2 +- .../multiple-def-uses-in-one-fn2.stderr | 14 +- .../multiple-def-uses-in-one-fn3.rs | 1 + .../multiple-def-uses-in-one-fn3.stderr | 17 +- ..._inferrable_concrete_type.full_tait.stderr | 14 +- ...o_inferrable_concrete_type.min_tait.stderr | 14 +- .../no_inferrable_concrete_type.rs | 9 +- .../structural-match-no-leak.full_tait.stderr | 14 +- .../structural-match-no-leak.min_tait.stderr | 12 +- .../structural-match-no-leak.rs | 7 +- .../structural-match.full_tait.stderr | 14 +- .../structural-match.min_tait.stderr | 12 +- .../type-alias-impl-trait/structural-match.rs | 7 +- ...pe-alias-impl-trait-const.full_tait.stderr | 25 +- ...ype-alias-impl-trait-const.min_tait.stderr | 24 +- .../type-alias-impl-trait-const.rs | 13 +- src/test/ui/type/type-check-defaults.stderr | 43 +- .../type-params-in-different-spaces-2.stderr | 16 +- .../ui/{ => typeck}/conversion-methods.rs | 0 .../ui/{ => typeck}/conversion-methods.stderr | 0 src/test/ui/{issues => typeck}/issue-74086.rs | 2 +- .../ui/{issues => typeck}/issue-74086.stderr | 2 +- src/test/ui/typeck/issue-75883.rs | 4 +- src/test/ui/typeck/issue-75883.stderr | 4 +- src/test/ui/typeck/issue-75889.rs | 6 + src/test/ui/typeck/issue-75889.stderr | 15 + src/test/ui/typeck/issue-80779.rs | 4 +- src/test/ui/typeck/issue-80779.stderr | 4 +- src/test/ui/{issues => typeck}/issue-81885.rs | 6 +- .../ui/{issues => typeck}/issue-81885.stderr | 6 +- ...-83621-placeholder-static-in-extern.stderr | 2 +- src/test/ui/typeck/issue-84160.rs | 9 + src/test/ui/typeck/issue-84160.stderr | 15 + .../issue-86721-return-expr-ice.rev1.stderr | 9 + .../issue-86721-return-expr-ice.rev2.stderr | 9 + .../ui/typeck/issue-86721-return-expr-ice.rs | 17 + src/test/ui/typeck/struct-enum-wrong-args.rs | 14 + .../ui/typeck/struct-enum-wrong-args.stderr | 67 + .../ui/typeck/type-placeholder-fn-in-const.rs | 14 + .../type-placeholder-fn-in-const.stderr | 21 + .../typeck-closure-to-unsafe-fn-ptr.rs | 0 .../typeck-fn-to-unsafe-fn-ptr.rs | 0 .../{ => typeck}/typeck_type_placeholder_1.rs | 0 ...eck_type_placeholder_item.full_tait.stderr | 218 +- ...peck_type_placeholder_item.min_tait.stderr | 218 +- .../ui/typeck/typeck_type_placeholder_item.rs | 121 +- .../typeck_type_placeholder_item_help.rs | 12 +- .../typeck_type_placeholder_item_help.stderr | 12 +- .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 6 +- .../unevaluated_fixed_size_array_len.stderr | 8 +- src/test/ui/union/union-align.rs | 3 + src/test/ui/union/union-backcomp.rs | 3 + src/test/ui/union/union-basic.rs | 3 + ...ow-move-parent-sibling.mirunsafeck.stderr} | 10 +- .../union/union-borrow-move-parent-sibling.rs | 3 + ...ow-move-parent-sibling.thirunsafeck.stderr | 60 + src/test/ui/union/union-const-codegen.rs | 2 + src/test/ui/union/union-const-eval-field.rs | 2 + src/test/ui/union/union-const-eval.rs | 3 + ....stderr => union-deref.mirunsafeck.stderr} | 12 +- src/test/ui/union/union-deref.rs | 3 + .../ui/union/union-deref.thirunsafeck.stderr | 56 + ... => union-derive-clone.mirunsafeck.stderr} | 4 +- src/test/ui/union/union-derive-clone.rs | 3 + .../union-derive-clone.thirunsafeck.stderr | 36 + ...err => union-derive-eq.mirunsafeck.stderr} | 5 +- src/test/ui/union/union-derive-eq.rs | 3 + .../union/union-derive-eq.thirunsafeck.stderr | 19 + src/test/ui/union/union-derive-rpass.rs | 3 + .../ui/union/union-drop.thirunsafeck.stderr | 22 + ...derr => union-fields-1.mirunsafeck.stderr} | 10 +- src/test/ui/union/union-fields-1.rs | 3 + .../union/union-fields-1.thirunsafeck.stderr | 32 + ...derr => union-fields-2.mirunsafeck.stderr} | 26 +- src/test/ui/union/union-fields-2.rs | 3 + .../union/union-fields-2.thirunsafeck.stderr | 84 + src/test/ui/union/union-generic-rpass.rs | 3 + ...tderr => union-generic.mirunsafeck.stderr} | 22 +- src/test/ui/union/union-generic.rs | 3 + .../union/union-generic.thirunsafeck.stderr | 27 + src/test/ui/union/union-inherent-method.rs | 2 + ...> union-lint-dead-code.mirunsafeck.stderr} | 4 +- src/test/ui/union/union-lint-dead-code.rs | 3 + .../union-lint-dead-code.thirunsafeck.stderr | 14 + src/test/ui/union/union-macro.rs | 3 + src/test/ui/union/union-manuallydrop-rpass.rs | 5 +- ...e.stderr => union-move.mirunsafeck.stderr} | 6 +- src/test/ui/union/union-move.rs | 3 + .../ui/union/union-move.thirunsafeck.stderr | 35 + src/test/ui/union/union-nodrop.rs | 2 + src/test/ui/union/union-nonzero.rs | 3 + src/test/ui/union/union-overwrite.rs | 2 + src/test/ui/union/union-packed.rs | 3 + src/test/ui/union/union-pat-refutability.rs | 3 + ...=> union-suggest-field.mirunsafeck.stderr} | 6 +- src/test/ui/union/union-suggest-field.rs | 3 + .../union-suggest-field.thirunsafeck.stderr | 27 + src/test/ui/union/union-trait-impl.rs | 2 + src/test/ui/union/union-transmute.rs | 2 + ...-unsafe.stderr => union-unsafe.mir.stderr} | 22 +- src/test/ui/union/union-unsafe.rs | 8 +- src/test/ui/union/union-unsafe.thir.stderr | 75 + ...tderr => union-unsized.mirunsafeck.stderr} | 4 +- src/test/ui/union/union-unsized.rs | 3 + .../union/union-unsized.thirunsafeck.stderr | 39 + ...union-with-drop-fields.mirunsafeck.stderr} | 12 +- src/test/ui/union/union-with-drop-fields.rs | 4 +- ...union-with-drop-fields.thirunsafeck.stderr | 39 + src/test/ui/unpretty-expr-fn-arg.rs | 13 + src/test/ui/unpretty-expr-fn-arg.stdout | 17 + .../ui/unsafe/access_union_field.mir.stderr | 19 + src/test/ui/unsafe/access_union_field.rs | 15 + .../ui/unsafe/access_union_field.thir.stderr | 19 + ...stderr => ranged_ints2.mirunsafeck.stderr} | 2 +- src/test/ui/unsafe/ranged_ints2.rs | 3 + .../unsafe/ranged_ints2.thirunsafeck.stderr | 11 + ... => ranged_ints2_const.mirunsafeck.stderr} | 8 +- src/test/ui/unsafe/ranged_ints2_const.rs | 3 + .../ranged_ints2_const.thirunsafeck.stderr | 39 + ...stderr => ranged_ints3.mirunsafeck.stderr} | 2 +- src/test/ui/unsafe/ranged_ints3.rs | 3 + .../unsafe/ranged_ints3.thirunsafeck.stderr | 11 + ... => ranged_ints3_const.mirunsafeck.stderr} | 6 +- src/test/ui/unsafe/ranged_ints3_const.rs | 3 + .../ranged_ints3_const.thirunsafeck.stderr | 30 + .../ranged_ints3_match.mirunsafeck.stderr | 19 + src/test/ui/unsafe/ranged_ints3_match.rs | 22 + .../ranged_ints3_match.thirunsafeck.stderr | 19 + ...stderr => ranged_ints4.mirunsafeck.stderr} | 2 +- src/test/ui/unsafe/ranged_ints4.rs | 3 + ...tderr => ranged_ints4.thirunsafeck.stderr} | 2 +- .../ranged_ints4_const.mirunsafeck.stderr | 11 + src/test/ui/unsafe/ranged_ints4_const.rs | 3 + .../ranged_ints4_const.thirunsafeck.stderr | 11 + src/test/ui/unsafe/union.mir.stderr | 16 + src/test/ui/unsafe/union.rs | 80 + .../ui/unsafe/union_access_through_block.rs | 18 + .../ui/unsafe/union_destructure.mir.stderr | 16 + src/test/ui/unsafe/union_destructure.rs | 51 + src/test/ui/unsafe/union_wild_or_wild.rs | 12 + ...round-compiler-generated-unsafe.mir.stderr | 8 +- ...unsafe-around-compiler-generated-unsafe.rs | 7 +- ...ound-compiler-generated-unsafe.thir.stderr | 8 +- .../unsafe/unsafe-assign.mirunsafeck.stderr | 11 + src/test/ui/unsafe/unsafe-assign.rs | 25 + .../unsafe/unsafe-assign.thirunsafeck.stderr | 11 + .../unsafe/unsafe-borrow.mirunsafeck.stderr | 27 + src/test/ui/unsafe/unsafe-borrow.rs | 56 + .../unsafe/unsafe-borrow.thirunsafeck.stderr | 27 + src/test/ui/unsized/unsized3-rpass.rs | 25 +- .../unused/unused-doc-comments-edge-cases.rs | 29 + .../unused-doc-comments-edge-cases.stderr | 61 + src/test/ui/unused/useless-comment.stderr | 16 + .../feature-gate-stdcall-unwind.rs | 31 +- .../feature-gate-stdcall-unwind.stderr | 60 +- .../feature-gate-thiscall-unwind.rs | 40 +- .../feature-gate-thiscall-unwind.stderr | 116 +- .../variance-btree-invariant-types.nll.stderr | 58 +- .../variance-btree-invariant-types.rs | 15 +- .../variance-btree-invariant-types.stderr | 110 +- src/test/ui/wait-forked-but-failed-child.rs | 2 +- src/test/ui/wf/hir-wf-check-erase-regions.rs | 14 + .../ui/wf/hir-wf-check-erase-regions.stderr | 31 + src/test/ui/wf/wf-complex-assoc-type.rs | 12 + src/test/ui/wf/wf-complex-assoc-type.stderr | 12 + src/test/ui/wf/wf-foreign-fn-decl-ret.stderr | 7 +- .../wf/wf-impl-associated-type-trait.stderr | 4 +- src/test/ui/wf/wf-in-fn-arg.stderr | 4 +- src/test/ui/wf/wf-in-fn-type-arg.stderr | 4 +- src/test/ui/wf/wf-in-fn-type-ret.stderr | 4 +- .../wf/wf-in-foreign-fn-decls-issue-80468.rs | 2 +- .../wf-in-foreign-fn-decls-issue-80468.stderr | 20 +- src/test/ui/wf/wf-in-obj-type-trait.stderr | 4 +- .../ui/wf/wf-trait-associated-type-trait.rs | 2 +- .../wf/wf-trait-associated-type-trait.stderr | 6 +- src/test/ui/wf/wf-trait-default-fn-arg.stderr | 4 +- src/test/ui/wf/wf-trait-fn-arg.stderr | 4 +- src/test/ui/write-fmt-errors.rs | 4 +- src/test/ui/xc-private-method.stderr | 10 + src/test/ui/xc-private-method2.stderr | 10 + src/tools/clippy/.github/workflows/clippy.yml | 2 +- .../clippy/.github/workflows/clippy_bors.yml | 7 +- src/tools/clippy/.github/workflows/remark.yml | 2 +- src/tools/clippy/.remarkrc | 1 + src/tools/clippy/CHANGELOG.md | 144 +- src/tools/clippy/CONTRIBUTING.md | 4 +- src/tools/clippy/Cargo.toml | 2 +- src/tools/clippy/README.md | 28 +- src/tools/clippy/clippy_dev/Cargo.toml | 2 +- src/tools/clippy/clippy_dev/src/fmt.rs | 8 +- src/tools/clippy/clippy_dev/src/ide_setup.rs | 103 - src/tools/clippy/clippy_dev/src/lib.rs | 2 +- src/tools/clippy/clippy_dev/src/main.rs | 81 +- .../clippy/clippy_dev/src/setup/git_hook.rs | 85 + .../clippy/clippy_dev/src/setup/intellij.rs | 223 + src/tools/clippy/clippy_dev/src/setup/mod.rs | 23 + .../clippy/clippy_dev/src/setup/vscode.rs | 104 + .../clippy/clippy_dev/src/update_lints.rs | 5 +- src/tools/clippy/clippy_lints/Cargo.toml | 3 +- .../clippy/clippy_lints/src/assign_ops.rs | 95 +- src/tools/clippy/clippy_lints/src/attrs.rs | 2 +- .../clippy_lints/src/blacklisted_name.rs | 31 +- .../clippy/clippy_lints/src/bytecount.rs | 70 +- .../clippy_lints/src/cargo_common_metadata.rs | 5 +- .../clippy_lints/src/collapsible_match.rs | 20 +- src/tools/clippy/clippy_lints/src/copies.rs | 14 +- src/tools/clippy/clippy_lints/src/default.rs | 3 +- .../src/default_numeric_fallback.rs | 30 +- .../clippy_lints/src/deprecated_lints.rs | 4 +- .../clippy/clippy_lints/src/dereference.rs | 4 +- src/tools/clippy/clippy_lints/src/derive.rs | 13 +- .../clippy_lints/src/disallowed_method.rs | 29 +- .../src/disallowed_script_idents.rs | 112 + .../clippy_lints/src/disallowed_type.rs | 126 + src/tools/clippy/clippy_lints/src/doc.rs | 81 +- src/tools/clippy/clippy_lints/src/eq_op.rs | 2 +- src/tools/clippy/clippy_lints/src/escape.rs | 9 +- .../clippy/clippy_lints/src/eta_reduction.rs | 20 +- .../clippy_lints/src/eval_order_dependence.rs | 2 +- .../clippy/clippy_lints/src/explicit_write.rs | 117 +- .../src/float_equality_without_abs.rs | 2 +- src/tools/clippy/clippy_lints/src/format.rs | 192 +- .../clippy/clippy_lints/src/formatting.rs | 6 +- .../clippy_lints/src/get_last_with_len.rs | 2 +- .../clippy/clippy_lints/src/if_let_mutex.rs | 2 +- .../clippy_lints/src/implicit_hasher.rs | 2 +- .../clippy/clippy_lints/src/inherent_impl.rs | 6 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 16 +- src/tools/clippy/clippy_lints/src/lib.rs | 95 +- .../clippy_lints/src/loops/manual_memcpy.rs | 2 +- .../clippy/clippy_lints/src/loops/mod.rs | 6 +- .../clippy_lints/src/loops/mut_range_bound.rs | 4 +- .../src/loops/needless_collect.rs | 97 +- .../src/loops/needless_range_loop.rs | 2 +- .../src/loops/while_let_on_iterator.rs | 11 +- .../clippy/clippy_lints/src/manual_map.rs | 24 +- .../clippy_lints/src/manual_unwrap_or.rs | 4 +- .../clippy/clippy_lints/src/map_identity.rs | 126 - src/tools/clippy/clippy_lints/src/matches.rs | 24 +- .../src/methods/expect_fun_call.rs | 72 +- .../src/methods/extend_with_drain.rs | 41 + .../src/methods/filter_map_identity.rs | 40 +- .../src/methods/flat_map_identity.rs | 44 +- .../clippy_lints/src/methods/map_identity.rs | 38 + .../clippy/clippy_lints/src/methods/mod.rs | 65 +- .../clippy_lints/src/methods/or_fun_call.rs | 2 +- src/tools/clippy/clippy_lints/src/misc.rs | 9 +- .../src/missing_enforced_import_rename.rs | 102 + .../src/multiple_crate_versions.rs | 4 +- src/tools/clippy/clippy_lints/src/mut_key.rs | 6 +- .../clippy/clippy_lints/src/needless_bool.rs | 3 + .../src/needless_pass_by_value.rs | 6 +- .../clippy/clippy_lints/src/no_effect.rs | 2 +- .../src/nonstandard_macro_braces.rs | 280 + .../clippy_lints/src/option_if_let_else.rs | 2 +- .../clippy_lints/src/panic_unimplemented.rs | 4 +- .../clippy_lints/src/pattern_type_mismatch.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr.rs | 4 +- src/tools/clippy/clippy_lints/src/ranges.rs | 2 +- .../clippy_lints/src/redundant_clone.rs | 110 +- .../src/self_named_constructors.rs | 91 + .../src/semicolon_if_nothing_returned.rs | 2 + src/tools/clippy/clippy_lints/src/strings.rs | 4 +- .../clippy_lints/src/strlen_on_c_strings.rs | 82 + .../clippy_lints/src/suspicious_trait_impl.rs | 147 +- .../clippy/clippy_lints/src/types/mod.rs | 37 +- .../clippy/clippy_lints/src/types/rc_mutex.rs | 27 + .../src/types/redundant_allocation.rs | 153 +- src/tools/clippy/clippy_lints/src/unicode.rs | 6 +- .../clippy_lints/src/unit_types/unit_cmp.rs | 7 +- .../clippy_lints/src/unnested_or_patterns.rs | 5 +- .../clippy/clippy_lints/src/unused_unit.rs | 4 + src/tools/clippy/clippy_lints/src/use_self.rs | 356 +- .../clippy_lints/src/useless_conversion.rs | 2 +- .../clippy/clippy_lints/src/utils/conf.rs | 24 +- .../clippy_lints/src/utils/internal_lints.rs | 16 +- .../internal_lints/metadata_collector.rs | 44 +- .../clippy_lints/src/wildcard_dependencies.rs | 5 +- .../clippy_lints/src/wildcard_imports.rs | 12 +- .../clippy_lints/src/zero_sized_map_values.rs | 5 +- src/tools/clippy/clippy_utils/Cargo.toml | 2 +- .../clippy/clippy_utils/src/ast_utils.rs | 13 +- src/tools/clippy/clippy_utils/src/attrs.rs | 5 + src/tools/clippy/clippy_utils/src/consts.rs | 10 +- src/tools/clippy/clippy_utils/src/higher.rs | 133 +- src/tools/clippy/clippy_utils/src/lib.rs | 204 +- .../clippy_utils/src/numeric_literal.rs | 3 + src/tools/clippy/clippy_utils/src/paths.rs | 5 +- src/tools/clippy/clippy_utils/src/ptr.rs | 32 +- src/tools/clippy/clippy_utils/src/sugg.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 32 +- src/tools/clippy/clippy_utils/src/usage.rs | 51 +- src/tools/clippy/doc/basics.md | 50 +- .../clippy/doc/common_tools_writing_lints.md | 2 +- src/tools/clippy/doc/release.md | 15 + src/tools/clippy/lintcheck/README.md | 4 +- src/tools/clippy/lintcheck/src/main.rs | 9 +- src/tools/clippy/rust-toolchain | 2 +- src/tools/clippy/src/main.rs | 26 +- src/tools/clippy/tests/compile-test.rs | 19 +- .../clippy.toml | 10 + .../conf_missing_enforced_import_rename.rs | 16 + ...conf_missing_enforced_import_rename.stderr | 40 + .../auxiliary/proc_macro_derive.rs | 18 + .../nonstandard_macro_braces/clippy.toml | 6 + .../conf_nonstandard_macro_braces.rs | 52 + .../conf_nonstandard_macro_braces.stderr | 94 + .../toml_disallowed_method/clippy.toml | 6 +- .../ui-toml/toml_disallowed_type/clippy.toml | 9 + .../conf_disallowed_type.rs | 35 + .../conf_disallowed_type.stderr | 88 + .../toml_unknown_key/conf_unknown_key.stderr | 2 +- .../tests/ui/assertions_on_constants.rs | 5 +- .../clippy/tests/ui/auxiliary/macro_rules.rs | 7 + .../tests/ui/auxiliary/non-exhaustive-enum.rs | 8 + src/tools/clippy/tests/ui/blacklisted_name.rs | 12 + .../branches_sharing_code/false_positives.rs | 28 + src/tools/clippy/tests/ui/bytes_nth.fixed | 2 +- src/tools/clippy/tests/ui/bytes_nth.rs | 2 +- src/tools/clippy/tests/ui/bytes_nth.stderr | 6 +- .../clippy/tests/ui/crashes/ice-3969.stderr | 6 +- src/tools/clippy/tests/ui/crashes/ice-6179.rs | 2 +- src/tools/clippy/tests/ui/crashes/ice-7340.rs | 6 + src/tools/clippy/tests/ui/crashes/ice-7410.rs | 31 + src/tools/clippy/tests/ui/crashes/ice-7423.rs | 13 + .../ui/default_numeric_fallback_f64.fixed | 174 + .../tests/ui/default_numeric_fallback_f64.rs | 174 + .../ui/default_numeric_fallback_f64.stderr | 147 + .../ui/default_numeric_fallback_i32.fixed | 173 + ...ack.rs => default_numeric_fallback_i32.rs} | 47 +- ...rr => default_numeric_fallback_i32.stderr} | 71 +- src/tools/clippy/tests/ui/deprecated.stderr | 8 +- .../tests/ui/disallowed_script_idents.rs | 10 + .../tests/ui/disallowed_script_idents.stderr | 20 + src/tools/clippy/tests/ui/{ => doc}/doc.rs | 2 +- .../clippy/tests/ui/{ => doc}/doc.stderr | 0 .../clippy/tests/ui/doc/unbalanced_ticks.rs | 43 + .../tests/ui/doc/unbalanced_ticks.stderr | 64 + src/tools/clippy/tests/ui/eta.fixed | 16 + src/tools/clippy/tests/ui/eta.rs | 16 + src/tools/clippy/tests/ui/eta.stderr | 26 +- .../ui/explicit_write_non_rustfix.stderr | 3 +- .../clippy/tests/ui/extend_with_drain.fixed | 55 + .../clippy/tests/ui/extend_with_drain.rs | 55 + .../clippy/tests/ui/extend_with_drain.stderr | 22 + .../tests/ui/field_reassign_with_default.rs | 20 + .../ui/field_reassign_with_default.stderr | 36 +- .../clippy/tests/ui/filter_map_identity.fixed | 5 +- .../clippy/tests/ui/filter_map_identity.rs | 5 +- .../tests/ui/filter_map_identity.stderr | 14 +- .../clippy/tests/ui/flat_map_identity.fixed | 5 +- .../clippy/tests/ui/flat_map_identity.rs | 5 +- .../clippy/tests/ui/flat_map_identity.stderr | 12 +- src/tools/clippy/tests/ui/format.fixed | 2 + src/tools/clippy/tests/ui/format.rs | 2 + .../clippy/tests/ui/future_not_send.stderr | 4 +- src/tools/clippy/tests/ui/issue-7447.rs | 25 + src/tools/clippy/tests/ui/issue_4266.rs | 4 +- src/tools/clippy/tests/ui/iter_count.fixed | 6 +- src/tools/clippy/tests/ui/iter_count.rs | 6 +- src/tools/clippy/tests/ui/iter_count.stderr | 18 +- .../clippy/tests/ui/match_same_arms.stderr | 7 + .../clippy/tests/ui/match_same_arms2.stderr | 7 + .../match_wildcard_for_single_variants.fixed | 7 + .../ui/match_wildcard_for_single_variants.rs | 7 + src/tools/clippy/tests/ui/missing-doc-impl.rs | 4 +- .../clippy/tests/ui/missing-doc-impl.stderr | 12 +- .../ui/missing_const_for_fn/cant_be_const.rs | 2 +- src/tools/clippy/tests/ui/mut_key.stderr | 2 +- .../tests/ui/needless_bool/fixable.fixed | 3 +- .../clippy/tests/ui/needless_bool/fixable.rs | 3 +- .../tests/ui/needless_bool/fixable.stderr | 24 +- .../clippy/tests/ui/needless_lifetimes.rs | 2 +- src/tools/clippy/tests/ui/panicking_macros.rs | 16 + src/tools/clippy/tests/ui/rc_mutex.rs | 34 + src/tools/clippy/tests/ui/rc_mutex.stderr | 28 + .../tests/ui/redundant_allocation.fixed | 48 - .../clippy/tests/ui/redundant_allocation.rs | 68 +- .../tests/ui/redundant_allocation.stderr | 152 +- .../ui/redundant_allocation_fixable.fixed | 75 + .../tests/ui/redundant_allocation_fixable.rs | 75 + .../ui/redundant_allocation_fixable.stderr | 99 + .../clippy/tests/ui/redundant_clone.fixed | 28 + src/tools/clippy/tests/ui/redundant_clone.rs | 28 + .../clippy/tests/ui/redundant_clone.stderr | 20 +- .../tests/ui/self_named_constructors.rs | 59 + .../tests/ui/self_named_constructors.stderr | 12 + .../tests/ui/semicolon_if_nothing_returned.rs | 44 + .../ui/semicolon_if_nothing_returned.stderr | 14 +- .../clippy/tests/ui/strlen_on_c_strings.rs | 16 + .../tests/ui/strlen_on_c_strings.stderr | 25 + .../ui/suspicious_arithmetic_impl.stderr | 20 +- src/tools/clippy/tests/ui/unit_arg.rs | 3 +- src/tools/clippy/tests/ui/unit_arg.stderr | 20 +- .../tests/ui/unnecessary_cast_fixable.fixed | 2 +- .../tests/ui/unnecessary_cast_fixable.rs | 2 +- src/tools/clippy/tests/ui/use_self.fixed | 30 +- src/tools/clippy/tests/ui/use_self.rs | 32 +- src/tools/clippy/tests/ui/use_self.stderr | 60 +- src/tools/clippy/tests/ui/vec.fixed | 2 +- src/tools/clippy/tests/ui/vec.rs | 2 +- .../tests/ui/while_let_on_iterator.fixed | 14 + .../clippy/tests/ui/while_let_on_iterator.rs | 14 + .../tests/ui/while_let_on_iterator.stderr | 10 +- .../tests/ui/wildcard_enum_match_arm.fixed | 39 +- .../tests/ui/wildcard_enum_match_arm.rs | 37 +- .../tests/ui/wildcard_enum_match_arm.stderr | 22 +- src/tools/clippy/tests/ui/zero_offset.rs | 20 +- src/tools/clippy/tests/ui/zero_offset.stderr | 55 +- src/tools/clippy/util/etc/pre-commit.sh | 21 + src/tools/clippy/util/etc/vscode-tasks.json | 57 + src/tools/clippy/util/lintlib.py | 5 +- src/tools/compiletest/Cargo.toml | 2 +- src/tools/compiletest/src/header.rs | 460 +- src/tools/compiletest/src/header/tests.rs | 113 +- src/tools/compiletest/src/json.rs | 5 +- src/tools/compiletest/src/main.rs | 64 +- src/tools/compiletest/src/runtest.rs | 37 +- src/tools/error_index_generator/main.rs | 4 +- src/tools/html-checker/Cargo.toml | 12 + src/tools/html-checker/main.rs | 98 + src/tools/linkchecker/main.rs | 2 +- .../tests/broken_redir/redir-bad.html | 1 + src/tools/linkchecker/tests/checks.rs | 50 +- .../tests/redirect_loop/redir-bad.html | 1 + .../tests/valid/inner/redir-bad.html | 1 + .../linkchecker/tests/valid/inner/redir.html | 1 + src/tools/lint-docs/src/lib.rs | 4 +- src/tools/rustc-workspace-hack/Cargo.toml | 13 +- src/tools/rustdoc-gui/tester.js | 50 +- src/tools/rustfmt/CHANGELOG.md | 10 +- src/tools/rustfmt/Configurations.md | 32 +- src/tools/rustfmt/Contributing.md | 2 +- src/tools/rustfmt/Design.md | 4 +- src/tools/rustfmt/README.md | 4 +- src/tools/rustfmt/ci/integration.sh | 2 +- src/tools/rustfmt/src/formatting.rs | 2 +- src/tools/rustfmt/src/lib.rs | 1 + src/tools/rustfmt/src/types.rs | 6 +- src/tools/rustfmt/src/utils.rs | 4 +- src/tools/tidy/Cargo.toml | 2 +- src/tools/tidy/src/deps.rs | 45 +- src/tools/tidy/src/error_codes_check.rs | 114 +- src/tools/tidy/src/features.rs | 1 + src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 2 + src/tools/tidy/src/pal.rs | 2 +- src/tools/tidy/src/style.rs | 1 + src/tools/tidy/src/target_specific_tests.rs | 96 + src/tools/tidy/src/ui_tests.rs | 4 +- src/version | 2 +- vendor/anyhow/.cargo-checksum.json | 2 +- vendor/anyhow/Cargo.toml | 4 +- vendor/anyhow/src/error.rs | 6 +- vendor/anyhow/src/lib.rs | 2 +- vendor/anyhow/tests/test_boxed.rs | 5 + vendor/anyhow/tests/test_chain.rs | 25 +- vendor/anyhow/tests/test_context.rs | 12 + vendor/anyhow/tests/test_convert.rs | 20 + vendor/anyhow/tests/test_downcast.rs | 9 + vendor/anyhow/tests/ui/no-impl.stderr | 2 +- vendor/arrayvec/.cargo-checksum.json | 2 +- vendor/arrayvec/CHANGELOG.md | 9 + vendor/arrayvec/Cargo.toml | 2 +- vendor/arrayvec/src/arrayvec.rs | 34 +- vendor/arrayvec/src/lib.rs | 2 +- vendor/arrayvec/tests/tests.rs | 24 + vendor/byteorder/.cargo-checksum.json | 2 +- vendor/byteorder/CHANGELOG.md | 25 - vendor/byteorder/Cargo.toml | 15 +- vendor/byteorder/README.md | 10 +- vendor/byteorder/benches/bench.rs | 236 +- vendor/byteorder/build.rs | 90 + vendor/byteorder/src/io.rs | 95 +- vendor/byteorder/src/lib.rs | 1819 +++---- .../.cargo-checksum.json | 1 - vendor/cargo_metadata-0.11.1/Cargo.toml | 37 - vendor/cargo_metadata-0.11.1/LICENSE-MIT | 23 - vendor/cargo_metadata-0.11.1/README.md | 12 - .../cargo_metadata-0.11.1/src/dependency.rs | 86 - .../cargo_metadata-0.11.1/src/diagnostic.rs | 159 - vendor/cargo_metadata-0.11.1/src/errors.rs | 106 - vendor/cargo_metadata-0.11.1/src/lib.rs | 575 --- vendor/cargo_metadata-0.11.1/src/messages.rs | 161 - .../cargo_metadata-0.11.1/tests/selftest.rs | 159 - .../tests/test_samples.rs | 559 -- vendor/cc/.cargo-checksum.json | 2 +- vendor/cc/Cargo.lock | 4 +- vendor/cc/Cargo.toml | 2 +- vendor/cc/src/lib.rs | 18 +- vendor/cc/src/windows_registry.rs | 12 +- vendor/compiler_builtins/.cargo-checksum.json | 2 +- vendor/compiler_builtins/Cargo.lock | 2 +- vendor/compiler_builtins/Cargo.toml | 11 +- vendor/compiler_builtins/build.rs | 31 +- vendor/compiler_builtins/libm/src/math/fma.rs | 16 +- vendor/compiler_builtins/libm/src/math/pow.rs | 4 +- vendor/compiler_builtins/src/int/shift.rs | 16 +- vendor/globwalk/.cargo-checksum.json | 1 + vendor/globwalk/Cargo.lock | 334 ++ vendor/globwalk/Cargo.toml | 43 + vendor/globwalk/LICENSE | 19 + vendor/globwalk/README.md | 46 + vendor/globwalk/appveyor.yml | 125 + vendor/globwalk/examples/list.rs | 35 + vendor/globwalk/src/doctests.rs | 20 + vendor/globwalk/src/lib.rs | 839 +++ vendor/globwalk/tests/docs.rs | 10 + vendor/hashbrown-0.9.1/.cargo-checksum.json | 1 - vendor/hashbrown-0.9.1/CHANGELOG.md | 294 -- vendor/hashbrown-0.9.1/Cargo.toml | 80 - vendor/hashbrown-0.9.1/LICENSE-MIT | 25 - vendor/hashbrown-0.9.1/README.md | 126 - vendor/hashbrown-0.9.1/benches/bench.rs | 260 - vendor/hashbrown-0.9.1/clippy.toml | 1 - .../src/external_trait_impls/mod.rs | 4 - .../src/external_trait_impls/rayon/helpers.rs | 26 - .../src/external_trait_impls/rayon/map.rs | 666 --- .../src/external_trait_impls/rayon/mod.rs | 4 - .../src/external_trait_impls/rayon/raw.rs | 199 - .../src/external_trait_impls/rayon/set.rs | 646 --- .../src/external_trait_impls/serde.rs | 200 - vendor/hashbrown-0.9.1/src/lib.rs | 112 - vendor/hashbrown-0.9.1/src/macros.rs | 69 - vendor/hashbrown-0.9.1/src/map.rs | 4524 ----------------- vendor/hashbrown-0.9.1/src/raw/bitmask.rs | 122 - vendor/hashbrown-0.9.1/src/raw/generic.rs | 151 - vendor/hashbrown-0.9.1/src/raw/mod.rs | 1924 ------- vendor/hashbrown-0.9.1/src/raw/sse2.rs | 144 - vendor/hashbrown-0.9.1/src/rustc_entry.rs | 618 --- vendor/hashbrown-0.9.1/src/scopeguard.rs | 49 - vendor/hashbrown-0.9.1/src/set.rs | 2119 -------- vendor/hashbrown-0.9.1/tests/hasher.rs | 65 - vendor/hashbrown-0.9.1/tests/rayon.rs | 533 -- vendor/hashbrown-0.9.1/tests/serde.rs | 65 - vendor/hashbrown-0.9.1/tests/set.rs | 30 - vendor/hashbrown/.cargo-checksum.json | 2 +- vendor/hashbrown/CHANGELOG.md | 16 +- vendor/hashbrown/Cargo.toml | 2 +- vendor/hashbrown/src/lib.rs | 2 +- vendor/hashbrown/src/map.rs | 2 +- vendor/hashbrown/src/set.rs | 2 +- vendor/heck/.cargo-checksum.json | 2 +- vendor/heck/Cargo.toml | 3 +- vendor/heck/README.md | 15 +- vendor/heck/no_step_on_snek.png | Bin 43512 -> 0 bytes vendor/heck/src/camel.rs | 2 +- vendor/heck/src/kebab.rs | 2 +- vendor/heck/src/lib.rs | 66 +- vendor/heck/src/mixed.rs | 17 +- vendor/heck/src/shouty_kebab.rs | 2 +- vendor/heck/src/shouty_snake.rs | 7 +- vendor/heck/src/snake.rs | 2 +- vendor/heck/src/title.rs | 2 +- vendor/hermit-abi/.cargo-checksum.json | 2 +- vendor/hermit-abi/Cargo.toml | 4 +- vendor/hermit-abi/src/lib.rs | 3 + vendor/indexmap/.cargo-checksum.json | 2 +- vendor/indexmap/Cargo.toml | 6 +- vendor/indexmap/README.rst | 10 +- vendor/indexmap/benches/bench.rs | 4 +- vendor/indexmap/src/lib.rs | 7 +- vendor/indexmap/src/map.rs | 10 +- vendor/indexmap/src/rayon/map.rs | 8 +- vendor/indexmap/src/rayon/mod.rs | 4 - vendor/indexmap/src/rayon/set.rs | 2 +- vendor/indexmap/src/set.rs | 7 +- vendor/indexmap/tests/quick.rs | 12 +- vendor/libc/.cargo-checksum.json | 2 +- vendor/libc/Cargo.toml | 2 +- vendor/libc/src/fuchsia/mod.rs | 2 + vendor/libc/src/unix/bsd/apple/mod.rs | 157 +- .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 152 + .../bsd/freebsdlike/freebsd/freebsd12/mod.rs | 3 + .../bsd/freebsdlike/freebsd/freebsd13/mod.rs | 3 + .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 91 + .../unix/bsd/freebsdlike/freebsd/powerpc.rs | 47 + vendor/libc/src/unix/bsd/freebsdlike/mod.rs | 29 + vendor/libc/src/unix/bsd/mod.rs | 14 +- vendor/libc/src/unix/bsd/netbsdlike/mod.rs | 9 + .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 124 +- .../src/unix/bsd/netbsdlike/openbsd/mod.rs | 8 + .../src/unix/linux_like/android/b32/arm.rs | 2 +- .../src/unix/linux_like/android/b32/mod.rs | 9 + .../linux_like/android/b64/aarch64/mod.rs | 1 + .../src/unix/linux_like/android/b64/mod.rs | 8 + .../unix/linux_like/android/b64/x86_64/mod.rs | 1 + .../libc/src/unix/linux_like/android/mod.rs | 88 + .../src/unix/linux_like/emscripten/mod.rs | 3 - .../src/unix/linux_like/linux/gnu/b32/mod.rs | 18 + .../src/unix/linux_like/linux/gnu/b64/mod.rs | 27 + .../libc/src/unix/linux_like/linux/gnu/mod.rs | 47 + vendor/libc/src/unix/linux_like/linux/mod.rs | 72 +- .../src/unix/linux_like/linux/uclibc/mod.rs | 2 + vendor/libc/src/unix/linux_like/mod.rs | 5 + vendor/libc/src/unix/solarish/illumos.rs | 8 + vendor/libc/src/unix/solarish/mod.rs | 42 + vendor/libc/src/wasi.rs | 13 + vendor/libc/src/windows/mod.rs | 6 + vendor/memchr/.cargo-checksum.json | 2 +- vendor/memchr/Cargo.toml | 25 +- vendor/memchr/README.md | 24 +- .../memchr/scripts/make-byte-frequency-table | 74 + vendor/memchr/src/cow.rs | 2 +- vendor/memchr/src/lib.rs | 2 +- vendor/memchr/src/memmem/genericsimd.rs | 6 +- .../memchr/src/memmem/prefilter/fallback.rs | 2 +- vendor/memchr/src/memmem/prefilter/mod.rs | 4 +- vendor/memchr/src/tests/memchr/testdata.rs | 2 +- vendor/memmap2-0.2.1/.cargo-checksum.json | 1 + .../{memmap2 => memmap2-0.2.1}/CHANGELOG.md | 28 +- vendor/{memmap2 => memmap2-0.2.1}/Cargo.lock | 14 +- vendor/{memmap2 => memmap2-0.2.1}/Cargo.toml | 2 +- .../{memmap2 => memmap2-0.2.1}/LICENSE-APACHE | 0 vendor/{memmap2 => memmap2-0.2.1}/LICENSE-MIT | 0 vendor/{memmap2 => memmap2-0.2.1}/README.md | 0 .../examples/cat.rs | 0 vendor/{memmap2 => memmap2-0.2.1}/src/lib.rs | 141 +- vendor/{memmap2 => memmap2-0.2.1}/src/unix.rs | 53 +- .../{memmap2 => memmap2-0.2.1}/src/windows.rs | 68 +- vendor/memmap2/.cargo-checksum.json | 1 - vendor/memmap2/src/stub.rs | 76 - vendor/num-integer/.cargo-checksum.json | 2 +- vendor/num-integer/Cargo.toml | 4 +- vendor/num-integer/README.md | 16 +- vendor/num-integer/RELEASES.md | 10 - vendor/num-integer/build.rs | 9 +- vendor/num-traits/.cargo-checksum.json | 2 +- vendor/num-traits/Cargo.toml | 4 +- vendor/num-traits/README.md | 15 - vendor/num-traits/RELEASES.md | 27 - vendor/num-traits/build.rs | 10 +- vendor/num-traits/src/cast.rs | 76 +- vendor/num-traits/src/lib.rs | 14 +- vendor/num-traits/src/ops/mod.rs | 1 - vendor/num-traits/src/ops/overflowing.rs | 104 - vendor/num-traits/src/sign.rs | 13 +- vendor/num-traits/tests/cast.rs | 3 +- vendor/object/.cargo-checksum.json | 2 +- vendor/object/CHANGELOG.md | 85 + vendor/object/Cargo.lock | 32 +- vendor/object/Cargo.toml | 11 +- vendor/object/README.md | 19 + vendor/object/examples/readobj.rs | 170 +- vendor/object/src/common.rs | 5 + vendor/object/src/elf.rs | 203 +- vendor/object/src/lib.rs | 20 + vendor/object/src/pe.rs | 10 + vendor/object/src/pod.rs | 424 +- vendor/object/src/read/any.rs | 60 +- vendor/object/src/read/archive.rs | 69 +- vendor/object/src/read/coff/file.rs | 27 +- vendor/object/src/read/coff/section.rs | 9 +- vendor/object/src/read/coff/symbol.rs | 88 +- vendor/object/src/read/elf/file.rs | 45 +- vendor/object/src/read/elf/hash.rs | 211 + vendor/object/src/read/elf/mod.rs | 6 + vendor/object/src/read/elf/note.rs | 4 +- vendor/object/src/read/elf/relocation.rs | 8 +- vendor/object/src/read/elf/section.rs | 299 +- vendor/object/src/read/elf/segment.rs | 4 +- vendor/object/src/read/elf/symbol.rs | 112 +- vendor/object/src/read/elf/version.rs | 175 + vendor/object/src/read/macho/dyld_cache.rs | 4 +- vendor/object/src/read/macho/file.rs | 2 +- vendor/object/src/read/macho/load_command.rs | 18 +- vendor/object/src/read/macho/symbol.rs | 19 +- vendor/object/src/read/mod.rs | 9 +- vendor/object/src/read/pe/file.rs | 33 +- vendor/object/src/read/pe/section.rs | 8 +- vendor/object/src/read/read_cache.rs | 28 +- vendor/object/src/read/read_ref.rs | 16 +- vendor/object/src/read/util.rs | 358 +- vendor/object/src/write/coff.rs | 25 +- vendor/object/src/write/elf.rs | 54 +- vendor/object/src/write/macho.rs | 27 +- vendor/object/src/write/mod.rs | 14 +- vendor/object/src/write/util.rs | 116 +- vendor/once_cell/.cargo-checksum.json | 2 +- vendor/once_cell/CHANGELOG.md | 4 + vendor/once_cell/Cargo.lock | 20 +- vendor/once_cell/Cargo.toml | 4 +- vendor/once_cell/src/lib.rs | 134 +- vendor/once_cell/src/race.rs | 2 +- vendor/opener/.cargo-checksum.json | 2 +- vendor/opener/Cargo.toml | 9 +- vendor/opener/Drakefile.ts | 79 + vendor/opener/LICENSE-APACHE | 0 vendor/opener/LICENSE-MIT | 0 vendor/opener/LICENSE-THIRD-PARTY | 0 vendor/opener/Makefile.toml | 10 - vendor/opener/release.toml | 4 - vendor/opener/src/lib.rs | 241 +- vendor/opener/src/linux_and_more.rs | 108 + vendor/opener/src/macos.rs | 15 + vendor/opener/src/windows.rs | 41 + vendor/opener/src/xdg-open | 2 +- vendor/opener/tests/version-numbers.rs | 4 + vendor/pin-project-lite/.cargo-checksum.json | 2 +- vendor/pin-project-lite/CHANGELOG.md | 7 +- vendor/pin-project-lite/Cargo.toml | 4 +- vendor/pin-project-lite/README.md | 5 - vendor/pin-project-lite/src/lib.rs | 123 +- vendor/pin-project-lite/tests/compiletest.rs | 2 +- vendor/pin-project-lite/tests/drop_order.rs | 2 +- .../tests/expand/pinned_drop/enum.expanded.rs | 95 + .../tests/expand/pinned_drop/enum.rs | 22 + .../expand/pinned_drop/struct.expanded.rs | 92 + .../tests/expand/pinned_drop/struct.rs | 17 + vendor/pin-project-lite/tests/expandtest.rs | 10 +- vendor/pin-project-lite/tests/lint.rs | 28 +- vendor/pin-project-lite/tests/test.rs | 35 +- .../tests/ui/pin_project/conflict-drop.stderr | 4 +- .../ui/pin_project/conflict-unpin.stderr | 12 +- .../ui/pin_project/invalid-bounds.stderr | 24 +- .../tests/ui/pin_project/invalid.stderr | 4 +- .../pin_project/overlapping_lifetime_names.rs | 4 +- .../overlapping_lifetime_names.stderr | 64 +- .../pin_project/overlapping_unpin_struct.rs | 3 +- .../overlapping_unpin_struct.stderr | 19 +- .../tests/ui/pin_project/packed.rs | 2 + .../tests/ui/pin_project/packed.stderr | 130 +- .../tests/ui/pin_project/unsupported.stderr | 10 +- .../tests/ui/pinned_drop/call-drop-inner.rs | 17 + .../ui/pinned_drop/call-drop-inner.stderr | 20 + .../ui/pinned_drop/conditional-drop-impl.rs | 26 + .../pinned_drop/conditional-drop-impl.stderr | 38 + vendor/redox_syscall/.cargo-checksum.json | 2 +- vendor/redox_syscall/Cargo.toml | 2 +- vendor/redox_syscall/src/io/io.rs | 12 +- vendor/redox_syscall/src/lib.rs | 1 - vendor/regex-1.4.3/.cargo-checksum.json | 1 - vendor/regex-1.4.3/Cargo.lock | 230 - vendor/regex-1.4.3/LICENSE-APACHE | 201 - vendor/regex-1.4.3/rustfmt.toml | 2 - vendor/regex-1.4.3/src/cache.rs | 100 - vendor/regex-1.4.6/.cargo-checksum.json | 1 + .../{regex-1.4.3 => regex-1.4.6}/CHANGELOG.md | 41 + vendor/regex-1.4.6/Cargo.lock | 98 + .../{regex-1.4.3 => regex-1.4.6}/Cargo.toml | 14 +- .../{regex-1.4.3 => regex-1.4.6}/HACKING.md | 0 .../LICENSE-APACHE | 0 .../{regex-1.4.3 => regex-1.4.6}/LICENSE-MIT | 0 .../PERFORMANCE.md | 0 vendor/{regex-1.4.3 => regex-1.4.6}/README.md | 6 +- .../{regex-1.4.3 => regex-1.4.6}/UNICODE.md | 34 +- .../examples/regexdna-input.txt | 0 .../examples/regexdna-output.txt | 0 .../examples/shootout-regex-dna-bytes.rs | 0 .../examples/shootout-regex-dna-cheat.rs | 0 .../examples/shootout-regex-dna-replace.rs | 0 .../shootout-regex-dna-single-cheat.rs | 0 .../examples/shootout-regex-dna-single.rs | 0 .../examples/shootout-regex-dna.rs | 0 .../{byteorder => regex-1.4.6}/rustfmt.toml | 0 .../src/backtrack.rs | 4 +- .../src/compile.rs | 17 +- .../{regex-1.4.3 => regex-1.4.6}/src/dfa.rs | 20 +- .../{regex-1.4.3 => regex-1.4.6}/src/error.rs | 0 .../{regex-1.4.3 => regex-1.4.6}/src/exec.rs | 41 +- .../src/expand.rs | 3 +- .../src/find_byte.rs | 0 .../{regex-1.4.3 => regex-1.4.6}/src/freqs.rs | 0 .../{regex-1.4.3 => regex-1.4.6}/src/input.rs | 0 .../{regex-1.4.3 => regex-1.4.6}/src/lib.rs | 18 +- .../src/literal/imp.rs | 0 .../src/literal/mod.rs | 0 .../src/pattern.rs | 0 .../src/pikevm.rs | 0 vendor/regex-1.4.6/src/pool.rs | 333 ++ .../{regex-1.4.3 => regex-1.4.6}/src/prog.rs | 19 +- .../src/re_builder.rs | 0 .../src/re_bytes.rs | 59 +- .../src/re_set.rs | 2 +- .../src/re_trait.rs | 0 .../src/re_unicode.rs | 59 +- .../src/sparse.rs | 2 +- .../src/testdata/LICENSE | 0 .../src/testdata/README | 0 .../src/testdata/basic.dat | 0 .../src/testdata/nullsubexpr.dat | 0 .../src/testdata/repetition.dat | 0 .../{regex-1.4.3 => regex-1.4.6}/src/utf8.rs | 0 vendor/{regex-1.4.3 => regex-1.4.6}/test | 0 .../{regex-1.4.3 => regex-1.4.6}/tests/api.rs | 0 .../tests/api_str.rs | 0 .../tests/bytes.rs | 0 .../tests/consistent.rs | 5 +- .../tests/crates_regex.rs | 0 .../tests/crazy.rs | 5 +- .../tests/flags.rs | 0 .../tests/fowler.rs | 0 .../tests/macros.rs | 0 .../tests/macros_bytes.rs | 1 - .../tests/macros_str.rs | 1 + .../tests/misc.rs | 0 .../tests/multiline.rs | 0 .../tests/noparse.rs | 0 .../tests/regression.rs | 0 .../tests/regression_fuzz.rs | 12 + .../tests/replace.rs | 98 + .../tests/searcher.rs | 0 .../{regex-1.4.3 => regex-1.4.6}/tests/set.rs | 0 .../tests/shortest_match.rs | 0 .../tests/suffix_reverse.rs | 0 .../tests/test_backtrack.rs | 0 .../tests/test_backtrack_bytes.rs | 0 .../tests/test_backtrack_utf8bytes.rs | 0 .../tests/test_crates_regex.rs | 0 .../tests/test_default.rs | 42 +- .../tests/test_default_bytes.rs | 0 .../tests/test_nfa.rs | 0 .../tests/test_nfa_bytes.rs | 0 .../tests/test_nfa_utf8bytes.rs | 0 .../tests/unicode.rs | 0 .../tests/word_boundary.rs | 0 .../tests/word_boundary_ascii.rs | 0 .../tests/word_boundary_unicode.rs | 0 vendor/regex-automata/.cargo-checksum.json | 2 +- vendor/regex-automata/Cargo.toml | 6 +- vendor/regex-automata/README.md | 11 +- vendor/regex-automata/src/byteorder.rs | 76 + vendor/regex-automata/src/determinize.rs | 3 +- vendor/regex-automata/src/lib.rs | 2 +- vendor/regex-automata/src/sparse_set.rs | 2 +- vendor/rustc-demangle/.cargo-checksum.json | 2 +- vendor/rustc-demangle/Cargo.toml | 2 +- vendor/rustc-demangle/src/v0.rs | 646 ++- vendor/rustfix-0.5.1/.cargo-checksum.json | 1 + vendor/rustfix-0.5.1/Cargo.toml | 52 + vendor/rustfix-0.5.1/Changelog.md | 79 + vendor/rustfix-0.5.1/LICENSE-APACHE | 202 + vendor/rustfix-0.5.1/LICENSE-MIT | 21 + vendor/rustfix-0.5.1/Readme.md | 41 + .../proptest-regressions/replace.txt | 8 + vendor/rustfix-0.5.1/src/diagnostics.rs | 89 + vendor/rustfix-0.5.1/src/lib.rs | 268 + vendor/rustfix-0.5.1/src/replace.rs | 327 ++ vendor/rustfix/.cargo-checksum.json | 2 +- vendor/rustfix/Cargo.toml | 8 +- vendor/rustfix/Readme.md | 2 +- vendor/rustfix/src/lib.rs | 3 +- vendor/rustfix/src/replace.rs | 6 +- vendor/rustversion/.cargo-checksum.json | 2 +- vendor/rustversion/Cargo.toml | 2 +- vendor/rustversion/build/build.rs | 6 + vendor/rustversion/build/rustc.rs | 30 +- vendor/rustversion/src/lib.rs | 15 + vendor/rustversion/src/time.rs | 13 +- vendor/rustversion/tests/test_parse.rs | 10 + vendor/rustversion/tests/ui/bad-bound.stderr | 4 +- vendor/rustversion/tests/ui/bad-date.stderr | 4 +- vendor/semver-0.10.0/.cargo-checksum.json | 1 - vendor/semver-0.10.0/Cargo.toml | 43 - vendor/semver-0.10.0/LICENSE-APACHE | 201 - vendor/semver-0.10.0/LICENSE-MIT | 25 - vendor/semver-0.10.0/README.md | 103 - vendor/semver-0.10.0/src/diesel_impls.rs | 45 - vendor/semver-0.10.0/src/lib.rs | 222 - vendor/semver-0.10.0/src/version.rs | 871 ---- vendor/semver-0.10.0/src/version_req.rs | 1031 ---- vendor/semver-0.10.0/tests/deprecation.rs | 25 - vendor/semver-0.10.0/tests/diesel.rs | 209 - vendor/semver-0.10.0/tests/serde.rs | 93 - .../semver-parser-0.7.0/.cargo-checksum.json | 1 - vendor/semver-parser-0.7.0/Cargo.toml | 11 - vendor/semver-parser-0.7.0/LICENSE-APACHE | 201 - vendor/semver-parser-0.7.0/LICENSE-MIT | 25 - vendor/semver-parser-0.7.0/src/common.rs | 66 - vendor/semver-parser-0.7.0/src/lib.rs | 8 - vendor/semver-parser-0.7.0/src/range.rs | 696 --- vendor/semver-parser-0.7.0/src/recognize.rs | 154 - vendor/semver-parser-0.7.0/src/version.rs | 365 -- vendor/syn/.cargo-checksum.json | 2 +- vendor/syn/Cargo.toml | 2 +- vendor/syn/src/attr.rs | 2 +- vendor/syn/src/data.rs | 2 +- vendor/syn/src/discouraged.rs | 2 +- vendor/syn/src/error.rs | 2 +- vendor/syn/src/expr.rs | 28 +- vendor/syn/src/gen/visit.rs | 756 +-- vendor/syn/src/gen/visit_mut.rs | 756 +-- vendor/syn/src/item.rs | 2 +- vendor/syn/src/lib.rs | 2 +- vendor/syn/src/lifetime.rs | 2 +- vendor/syn/src/lit.rs | 14 +- vendor/syn/src/punctuated.rs | 2 +- vendor/syn/tests/common/eq.rs | 8 +- vendor/tera/.cargo-checksum.json | 1 + vendor/tera/CHANGELOG.md | 466 ++ vendor/tera/Cargo.toml | 88 + vendor/tera/LICENSE | 22 + vendor/tera/README.md | 31 + vendor/tera/docs/README.md | 4 + vendor/tera/src/builtins/filters/array.rs | 835 +++ vendor/tera/src/builtins/filters/common.rs | 357 ++ vendor/tera/src/builtins/filters/mod.rs | 30 + vendor/tera/src/builtins/filters/number.rs | 181 + vendor/tera/src/builtins/filters/object.rs | 53 + vendor/tera/src/builtins/filters/string.rs | 848 +++ vendor/tera/src/builtins/functions.rs | 341 ++ vendor/tera/src/builtins/mod.rs | 3 + vendor/tera/src/builtins/testers.rs | 348 ++ vendor/tera/src/context.rs | 287 ++ vendor/tera/src/errors.rs | 234 + vendor/tera/src/filter_utils.rs | 176 + vendor/tera/src/lib.rs | 50 + vendor/tera/src/macros.rs | 35 + vendor/tera/src/parser/ast.rs | 353 ++ vendor/tera/src/parser/mod.rs | 1223 +++++ vendor/tera/src/parser/tera.pest | 316 ++ vendor/tera/src/parser/tests/errors.rs | 290 ++ vendor/tera/src/parser/tests/lexer.rs | 688 +++ vendor/tera/src/parser/tests/mod.rs | 4 + vendor/tera/src/parser/tests/parser.rs | 1114 ++++ vendor/tera/src/parser/tests/whitespace.rs | 264 + vendor/tera/src/parser/whitespace.rs | 188 + vendor/tera/src/renderer/call_stack.rs | 234 + vendor/tera/src/renderer/for_loop.rs | 181 + vendor/tera/src/renderer/macros.rs | 119 + vendor/tera/src/renderer/mod.rs | 62 + vendor/tera/src/renderer/processor.rs | 1060 ++++ vendor/tera/src/renderer/square_brackets.rs | 51 + vendor/tera/src/renderer/stack_frame.rs | 202 + vendor/tera/src/renderer/tests/basic.rs | 972 ++++ vendor/tera/src/renderer/tests/errors.rs | 284 ++ vendor/tera/src/renderer/tests/inheritance.rs | 176 + vendor/tera/src/renderer/tests/macros.rs | 356 ++ vendor/tera/src/renderer/tests/mod.rs | 32 + .../src/renderer/tests/square_brackets.rs | 94 + vendor/tera/src/renderer/tests/whitespace.rs | 118 + vendor/tera/src/template.rs | 170 + vendor/tera/src/tera.rs | 1183 +++++ vendor/tera/src/utils.rs | 85 + .../tracing-subscriber/.cargo-checksum.json | 2 +- vendor/tracing-subscriber/CHANGELOG.md | 32 + vendor/tracing-subscriber/Cargo.toml | 2 +- .../tracing-subscriber/src/filter/env/mod.rs | 7 +- vendor/tracing-subscriber/src/filter/level.rs | 2 +- .../tracing-subscriber/src/fmt/fmt_layer.rs | 86 +- .../tracing-subscriber/src/fmt/format/json.rs | 6 +- .../tracing-subscriber/src/fmt/format/mod.rs | 47 +- .../src/fmt/format/pretty.rs | 10 +- vendor/tracing-subscriber/src/fmt/mod.rs | 5 + vendor/tracing-subscriber/src/fmt/writer.rs | 1188 ++++- vendor/tracing-subscriber/src/layer.rs | 276 +- vendor/tracing-subscriber/src/lib.rs | 2 +- vendor/tracing-subscriber/src/prelude.rs | 4 + vendor/tracing-subscriber/src/registry/mod.rs | 342 +- .../.cargo-checksum.json | 2 +- vendor/unicode-normalization/Cargo.toml | 2 +- vendor/unicode-normalization/README.md | 2 +- .../unicode-normalization/scripts/unicode.py | 15 +- vendor/unicode-normalization/src/lib.rs | 2 +- vendor/unicode-normalization/src/tables.rs | 31 +- vendor/unicode-script/.cargo-checksum.json | 2 +- vendor/unicode-script/Cargo.toml | 2 +- vendor/unicode-script/scripts/unicode.py | 72 +- vendor/unicode-script/src/lib.rs | 19 +- vendor/unicode-script/src/tables.rs | 337 +- .../unicode-segmentation/.cargo-checksum.json | 2 +- vendor/unicode-segmentation/Cargo.toml | 15 +- vendor/unicode-segmentation/README.md | 2 +- .../unicode-segmentation/benches/graphemes.rs | 59 +- .../benches/unicode_words.rs | 64 + .../benches/word_bounds.rs | 64 + .../unicode-segmentation/scripts/unicode.py | 5 +- vendor/unicode-segmentation/src/grapheme.rs | 30 +- vendor/unicode-segmentation/src/lib.rs | 31 +- vendor/unicode-segmentation/src/sentence.rs | 8 +- vendor/unicode-segmentation/src/tables.rs | 8 +- vendor/unicode-segmentation/src/test.rs | 6 +- vendor/unicode-segmentation/src/word.rs | 65 +- version | 2 +- 3897 files changed, 86571 insertions(+), 54438 deletions(-) delete mode 100755 compiler/rustc_codegen_cranelift/build.sh delete mode 100755 compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh delete mode 100755 compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh create mode 100644 compiler/rustc_codegen_cranelift/build_system/build_backend.rs create mode 100644 compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs create mode 100644 compiler/rustc_codegen_cranelift/build_system/config.rs create mode 100644 compiler/rustc_codegen_cranelift/build_system/prepare.rs create mode 100644 compiler/rustc_codegen_cranelift/build_system/rustc_info.rs create mode 100644 compiler/rustc_codegen_cranelift/build_system/utils.rs create mode 100644 compiler/rustc_codegen_cranelift/config.txt rename compiler/rustc_codegen_cranelift/{crate_patches => patches}/0001-compiler-builtins-Disable-128bit-atomic-operations.patch (100%) rename compiler/rustc_codegen_cranelift/{crate_patches => patches}/0001-rand-Enable-c2-chacha-simd-feature.patch (100%) rename compiler/rustc_codegen_cranelift/{crate_patches => patches}/0002-rand-Disable-failing-test.patch (100%) rename compiler/rustc_codegen_cranelift/patches/{0022-core-Disable-not-compiling-tests.patch => 0022-sysroot-Disable-not-compiling-tests.patch} (100%) rename compiler/rustc_codegen_cranelift/patches/{0023-core-Ignore-failing-tests.patch => 0023-sysroot-Ignore-failing-tests.patch} (100%) rename compiler/rustc_codegen_cranelift/patches/{0027-Disable-128bit-atomic-operations.patch => 0027-sysroot-128bit-atomic-operations.patch} (100%) delete mode 100755 compiler/rustc_codegen_cranelift/prepare.sh create mode 100644 compiler/rustc_codegen_cranelift/scripts/cargo.rs delete mode 100755 compiler/rustc_codegen_cranelift/scripts/cargo.sh create mode 100755 compiler/rustc_codegen_cranelift/y.rs create mode 100644 compiler/rustc_error_codes/src/error_codes/E0632.md create mode 100644 compiler/rustc_error_codes/src/error_codes/E0722.md create mode 100644 compiler/rustc_error_codes/src/error_codes/E0757.md create mode 100644 compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs create mode 100644 compiler/rustc_lint/src/tests.rs rename compiler/rustc_middle/src/ty/{query/mod.rs => query.rs} (91%) create mode 100644 compiler/rustc_middle/src/ty/vtable.rs create mode 100644 compiler/rustc_mir/src/monomorphize/util.rs create mode 100644 compiler/rustc_mir/src/transform/lower_slice_len.rs rename compiler/{rustc_middle/src/ty/query => rustc_query_impl/src}/on_disk_cache.rs (90%) delete mode 100644 compiler/rustc_span/src/crate_disambiguator.rs delete mode 100644 compiler/rustc_target/src/spec/arm_base.rs create mode 100644 compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs delete mode 100644 compiler/rustc_target/src/spec/riscv_base.rs create mode 100644 compiler/rustc_target/src/tests.rs create mode 100644 compiler/rustc_typeck/src/check/method/prelude2021.rs create mode 100644 compiler/rustc_typeck/src/hir_wf_check.rs create mode 100644 library/core/src/array/equality.rs create mode 100644 library/core/src/fmt/nofloat.rs delete mode 100644 library/core/src/num/dec2flt/algorithm.rs create mode 100644 library/core/src/num/dec2flt/common.rs create mode 100644 library/core/src/num/dec2flt/decimal.rs create mode 100644 library/core/src/num/dec2flt/float.rs create mode 100644 library/core/src/num/dec2flt/fpu.rs create mode 100644 library/core/src/num/dec2flt/lemire.rs delete mode 100644 library/core/src/num/dec2flt/num.rs create mode 100644 library/core/src/num/dec2flt/number.rs delete mode 100644 library/core/src/num/dec2flt/rawfp.rs create mode 100644 library/core/src/num/dec2flt/slow.rs create mode 100644 library/core/src/num/fmt.rs create mode 100644 library/core/src/num/int_log10.rs delete mode 100644 library/core/src/ops/try.rs delete mode 100644 library/core/src/raw.rs create mode 100644 library/core/tests/num/dec2flt/float.rs create mode 100644 library/core/tests/num/dec2flt/lemire.rs delete mode 100644 library/core/tests/num/dec2flt/rawfp.rs create mode 100644 library/core/tests/num/int_log.rs rename library/std/src/os/unix/{ffi.rs => ffi/mod.rs} (93%) create mode 100644 library/std/src/os/unix/ffi/os_str.rs create mode 100644 library/std/src/sys/windows/c/errors.rs delete mode 100644 library/std/src/sys_common/bytestring.rs delete mode 100644 library/std/src/sys_common/bytestring/tests.rs create mode 100644 library/std/src/sys_common/os_str_bytes/tests.rs delete mode 100644 library/std/src/thread/available_concurrency.rs delete mode 100644 library/term/Cargo.toml delete mode 100644 library/term/src/lib.rs create mode 100644 library/test/src/term.rs rename library/{term/src => test/src/term}/terminfo/mod.rs (69%) rename library/{term/src => test/src/term}/terminfo/parm.rs (92%) rename library/{term/src => test/src/term}/terminfo/parm/tests.rs (87%) rename library/{term/src => test/src/term}/terminfo/parser/compiled.rs (96%) rename library/{term/src => test/src/term}/terminfo/parser/compiled/tests.rs (100%) rename library/{term/src => test/src/term}/terminfo/searcher.rs (96%) rename library/{term/src => test/src/term}/terminfo/searcher/tests.rs (100%) rename library/{term/src => test/src/term}/win.rs (78%) create mode 100644 src/doc/book/nostarch/chapter02.md delete mode 100644 src/doc/book/src/img/ferris/unsafe.svg create mode 100644 src/doc/edition-guide/src/editions/advanced-migrations.md create mode 100644 src/doc/edition-guide/triagebot.toml delete mode 100644 src/doc/nomicon/src/README.md rename src/doc/nomicon/src/{ => arc-mutex}/arc-and-mutex.md (62%) rename src/doc/nomicon/src/{ => arc-mutex}/arc-base.md (94%) rename src/doc/nomicon/src/{ => arc-mutex}/arc-clone.md (91%) rename src/doc/nomicon/src/{ => arc-mutex}/arc-drop.md (94%) rename src/doc/nomicon/src/{ => arc-mutex}/arc-final.md (99%) rename src/doc/nomicon/src/{ => arc-mutex}/arc-layout.md (93%) rename src/doc/nomicon/src/{ => arc-mutex}/arc.md (86%) create mode 100644 src/doc/nomicon/src/intro.md rename src/doc/nomicon/src/{ => vec}/vec-alloc.md (96%) rename src/doc/nomicon/src/{ => vec}/vec-dealloc.md (96%) rename src/doc/nomicon/src/{ => vec}/vec-deref.md (94%) rename src/doc/nomicon/src/{ => vec}/vec-drain.md (96%) rename src/doc/nomicon/src/{ => vec}/vec-final.md (100%) rename src/doc/nomicon/src/{ => vec}/vec-insert-remove.md (96%) rename src/doc/nomicon/src/{ => vec}/vec-into-iter.md (96%) rename src/doc/nomicon/src/{ => vec}/vec-layout.md (94%) rename src/doc/nomicon/src/{ => vec}/vec-push-pop.md (96%) rename src/doc/nomicon/src/{ => vec}/vec-raw.md (97%) rename src/doc/nomicon/src/{ => vec}/vec-zsts.md (98%) rename src/doc/nomicon/src/{ => vec}/vec.md (100%) create mode 100644 src/doc/nomicon/theme/nomicon.css create mode 100644 src/doc/rust-by-example/.github/workflows/rbe.yml create mode 100644 src/doc/rustc-dev-guide/src/lang-items.md create mode 100644 src/doc/rustdoc/src/website-features.md rename src/doc/unstable-book/src/compiler-flags/{force-warns.md => force-warn.md} (70%) create mode 100644 src/doc/unstable-book/src/language-features/exclusive-range-pattern.md create mode 100644 src/doc/unstable-book/src/language-features/half-open-range-patterns.md delete mode 100644 src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md delete mode 100644 src/doc/unstable-book/src/library-features/try-trait.md mode change 100755 => 100644 src/etc/dec2flt_table.py create mode 100644 src/etc/test-float-parse/Cargo.toml rename src/etc/test-float-parse/{ => src/bin}/few-ones.rs (87%) rename src/etc/test-float-parse/{ => src/bin}/huge-pow10.rs (77%) rename src/etc/test-float-parse/{ => src/bin}/long-fractions.rs (88%) rename src/etc/test-float-parse/{ => src/bin}/many-digits.rs (93%) rename src/etc/test-float-parse/{ => src/bin}/rand-f64.rs (89%) rename src/etc/test-float-parse/{ => src/bin}/short-decimals.rs (93%) rename src/etc/test-float-parse/{ => src/bin}/subnorm.rs (88%) rename src/etc/test-float-parse/{ => src/bin}/tiny-pow10.rs (78%) rename src/etc/test-float-parse/{ => src/bin}/u32-small.rs (69%) rename src/etc/test-float-parse/{ => src/bin}/u64-pow2.rs (90%) rename src/etc/test-float-parse/{_common.rs => src/lib.rs} (100%) create mode 100644 src/librustdoc/html/static/css/normalize.css rename src/librustdoc/html/static/{ => css}/noscript.css (100%) rename src/librustdoc/html/static/{ => css}/rustdoc.css (93%) rename src/librustdoc/html/static/{ => css}/settings.css (100%) rename src/librustdoc/html/static/{ => css}/themes/ayu.css (98%) rename src/librustdoc/html/static/{ => css}/themes/dark.css (98%) rename src/librustdoc/html/static/{ => css}/themes/light.css (98%) rename src/librustdoc/html/static/{ => fonts}/FiraSans-LICENSE.txt (99%) rename src/librustdoc/html/static/{ => fonts}/FiraSans-Medium.woff (100%) rename src/librustdoc/html/static/{ => fonts}/FiraSans-Medium.woff2 (100%) rename src/librustdoc/html/static/{ => fonts}/FiraSans-Regular.woff (100%) rename src/librustdoc/html/static/{ => fonts}/FiraSans-Regular.woff2 (100%) rename src/librustdoc/html/static/{ => fonts}/SourceCodePro-It.ttf.woff (100%) create mode 100644 src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff2 rename src/librustdoc/html/static/{ => fonts}/SourceCodePro-LICENSE.txt (100%) rename src/librustdoc/html/static/{ => fonts}/SourceCodePro-Regular.ttf.woff (100%) create mode 100644 src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff2 rename src/librustdoc/html/static/{ => fonts}/SourceCodePro-Semibold.ttf.woff (100%) create mode 100644 src/librustdoc/html/static/fonts/SourceCodePro-Semibold.ttf.woff2 rename src/librustdoc/html/static/{ => fonts}/SourceSerif4-Bold.ttf.woff (100%) create mode 100644 src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 rename src/librustdoc/html/static/{ => fonts}/SourceSerif4-It.ttf.woff (100%) create mode 100644 src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 rename src/librustdoc/html/static/{ => fonts}/SourceSerif4-LICENSE.md (100%) rename src/librustdoc/html/static/{ => fonts}/SourceSerif4-Regular.ttf.woff (100%) create mode 100644 src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 rename src/librustdoc/html/static/{ => images}/brush.svg (100%) rename src/librustdoc/html/static/{ => images}/clipboard.svg (100%) rename src/librustdoc/html/static/{ => images}/down-arrow.svg (100%) rename src/librustdoc/html/static/{ => images}/favicon-16x16.png (100%) rename src/librustdoc/html/static/{ => images}/favicon-32x32.png (100%) rename src/librustdoc/html/static/{ => images}/favicon.svg (100%) rename src/librustdoc/html/static/{ => images}/rust-logo.png (100%) rename src/librustdoc/html/static/{ => images}/wheel.svg (100%) rename src/librustdoc/html/static/{ => js}/main.js (97%) rename src/librustdoc/html/static/{ => js}/search.js (94%) rename src/librustdoc/html/static/{ => js}/settings.js (100%) rename src/librustdoc/html/static/{ => js}/source-script.js (100%) rename src/librustdoc/html/static/{ => js}/storage.js (97%) delete mode 100644 src/librustdoc/html/static/normalize.css delete mode 100644 src/librustdoc/html/static/noto-sans-kr-v13-korean-regular-LICENSE.txt delete mode 100644 src/librustdoc/html/static/noto-sans-kr-v13-korean-regular.woff create mode 100644 src/librustdoc/html/templates/STYLE.md create mode 100644 src/librustdoc/html/templates/page.html create mode 100644 src/test/codegen/align-fn.rs create mode 100644 src/test/codegen/array-equality.rs create mode 100644 src/test/codegen/asm-clobbers.rs create mode 100644 src/test/codegen/frame-pointer.rs create mode 100644 src/test/debuginfo/duration-type.rs create mode 100644 src/test/debuginfo/fixed-sized-array.rs create mode 100644 src/test/debuginfo/function-names.rs create mode 100644 src/test/debuginfo/marker-types.rs create mode 100644 src/test/debuginfo/mutable-locs.rs create mode 100644 src/test/debuginfo/mutex.rs create mode 100644 src/test/debuginfo/numeric-types.rs create mode 100644 src/test/debuginfo/pretty-slices.rs create mode 100644 src/test/debuginfo/range-types.rs create mode 100644 src/test/debuginfo/result-types.rs create mode 100644 src/test/debuginfo/rwlock-read.rs create mode 100644 src/test/debuginfo/rwlock-write.rs create mode 100644 src/test/debuginfo/thread.rs create mode 100644 src/test/debuginfo/type-names.cdb.js create mode 100644 src/test/incremental/issue-86753.rs create mode 100644 src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff create mode 100644 src/test/mir-opt/lower_slice_len.rs create mode 100644 src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir create mode 100644 src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff create mode 100644 src/test/mir-opt/uninhabited_enum_branching2.rs create mode 100644 src/test/pretty/hir-pretty-loop.pp create mode 100644 src/test/pretty/hir-pretty-loop.rs create mode 100644 src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile create mode 100644 src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json create mode 100644 src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json create mode 100644 src/test/run-make/emit-path-unhashed/Makefile create mode 100644 src/test/run-make/emit-path-unhashed/foo.rs create mode 100644 src/test/run-make/raw-dylib-alt-calling-convention/Makefile create mode 100644 src/test/run-make/raw-dylib-alt-calling-convention/driver.rs create mode 100644 src/test/run-make/raw-dylib-alt-calling-convention/extern.c create mode 100644 src/test/run-make/raw-dylib-alt-calling-convention/lib.rs create mode 100644 src/test/run-make/raw-dylib-alt-calling-convention/output.txt rename src/test/run-make/{raw-dylib => raw-dylib-c}/Makefile (96%) rename src/test/run-make/{raw-dylib => raw-dylib-c}/driver.rs (100%) rename src/test/run-make/{raw-dylib => raw-dylib-c}/extern_1.c (100%) rename src/test/run-make/{raw-dylib => raw-dylib-c}/extern_2.c (100%) rename src/test/run-make/{raw-dylib => raw-dylib-c}/lib.rs (100%) rename src/test/run-make/{raw-dylib => raw-dylib-c}/output.txt (100%) create mode 100644 src/test/run-make/track-path-dep-info/Makefile create mode 100644 src/test/run-make/track-path-dep-info/emojis.txt create mode 100644 src/test/run-make/track-path-dep-info/macro_def.rs create mode 100644 src/test/run-make/track-path-dep-info/macro_use.rs rename src/test/run-make/unstable-flag-required/{force-warns.stderr => force-warn.stderr} (65%) create mode 100644 src/test/rustdoc-gui/auto-hide-trait-implementations.goml create mode 100644 src/test/rustdoc-gui/ayu-code-tag-colors.goml create mode 100644 src/test/rustdoc-gui/basic-code.goml create mode 100644 src/test/rustdoc-gui/basic.goml create mode 100644 src/test/rustdoc-gui/check_info_sign_position.goml create mode 100644 src/test/rustdoc-gui/code-blocks-overflow.goml create mode 100644 src/test/rustdoc-gui/code-sidebar-toggle.goml create mode 100644 src/test/rustdoc-gui/default-settings.goml create mode 100644 src/test/rustdoc-gui/docblock-table-overflow.goml create mode 100644 src/test/rustdoc-gui/escape-key.goml create mode 100644 src/test/rustdoc-gui/font-weight.goml create mode 100644 src/test/rustdoc-gui/hash-item-expansion.goml create mode 100644 src/test/rustdoc-gui/impl-default-expansion.goml create mode 100644 src/test/rustdoc-gui/implementors.goml create mode 100644 src/test/rustdoc-gui/item-info-width.goml create mode 100644 src/test/rustdoc-gui/item-summary-table.goml create mode 100644 src/test/rustdoc-gui/label-next-to-symbol.goml create mode 100644 src/test/rustdoc-gui/list_code_block.goml create mode 100644 src/test/rustdoc-gui/module-items-font.goml create mode 100644 src/test/rustdoc-gui/search-filter.goml create mode 100644 src/test/rustdoc-gui/search-input-mobile.goml create mode 100644 src/test/rustdoc-gui/search-result-color.goml create mode 100644 src/test/rustdoc-gui/search-result-colors.goml create mode 100644 src/test/rustdoc-gui/search-result-description.goml create mode 100644 src/test/rustdoc-gui/search-result-display.goml create mode 100644 src/test/rustdoc-gui/search-result-go-to-first.goml create mode 100644 src/test/rustdoc-gui/search-result-keyword.goml create mode 100644 src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml create mode 100644 src/test/rustdoc-gui/shortcuts.goml create mode 100644 src/test/rustdoc-gui/sidebar-mobile.goml create mode 100644 src/test/rustdoc-gui/sidebar.goml create mode 100644 src/test/rustdoc-gui/source-code-page.goml delete mode 100644 src/test/rustdoc-gui/src/lib2.rs create mode 100644 src/test/rustdoc-gui/src/lib2/Cargo.lock create mode 100644 src/test/rustdoc-gui/src/lib2/Cargo.toml create mode 100644 src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock create mode 100644 src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml create mode 100644 src/test/rustdoc-gui/src/lib2/implementors/lib.rs create mode 100644 src/test/rustdoc-gui/src/lib2/lib.rs create mode 100644 src/test/rustdoc-gui/src/settings/.cargo/config.toml delete mode 100644 src/test/rustdoc-gui/src/settings/.package-cache create mode 100644 src/test/rustdoc-gui/src/settings/Cargo.lock create mode 100644 src/test/rustdoc-gui/src/settings/Cargo.toml create mode 100644 src/test/rustdoc-gui/src/settings/lib.rs create mode 100644 src/test/rustdoc-gui/src/test_docs/Cargo.lock create mode 100644 src/test/rustdoc-gui/src/test_docs/Cargo.toml rename src/test/rustdoc-gui/src/{ => test_docs}/lib.rs (84%) create mode 100644 src/test/rustdoc-gui/theme-change.goml create mode 100644 src/test/rustdoc-gui/toggle-docs-mobile.goml create mode 100644 src/test/rustdoc-gui/toggle-docs.goml create mode 100644 src/test/rustdoc-gui/toggle-implementors.goml create mode 100644 src/test/rustdoc-gui/toggled-open-implementations.goml create mode 100644 src/test/rustdoc-gui/trait-sidebar-item-order.goml create mode 100644 src/test/rustdoc-gui/type-declation-overflow.goml delete mode 100644 src/test/rustdoc-gui/type-weight.rs create mode 100644 src/test/rustdoc-js-std/alias-4.js create mode 100644 src/test/rustdoc-js-std/typed-query.js create mode 100644 src/test/rustdoc-js/generics-trait.js create mode 100644 src/test/rustdoc-js/generics-trait.rs create mode 100644 src/test/rustdoc-js/generics.js create mode 100644 src/test/rustdoc-js/generics.rs create mode 100644 src/test/rustdoc-ui/intra-doc/field-ice.rs create mode 100644 src/test/rustdoc-ui/intra-doc/field-ice.stderr create mode 100644 src/test/rustdoc-ui/nocapture-fail.rs create mode 100644 src/test/rustdoc-ui/nocapture-fail.stderr create mode 100644 src/test/rustdoc-ui/nocapture-fail.stdout create mode 100644 src/test/rustdoc-ui/nocapture.rs create mode 100644 src/test/rustdoc-ui/nocapture.stderr create mode 100644 src/test/rustdoc-ui/nocapture.stdout create mode 100644 src/test/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs create mode 100644 src/test/rustdoc/auxiliary/issue-85454.rs create mode 100644 src/test/rustdoc/auxiliary/issue-86620-1.rs create mode 100644 src/test/rustdoc/auxiliary/reexports.rs create mode 100644 src/test/rustdoc/const-generics/const-evaluatable-checked.rs create mode 100644 src/test/rustdoc/cross-crate-hidden-impl-parameter.rs create mode 100644 src/test/rustdoc/default-theme.rs create mode 100644 src/test/rustdoc/duplicate-flags.rs delete mode 100644 src/test/rustdoc/for-lifetime.rs create mode 100644 src/test/rustdoc/higher-ranked-trait-bounds.rs create mode 100644 src/test/rustdoc/intra-doc/macros-disambiguators.rs create mode 100644 src/test/rustdoc/intra-doc/type-alias.rs delete mode 100644 src/test/rustdoc/issue-19055.rs create mode 100644 src/test/rustdoc/issue-86620.rs create mode 100644 src/test/rustdoc/macro_rules-matchers.rs delete mode 100644 src/test/rustdoc/must-use.rs create mode 100644 src/test/rustdoc/recursive-deref-sidebar.rs create mode 100644 src/test/rustdoc/recursive-deref.rs create mode 100644 src/test/rustdoc/reexports-priv.rs create mode 100644 src/test/rustdoc/reexports.rs create mode 100644 src/test/rustdoc/safe-intrinsic.rs create mode 100644 src/test/rustdoc/same-crate-hidden-impl-parameter.rs create mode 100644 src/test/rustdoc/short-docblock.rs delete mode 100644 src/test/rustdoc/short-dockblock.rs delete mode 100644 src/test/rustdoc/trait-attributes.rs create mode 100644 src/test/ui/abi/unsupported.aarch64.stderr create mode 100644 src/test/ui/abi/unsupported.i686.stderr create mode 100644 src/test/ui/abi/unsupported.rs create mode 100644 src/test/ui/abi/unsupported.x64.stderr rename src/test/ui/{issues => asm}/issue-82869.rs (100%) rename src/test/ui/{issues => asm}/issue-82869.stderr (100%) delete mode 100644 src/test/ui/associated-type-bounds/dyn-lcsit.rs delete mode 100644 src/test/ui/associated-type-bounds/dyn-lcsit.stderr delete mode 100644 src/test/ui/associated-type-bounds/lcsit.rs delete mode 100644 src/test/ui/associated-type-bounds/lcsit.stderr rename src/test/ui/{issues => associated-types}/issue-20005.rs (100%) rename src/test/ui/{issues => associated-types}/issue-20005.stderr (100%) create mode 100644 src/test/ui/associated-types/normalization-debruijn-1.rs create mode 100644 src/test/ui/associated-types/normalization-debruijn-2.rs create mode 100644 src/test/ui/associated-types/normalization-debruijn-3.rs create mode 100644 src/test/ui/associated-types/normalization-generality.rs create mode 100644 src/test/ui/async-await/issue-84841.rs create mode 100644 src/test/ui/async-await/issue-84841.stderr create mode 100644 src/test/ui/async-await/issue-86507.rs create mode 100644 src/test/ui/async-await/issue-86507.stderr rename src/test/ui/{ => borrowck}/fsu-moves-and-copies.rs (100%) create mode 100644 src/test/ui/borrowck/issue-83760.rs create mode 100644 src/test/ui/borrowck/issue-83760.stderr create mode 100644 src/test/ui/borrowck/issue-85581.rs create mode 100644 src/test/ui/borrowck/issue-85581.stderr create mode 100644 src/test/ui/c-variadic/issue-86053-1.rs create mode 100644 src/test/ui/c-variadic/issue-86053-1.stderr create mode 100644 src/test/ui/c-variadic/issue-86053-2.rs create mode 100644 src/test/ui/c-variadic/issue-86053-2.stderr delete mode 100644 src/test/ui/cast/cast-ptr-to-int-const.mir.stderr delete mode 100644 src/test/ui/cast/cast-ptr-to-int-const.rs delete mode 100644 src/test/ui/cast/cast-ptr-to-int-const.thir.stderr delete mode 100644 src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs delete mode 100644 src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr create mode 100644 src/test/ui/cfg/cfg-target-abi.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/issue-87097.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/issue-87097.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/old_name.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/old_name.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr delete mode 100644 src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr create mode 100644 src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs create mode 100644 src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr create mode 100644 src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs rename src/test/ui/{issues => coercion}/issue-37655.rs (100%) rename src/test/ui/{ => conditional-compilation}/test-cfg.rs (100%) rename src/test/ui/{ => conditional-compilation}/test-cfg.stderr (100%) create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs create mode 100644 src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs delete mode 100644 src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr create mode 100644 src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs create mode 100644 src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr rename src/test/ui/const-generics/{ => issues}/auxiliary/impl-const.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-61522-array-len-succ.full.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-61522-array-len-succ.min.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-61522-array-len-succ.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-66596-impl-trait-for-str-const-arg.min.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-66596-impl-trait-for-str-const-arg.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-67375.full.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67375.min.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67375.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-1.full.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-1.min.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-1.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-2.full.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-2.min.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-2.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-3.full.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-3.min.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-67945-3.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-68104-print-stack-overflow.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-70180-1-stalled_on.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-70180-2-stalled_on.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-71202.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-71986.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-73899.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-74906.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-75763.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-79518-default_trait_method_normalization.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-79518-default_trait_method_normalization.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-80561-incorrect-param-env.rs (100%) create mode 100644 src/test/ui/const-generics/issues/issue-83765.rs create mode 100644 src/test/ui/const-generics/issues/issue-83765.stderr create mode 100644 src/test/ui/const-generics/issues/issue-85848.rs create mode 100644 src/test/ui/const-generics/issues/issue-85848.stderr create mode 100644 src/test/ui/const-generics/issues/issue-86820.rs create mode 100644 src/test/ui/const-generics/issues/issue-86820.stderr create mode 100644 src/test/ui/const-generics/issues/issue-87076.rs create mode 100644 src/test/ui/const-ptr/out_of_bounds_read.rs create mode 100644 src/test/ui/const-ptr/out_of_bounds_read.stderr delete mode 100644 src/test/ui/const-ptr/ptr_to_usize_cast.rs delete mode 100644 src/test/ui/const-ptr/ptr_to_usize_cast.stderr create mode 100644 src/test/ui/consts/const-eval/const_panic_track_caller.rs create mode 100644 src/test/ui/consts/const-eval/const_panic_track_caller.stderr delete mode 100644 src/test/ui/consts/const-eval/issue-52442.rs delete mode 100644 src/test/ui/consts/const-eval/issue-52442.stderr create mode 100644 src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr create mode 100644 src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr delete mode 100644 src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr create mode 100644 src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr create mode 100644 src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr create mode 100644 src/test/ui/consts/const-mut-refs/issue-76510.rs create mode 100644 src/test/ui/consts/copy-intrinsic.rs create mode 100644 src/test/ui/consts/copy-intrinsic.stderr rename src/test/ui/{issues => consts}/issue-17756.rs (100%) create mode 100644 src/test/ui/consts/issue-39161-bogus-error.rs delete mode 100644 src/test/ui/consts/issue-51559.rs delete mode 100644 src/test/ui/consts/issue-51559.stderr delete mode 100644 src/test/ui/consts/issue-52432.rs delete mode 100644 src/test/ui/consts/issue-52432.stderr rename src/test/ui/{issues => consts}/issue-69532.rs (100%) create mode 100644 src/test/ui/consts/issue-87046.rs create mode 100644 src/test/ui/consts/issue-87046.stderr create mode 100644 src/test/ui/consts/large_const_alloc.rs create mode 100644 src/test/ui/consts/large_const_alloc.stderr create mode 100644 src/test/ui/consts/rustc-const-stability-require-const.rs create mode 100644 src/test/ui/consts/rustc-const-stability-require-const.stderr create mode 100644 src/test/ui/consts/rustc-impl-const-stability.rs create mode 100644 src/test/ui/crate-loading/auxiliary/proc-macro.rs create mode 100644 src/test/ui/crate-loading/cross-compiled-proc-macro.rs delete mode 100644 src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr delete mode 100644 src/test/ui/deduplicate-diagnostics-2.duplicate.stderr delete mode 100644 src/test/ui/deduplicate-diagnostics-2.rs create mode 100644 src/test/ui/deriving/deriving-with-helper.rs create mode 100644 src/test/ui/dyn-drop/dyn-drop.rs create mode 100644 src/test/ui/dyn-drop/dyn-drop.stderr create mode 100644 src/test/ui/extern/extern-main-issue-86110.rs create mode 100644 src/test/ui/extern/extern-main-issue-86110.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.rs create mode 100644 src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs create mode 100644 src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-abi_ptx.rs create mode 100644 src/test/ui/feature-gates/feature-gate-abi_ptx.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-cfg-target-abi.rs create mode 100644 src/test/ui/feature-gates/feature-gate-cfg-target-abi.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-fn_align.rs create mode 100644 src/test/ui/feature-gates/feature-gate-fn_align.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-vectorcall.rs create mode 100644 src/test/ui/feature-gates/feature-gate-vectorcall.stderr create mode 100644 src/test/ui/fmt/format-concat-span.rs create mode 100644 src/test/ui/fmt/format-concat-span.stderr create mode 100644 src/test/ui/fmt/issue-86085.rs create mode 100644 src/test/ui/fmt/issue-86085.stderr create mode 100644 src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs delete mode 100644 src/test/ui/generic-associated-types/gat-incomplete-warning.stderr delete mode 100644 src/test/ui/generic-associated-types/issue-68648-1.stderr delete mode 100644 src/test/ui/generic-associated-types/issue-68649-pass.stderr create mode 100644 src/test/ui/generic-associated-types/issue-76407.rs create mode 100644 src/test/ui/generic-associated-types/issue-76826.rs create mode 100644 src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs create mode 100644 src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr create mode 100644 src/test/ui/generic-associated-types/issue-81487.rs create mode 100644 src/test/ui/generic-associated-types/issue-86483.rs create mode 100644 src/test/ui/generic-associated-types/issue-86483.stderr create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions0.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions1.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions2.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions3.rs create mode 100644 src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr create mode 100644 src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs delete mode 100644 src/test/ui/impl-trait/binding-without-value.rs delete mode 100644 src/test/ui/impl-trait/binding-without-value.stderr delete mode 100644 src/test/ui/impl-trait/bindings-opaque.rs delete mode 100644 src/test/ui/impl-trait/bindings-opaque.stderr delete mode 100644 src/test/ui/impl-trait/bindings.rs delete mode 100644 src/test/ui/impl-trait/bindings.stderr delete mode 100644 src/test/ui/impl-trait/bound-normalization-pass.default.stderr delete mode 100644 src/test/ui/impl-trait/bound-normalization-pass.sa.stderr delete mode 100644 src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs delete mode 100644 src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr delete mode 100644 src/test/ui/impl-trait/impl-trait-in-bindings.rs delete mode 100644 src/test/ui/impl-trait/impl-trait-in-bindings.stderr delete mode 100644 src/test/ui/impl-trait/issue-57200.rs delete mode 100644 src/test/ui/impl-trait/issue-57200.stderr delete mode 100644 src/test/ui/impl-trait/issue-57201.rs delete mode 100644 src/test/ui/impl-trait/issue-57201.stderr delete mode 100644 src/test/ui/impl-trait/issue-60473.rs delete mode 100644 src/test/ui/impl-trait/issue-60473.stderr delete mode 100644 src/test/ui/impl-trait/issue-67166.rs delete mode 100644 src/test/ui/impl-trait/issue-67166.stderr delete mode 100644 src/test/ui/impl-trait/issue-69840.rs create mode 100644 src/test/ui/impl-trait/issue-86465.rs create mode 100644 src/test/ui/impl-trait/issue-86465.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-54600.rs create mode 100644 src/test/ui/impl-trait/issues/issue-54600.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-54840.rs create mode 100644 src/test/ui/impl-trait/issues/issue-54840.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-58504.rs create mode 100644 src/test/ui/impl-trait/issues/issue-58504.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-58956.rs create mode 100644 src/test/ui/impl-trait/issues/issue-58956.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-70971.rs create mode 100644 src/test/ui/impl-trait/issues/issue-70971.stderr delete mode 100644 src/test/ui/impl-trait/issues/issue-78721.rs delete mode 100644 src/test/ui/impl-trait/issues/issue-78721.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-79099.rs create mode 100644 src/test/ui/impl-trait/issues/issue-79099.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-84919.rs create mode 100644 src/test/ui/impl-trait/issues/issue-84919.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-86201.rs create mode 100644 src/test/ui/impl-trait/issues/issue-86201.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-86642.rs create mode 100644 src/test/ui/impl-trait/issues/issue-86642.stderr create mode 100644 src/test/ui/impl-trait/issues/issue-87295.rs create mode 100644 src/test/ui/impl-trait/issues/issue-87295.stderr delete mode 100644 src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs delete mode 100644 src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr create mode 100644 src/test/ui/inference/issue-70703.rs create mode 100644 src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs create mode 100644 src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr create mode 100644 src/test/ui/intrinsics/intrinsic-raw_eq-const.rs rename src/test/ui/{ => intrinsics}/non-integer-atomic.rs (100%) rename src/test/ui/{ => intrinsics}/non-integer-atomic.stderr (100%) create mode 100644 src/test/ui/invalid-compile-flags/codegen-option-without-group.rs create mode 100644 src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr create mode 100644 src/test/ui/invalid-compile-flags/debug-option-without-group.rs create mode 100644 src/test/ui/invalid-compile-flags/debug-option-without-group.stderr delete mode 100644 src/test/ui/issues/issue-27895.rs delete mode 100644 src/test/ui/issues/issue-27895.stderr delete mode 100644 src/test/ui/issues/issue-31109.rs delete mode 100644 src/test/ui/issues/issue-31109.stderr create mode 100644 src/test/ui/issues/issue-87199.rs create mode 100644 src/test/ui/issues/issue-87199.stderr rename src/test/ui/{issues/issue-36638.rs => keyword/keyword-self-as-type-param.rs} (85%) rename src/test/ui/{issues/issue-36638.stderr => keyword/keyword-self-as-type-param.stderr} (83%) create mode 100644 src/test/ui/lang-items/issue-86238.rs create mode 100644 src/test/ui/lang-items/issue-86238.stderr create mode 100644 src/test/ui/lint/cli-lint-override.forbid_warn.stderr create mode 100644 src/test/ui/lint/cli-lint-override.force_warn_deny.stderr create mode 100644 src/test/ui/lint/cli-lint-override.rs create mode 100644 src/test/ui/lint/cli-lint-override.warn_deny.stderr create mode 100644 src/test/ui/lint/cli-unknown-force-warn.rs create mode 100644 src/test/ui/lint/cli-unknown-force-warn.stderr create mode 100644 src/test/ui/lint/command-line-register-lint-tool.rs create mode 100644 src/test/ui/lint/command-line-register-unknown-lint-tool.rs create mode 100644 src/test/ui/lint/command-line-register-unknown-lint-tool.stderr create mode 100644 src/test/ui/lint/dead-code/self-assign.rs create mode 100644 src/test/ui/lint/dead-code/self-assign.stderr create mode 100644 src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs create mode 100644 src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr create mode 100644 src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs create mode 100644 src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr create mode 100644 src/test/ui/lint/future-incompat-test.rs create mode 100644 src/test/ui/lint/future-incompat-test.stderr delete mode 100644 src/test/ui/lint/issue-78660-cap-lints-future-compat.rs delete mode 100644 src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr create mode 100644 src/test/ui/lint/issue-86600-lint-twice.rs create mode 100644 src/test/ui/lint/issue-86600-lint-twice.stderr create mode 100644 src/test/ui/lint/issue-87274-paren-parent.rs create mode 100644 src/test/ui/lint/issue-87274-paren-parent.stderr create mode 100644 src/test/ui/lint/missing-doc-private-macro.rs create mode 100644 src/test/ui/lint/missing-doc-private-macro.stderr create mode 100644 src/test/ui/lint/unused-borrows.rs create mode 100644 src/test/ui/lint/unused-borrows.stderr create mode 100644 src/test/ui/macros/auxiliary/or-pattern.rs rename src/test/ui/{issues => macros}/issue-52169.rs (100%) create mode 100644 src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs create mode 100644 src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr rename src/test/ui/{issues => nll}/issue-24535-allow-mutable-borrow-in-match-guard.rs (100%) rename src/test/ui/{issues => nll}/issue-45157.rs (100%) rename src/test/ui/{issues => nll}/issue-45157.stderr (100%) delete mode 100644 src/test/ui/non-constant-in-const-path.rs delete mode 100644 src/test/ui/non-constant-in-const-path.stderr rename src/test/ui/{issues => packed}/issue-27060-2.rs (100%) rename src/test/ui/{issues => packed}/issue-27060-2.stderr (100%) rename src/test/ui/{issues => packed}/issue-27060-rpass.rs (100%) rename src/test/ui/{issues => packed}/issue-27060.rs (100%) rename src/test/ui/{issues => packed}/issue-27060.stderr (100%) create mode 100644 src/test/ui/panic-runtime/incompatible-type.rs create mode 100644 src/test/ui/parser/float-literals.rs rename src/test/ui/{issues => parser}/issue-48636.fixed (100%) rename src/test/ui/{issues => parser}/issue-48636.rs (100%) rename src/test/ui/{issues => parser}/issue-48636.stderr (100%) rename src/test/ui/{issues => parser}/issue-54521-1.rs (100%) rename src/test/ui/{issues => parser}/issue-54521-2.fixed (100%) rename src/test/ui/{issues => parser}/issue-54521-2.rs (100%) rename src/test/ui/{issues => parser}/issue-54521-2.stderr (100%) rename src/test/ui/{issues/issue-54521.fixed => parser/issue-54521-3.fixed} (100%) rename src/test/ui/{issues/issue-54521.rs => parser/issue-54521-3.rs} (100%) rename src/test/ui/{issues/issue-54521.stderr => parser/issue-54521-3.stderr} (86%) create mode 100644 src/test/ui/parser/issue-86895.rs create mode 100644 src/test/ui/parser/issue-86895.stderr create mode 100644 src/test/ui/parser/issue-87086-colon-path-sep.rs create mode 100644 src/test/ui/parser/issue-87086-colon-path-sep.stderr create mode 100644 src/test/ui/parser/range-inclusive-extra-equals.rs create mode 100644 src/test/ui/parser/range-inclusive-extra-equals.stderr create mode 100644 src/test/ui/parser/recover-ref-dyn-mut.rs create mode 100644 src/test/ui/parser/recover-ref-dyn-mut.stderr delete mode 100644 src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs delete mode 100644 src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr delete mode 100644 src/test/ui/pattern/issue-68396-let-float-bug.rs delete mode 100644 src/test/ui/pattern/issue-68396-let-float-bug.stderr delete mode 100644 src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs delete mode 100644 src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr create mode 100644 src/test/ui/pattern/non-constant-in-const-path.rs create mode 100644 src/test/ui/pattern/non-constant-in-const-path.stderr create mode 100644 src/test/ui/proc-macro/auxiliary/call-deprecated.rs create mode 100644 src/test/ui/proc-macro/call-deprecated.rs create mode 100644 src/test/ui/proc-macro/call-deprecated.stderr create mode 100644 src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs create mode 100644 src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr create mode 100644 src/test/ui/repr/issue-83505-repr-simd.rs create mode 100644 src/test/ui/repr/issue-83505-repr-simd.stderr create mode 100644 src/test/ui/repr/issue-83921-ice.rs create mode 100644 src/test/ui/repr/issue-83921-ice.stderr create mode 100644 src/test/ui/repr/issue-83921-pretty.normal.stderr create mode 100644 src/test/ui/repr/issue-83921-pretty.pretty.stdout create mode 100644 src/test/ui/repr/issue-83921-pretty.rs create mode 100644 src/test/ui/resolve/use_suggestion_placement.fixed create mode 100644 src/test/ui/return/issue-86188-return-not-in-fn-body.rs create mode 100644 src/test/ui/return/issue-86188-return-not-in-fn-body.stderr create mode 100644 src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr create mode 100644 src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr create mode 100644 src/test/ui/rt-explody-panic-payloads.rs create mode 100644 src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs create mode 100644 src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs create mode 100644 src/test/ui/rust-2021/future-prelude-collision-imported.fixed create mode 100644 src/test/ui/rust-2021/future-prelude-collision-imported.rs create mode 100644 src/test/ui/rust-2021/future-prelude-collision-imported.stderr create mode 100644 src/test/ui/rust-2021/future-prelude-collision-shadow.rs create mode 100644 src/test/ui/rust-2021/future-prelude-collision-shadow.stderr create mode 100644 src/test/ui/rust-2021/future-prelude-collision-unneeded.rs create mode 100644 src/test/ui/rust-2021/future-prelude-collision.fixed create mode 100644 src/test/ui/rust-2021/future-prelude-collision.rs create mode 100644 src/test/ui/rust-2021/future-prelude-collision.stderr create mode 100644 src/test/ui/rust-2021/generic-type-collision.fixed create mode 100644 src/test/ui/rust-2021/generic-type-collision.rs create mode 100644 src/test/ui/rust-2021/generic-type-collision.stderr create mode 100644 src/test/ui/rust-2021/inherent-dyn-collision.fixed create mode 100644 src/test/ui/rust-2021/inherent-dyn-collision.rs create mode 100644 src/test/ui/rust-2021/inherent-dyn-collision.stderr create mode 100644 src/test/ui/rust-2021/inherent-method-collision.rs create mode 100644 src/test/ui/rust-2021/reserved-prefixes-migration.fixed create mode 100644 src/test/ui/rust-2021/reserved-prefixes-migration.rs create mode 100644 src/test/ui/rust-2021/reserved-prefixes-migration.stderr create mode 100644 src/test/ui/rust-2021/reserved-prefixes-via-macro-2.rs create mode 100644 src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr create mode 100644 src/test/ui/rust-2021/reserved-prefixes-via-macro.rs create mode 100644 src/test/ui/rust-2021/reserved-prefixes.rs create mode 100644 src/test/ui/rust-2021/reserved-prefixes.stderr create mode 100644 src/test/ui/simd-intrinsic/issue-85855.rs create mode 100644 src/test/ui/simd-intrinsic/issue-85855.stderr create mode 100644 src/test/ui/suggestions/issue-86667.rs create mode 100644 src/test/ui/suggestions/issue-86667.stderr create mode 100644 src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs create mode 100644 src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr create mode 100644 src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs create mode 100644 src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr create mode 100644 src/test/ui/suggestions/unnamable-types.rs create mode 100644 src/test/ui/suggestions/unnamable-types.stderr create mode 100644 src/test/ui/suggestions/use-placement-resolve.fixed create mode 100644 src/test/ui/suggestions/use-placement-resolve.rs create mode 100644 src/test/ui/suggestions/use-placement-resolve.stderr create mode 100644 src/test/ui/suggestions/use-placement-typeck.fixed create mode 100644 src/test/ui/suggestions/use-placement-typeck.rs create mode 100644 src/test/ui/suggestions/use-placement-typeck.stderr rename src/test/ui/{ => test-attrs}/test-panic-abort-disabled.rs (100%) rename src/test/ui/{ => test-attrs}/test-panic-abort-disabled.stderr (100%) rename src/test/ui/{ => test-attrs}/test-panic-abort-nocapture.rs (100%) rename src/test/ui/{ => test-attrs}/test-panic-abort-nocapture.run.stderr (100%) rename src/test/ui/{ => test-attrs}/test-panic-abort-nocapture.run.stdout (100%) rename src/test/ui/{ => test-attrs}/test-panic-abort.rs (100%) rename src/test/ui/{ => test-attrs}/test-panic-abort.run.stdout (100%) rename src/test/ui/{ => test-attrs}/test-panic-while-printing.rs (100%) rename src/test/ui/{ => test-attrs}/test-passed-wasm.rs (100%) rename src/test/ui/{ => test-attrs}/test-passed-wasm.run.stdout (100%) rename src/test/ui/{ => test-attrs}/test-passed.rs (100%) rename src/test/ui/{ => test-attrs}/test-passed.run.stdout (100%) rename src/test/ui/{ => test-attrs}/test-thread-capture.rs (100%) rename src/test/ui/{ => test-attrs}/test-thread-capture.run.stdout (100%) rename src/test/ui/{ => test-attrs}/test-thread-nocapture.rs (100%) rename src/test/ui/{ => test-attrs}/test-thread-nocapture.run.stderr (100%) rename src/test/ui/{ => test-attrs}/test-thread-nocapture.run.stdout (100%) create mode 100644 src/test/ui/thir-unsafeck-issue-85871.rs create mode 100644 src/test/ui/thread-local/thread-local-issue-37508.rs create mode 100644 src/test/ui/traits/issue-78632.rs create mode 100644 src/test/ui/traits/operator-overloading-issue-52025.rs delete mode 100644 src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.rs delete mode 100644 src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-63355.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-63355.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-65384.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-65384.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-69323.full.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-69323.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-74761-2.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-74761-2.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-78450.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-78450.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs rename src/test/ui/{ => typeck}/conversion-methods.rs (100%) rename src/test/ui/{ => typeck}/conversion-methods.stderr (100%) rename src/test/ui/{issues => typeck}/issue-74086.rs (71%) rename src/test/ui/{issues => typeck}/issue-74086.stderr (89%) create mode 100644 src/test/ui/typeck/issue-75889.rs create mode 100644 src/test/ui/typeck/issue-75889.stderr rename src/test/ui/{issues => typeck}/issue-81885.rs (62%) rename src/test/ui/{issues => typeck}/issue-81885.stderr (82%) create mode 100644 src/test/ui/typeck/issue-84160.rs create mode 100644 src/test/ui/typeck/issue-84160.stderr create mode 100644 src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr create mode 100644 src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr create mode 100644 src/test/ui/typeck/issue-86721-return-expr-ice.rs create mode 100644 src/test/ui/typeck/struct-enum-wrong-args.rs create mode 100644 src/test/ui/typeck/struct-enum-wrong-args.stderr create mode 100644 src/test/ui/typeck/type-placeholder-fn-in-const.rs create mode 100644 src/test/ui/typeck/type-placeholder-fn-in-const.stderr rename src/test/ui/{ => typeck}/typeck-closure-to-unsafe-fn-ptr.rs (100%) rename src/test/ui/{ => typeck}/typeck-fn-to-unsafe-fn-ptr.rs (100%) rename src/test/ui/{ => typeck}/typeck_type_placeholder_1.rs (100%) rename src/test/ui/union/{union-borrow-move-parent-sibling.stderr => union-borrow-move-parent-sibling.mirunsafeck.stderr} (89%) create mode 100644 src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr rename src/test/ui/union/{union-deref.stderr => union-deref.mirunsafeck.stderr} (91%) create mode 100644 src/test/ui/union/union-deref.thirunsafeck.stderr rename src/test/ui/union/{union-derive-clone.stderr => union-derive-clone.mirunsafeck.stderr} (94%) create mode 100644 src/test/ui/union/union-derive-clone.thirunsafeck.stderr rename src/test/ui/union/{union-derive-eq.stderr => union-derive-eq.mirunsafeck.stderr} (83%) create mode 100644 src/test/ui/union/union-derive-eq.thirunsafeck.stderr create mode 100644 src/test/ui/union/union-drop.thirunsafeck.stderr rename src/test/ui/union/{union-fields-1.stderr => union-fields-1.mirunsafeck.stderr} (77%) create mode 100644 src/test/ui/union/union-fields-1.thirunsafeck.stderr rename src/test/ui/union/{union-fields-2.stderr => union-fields-2.mirunsafeck.stderr} (85%) create mode 100644 src/test/ui/union/union-fields-2.thirunsafeck.stderr rename src/test/ui/union/{union-generic.stderr => union-generic.mirunsafeck.stderr} (69%) create mode 100644 src/test/ui/union/union-generic.thirunsafeck.stderr rename src/test/ui/union/{union-lint-dead-code.stderr => union-lint-dead-code.mirunsafeck.stderr} (72%) create mode 100644 src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr rename src/test/ui/union/{union-move.stderr => union-move.mirunsafeck.stderr} (92%) create mode 100644 src/test/ui/union/union-move.thirunsafeck.stderr rename src/test/ui/union/{union-suggest-field.stderr => union-suggest-field.mirunsafeck.stderr} (86%) create mode 100644 src/test/ui/union/union-suggest-field.thirunsafeck.stderr rename src/test/ui/union/{union-unsafe.stderr => union-unsafe.mir.stderr} (92%) create mode 100644 src/test/ui/union/union-unsafe.thir.stderr rename src/test/ui/union/{union-unsized.stderr => union-unsized.mirunsafeck.stderr} (95%) create mode 100644 src/test/ui/union/union-unsized.thirunsafeck.stderr rename src/test/ui/union/{union-with-drop-fields.stderr => union-with-drop-fields.mirunsafeck.stderr} (74%) create mode 100644 src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr create mode 100644 src/test/ui/unpretty-expr-fn-arg.rs create mode 100644 src/test/ui/unpretty-expr-fn-arg.stdout create mode 100644 src/test/ui/unsafe/access_union_field.mir.stderr create mode 100644 src/test/ui/unsafe/access_union_field.rs create mode 100644 src/test/ui/unsafe/access_union_field.thir.stderr rename src/test/ui/unsafe/{ranged_ints2.stderr => ranged_ints2.mirunsafeck.stderr} (92%) create mode 100644 src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints2_const.stderr => ranged_ints2_const.mirunsafeck.stderr} (90%) create mode 100644 src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints3.stderr => ranged_ints3.mirunsafeck.stderr} (93%) create mode 100644 src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints3_const.stderr => ranged_ints3_const.mirunsafeck.stderr} (91%) create mode 100644 src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr create mode 100644 src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/ranged_ints3_match.rs create mode 100644 src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints4.stderr => ranged_ints4.mirunsafeck.stderr} (92%) rename src/test/ui/unsafe/{ranged_ints4_const.stderr => ranged_ints4.thirunsafeck.stderr} (90%) create mode 100644 src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr create mode 100644 src/test/ui/unsafe/union.mir.stderr create mode 100644 src/test/ui/unsafe/union.rs create mode 100644 src/test/ui/unsafe/union_access_through_block.rs create mode 100644 src/test/ui/unsafe/union_destructure.mir.stderr create mode 100644 src/test/ui/unsafe/union_destructure.rs create mode 100644 src/test/ui/unsafe/union_wild_or_wild.rs create mode 100644 src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/unsafe-assign.rs create mode 100644 src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr create mode 100644 src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/unsafe-borrow.rs create mode 100644 src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr create mode 100644 src/test/ui/unused/unused-doc-comments-edge-cases.rs create mode 100644 src/test/ui/unused/unused-doc-comments-edge-cases.stderr create mode 100644 src/test/ui/wf/hir-wf-check-erase-regions.rs create mode 100644 src/test/ui/wf/hir-wf-check-erase-regions.stderr create mode 100644 src/test/ui/wf/wf-complex-assoc-type.rs create mode 100644 src/test/ui/wf/wf-complex-assoc-type.stderr delete mode 100644 src/tools/clippy/clippy_dev/src/ide_setup.rs create mode 100644 src/tools/clippy/clippy_dev/src/setup/git_hook.rs create mode 100644 src/tools/clippy/clippy_dev/src/setup/intellij.rs create mode 100644 src/tools/clippy/clippy_dev/src/setup/mod.rs create mode 100644 src/tools/clippy/clippy_dev/src/setup/vscode.rs create mode 100644 src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs create mode 100644 src/tools/clippy/clippy_lints/src/disallowed_type.rs delete mode 100644 src/tools/clippy/clippy_lints/src/map_identity.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/map_identity.rs create mode 100644 src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs create mode 100644 src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs create mode 100644 src/tools/clippy/clippy_lints/src/self_named_constructors.rs create mode 100644 src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs create mode 100644 src/tools/clippy/clippy_lints/src/types/rc_mutex.rs create mode 100644 src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs create mode 100644 src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr create mode 100644 src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs create mode 100644 src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs create mode 100644 src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr create mode 100644 src/tools/clippy/tests/ui-toml/toml_disallowed_type/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs create mode 100644 src/tools/clippy/tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr create mode 100644 src/tools/clippy/tests/ui/auxiliary/non-exhaustive-enum.rs create mode 100644 src/tools/clippy/tests/ui/branches_sharing_code/false_positives.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7340.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7410.rs create mode 100644 src/tools/clippy/tests/ui/crashes/ice-7423.rs create mode 100644 src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed create mode 100644 src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs create mode 100644 src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr create mode 100644 src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed rename src/tools/clippy/tests/ui/{default_numeric_fallback.rs => default_numeric_fallback_i32.rs} (82%) rename src/tools/clippy/tests/ui/{default_numeric_fallback.stderr => default_numeric_fallback_i32.stderr} (67%) create mode 100644 src/tools/clippy/tests/ui/disallowed_script_idents.rs create mode 100644 src/tools/clippy/tests/ui/disallowed_script_idents.stderr rename src/tools/clippy/tests/ui/{ => doc}/doc.rs (99%) rename src/tools/clippy/tests/ui/{ => doc}/doc.stderr (100%) create mode 100644 src/tools/clippy/tests/ui/doc/unbalanced_ticks.rs create mode 100644 src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr create mode 100644 src/tools/clippy/tests/ui/extend_with_drain.fixed create mode 100644 src/tools/clippy/tests/ui/extend_with_drain.rs create mode 100644 src/tools/clippy/tests/ui/extend_with_drain.stderr create mode 100644 src/tools/clippy/tests/ui/issue-7447.rs create mode 100644 src/tools/clippy/tests/ui/rc_mutex.rs create mode 100644 src/tools/clippy/tests/ui/rc_mutex.stderr delete mode 100644 src/tools/clippy/tests/ui/redundant_allocation.fixed create mode 100644 src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed create mode 100644 src/tools/clippy/tests/ui/redundant_allocation_fixable.rs create mode 100644 src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr create mode 100644 src/tools/clippy/tests/ui/self_named_constructors.rs create mode 100644 src/tools/clippy/tests/ui/self_named_constructors.stderr create mode 100644 src/tools/clippy/tests/ui/strlen_on_c_strings.rs create mode 100644 src/tools/clippy/tests/ui/strlen_on_c_strings.stderr create mode 100755 src/tools/clippy/util/etc/pre-commit.sh create mode 100644 src/tools/clippy/util/etc/vscode-tasks.json create mode 100644 src/tools/html-checker/Cargo.toml create mode 100644 src/tools/html-checker/main.rs create mode 100644 src/tools/tidy/src/target_specific_tests.rs create mode 100644 vendor/byteorder/build.rs delete mode 100644 vendor/cargo_metadata-0.11.1/.cargo-checksum.json delete mode 100644 vendor/cargo_metadata-0.11.1/Cargo.toml delete mode 100644 vendor/cargo_metadata-0.11.1/LICENSE-MIT delete mode 100644 vendor/cargo_metadata-0.11.1/README.md delete mode 100644 vendor/cargo_metadata-0.11.1/src/dependency.rs delete mode 100644 vendor/cargo_metadata-0.11.1/src/diagnostic.rs delete mode 100644 vendor/cargo_metadata-0.11.1/src/errors.rs delete mode 100644 vendor/cargo_metadata-0.11.1/src/lib.rs delete mode 100644 vendor/cargo_metadata-0.11.1/src/messages.rs delete mode 100644 vendor/cargo_metadata-0.11.1/tests/selftest.rs delete mode 100644 vendor/cargo_metadata-0.11.1/tests/test_samples.rs create mode 100644 vendor/globwalk/.cargo-checksum.json create mode 100644 vendor/globwalk/Cargo.lock create mode 100644 vendor/globwalk/Cargo.toml create mode 100644 vendor/globwalk/LICENSE create mode 100644 vendor/globwalk/README.md create mode 100644 vendor/globwalk/appveyor.yml create mode 100644 vendor/globwalk/examples/list.rs create mode 100644 vendor/globwalk/src/doctests.rs create mode 100644 vendor/globwalk/src/lib.rs create mode 100644 vendor/globwalk/tests/docs.rs delete mode 100644 vendor/hashbrown-0.9.1/.cargo-checksum.json delete mode 100644 vendor/hashbrown-0.9.1/CHANGELOG.md delete mode 100644 vendor/hashbrown-0.9.1/Cargo.toml delete mode 100644 vendor/hashbrown-0.9.1/LICENSE-MIT delete mode 100644 vendor/hashbrown-0.9.1/README.md delete mode 100644 vendor/hashbrown-0.9.1/benches/bench.rs delete mode 100644 vendor/hashbrown-0.9.1/clippy.toml delete mode 100644 vendor/hashbrown-0.9.1/src/external_trait_impls/mod.rs delete mode 100644 vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/helpers.rs delete mode 100644 vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/map.rs delete mode 100644 vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/mod.rs delete mode 100644 vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/raw.rs delete mode 100644 vendor/hashbrown-0.9.1/src/external_trait_impls/rayon/set.rs delete mode 100644 vendor/hashbrown-0.9.1/src/external_trait_impls/serde.rs delete mode 100644 vendor/hashbrown-0.9.1/src/lib.rs delete mode 100644 vendor/hashbrown-0.9.1/src/macros.rs delete mode 100644 vendor/hashbrown-0.9.1/src/map.rs delete mode 100644 vendor/hashbrown-0.9.1/src/raw/bitmask.rs delete mode 100644 vendor/hashbrown-0.9.1/src/raw/generic.rs delete mode 100644 vendor/hashbrown-0.9.1/src/raw/mod.rs delete mode 100644 vendor/hashbrown-0.9.1/src/raw/sse2.rs delete mode 100644 vendor/hashbrown-0.9.1/src/rustc_entry.rs delete mode 100644 vendor/hashbrown-0.9.1/src/scopeguard.rs delete mode 100644 vendor/hashbrown-0.9.1/src/set.rs delete mode 100644 vendor/hashbrown-0.9.1/tests/hasher.rs delete mode 100644 vendor/hashbrown-0.9.1/tests/rayon.rs delete mode 100644 vendor/hashbrown-0.9.1/tests/serde.rs delete mode 100644 vendor/hashbrown-0.9.1/tests/set.rs delete mode 100644 vendor/heck/no_step_on_snek.png create mode 100644 vendor/libc/src/unix/bsd/freebsdlike/freebsd/powerpc.rs create mode 100755 vendor/memchr/scripts/make-byte-frequency-table create mode 100644 vendor/memmap2-0.2.1/.cargo-checksum.json rename vendor/{memmap2 => memmap2-0.2.1}/CHANGELOG.md (55%) rename vendor/{memmap2 => memmap2-0.2.1}/Cargo.lock (88%) rename vendor/{memmap2 => memmap2-0.2.1}/Cargo.toml (98%) rename vendor/{memmap2 => memmap2-0.2.1}/LICENSE-APACHE (100%) rename vendor/{memmap2 => memmap2-0.2.1}/LICENSE-MIT (100%) rename vendor/{memmap2 => memmap2-0.2.1}/README.md (100%) rename vendor/{memmap2 => memmap2-0.2.1}/examples/cat.rs (100%) rename vendor/{memmap2 => memmap2-0.2.1}/src/lib.rs (91%) rename vendor/{memmap2 => memmap2-0.2.1}/src/unix.rs (76%) rename vendor/{memmap2 => memmap2-0.2.1}/src/windows.rs (88%) delete mode 100644 vendor/memmap2/.cargo-checksum.json delete mode 100644 vendor/memmap2/src/stub.rs delete mode 100644 vendor/num-traits/src/ops/overflowing.rs create mode 100644 vendor/object/src/read/elf/hash.rs create mode 100644 vendor/object/src/read/elf/version.rs create mode 100755 vendor/opener/Drakefile.ts mode change 100644 => 100755 vendor/opener/LICENSE-APACHE mode change 100644 => 100755 vendor/opener/LICENSE-MIT mode change 100644 => 100755 vendor/opener/LICENSE-THIRD-PARTY delete mode 100644 vendor/opener/Makefile.toml delete mode 100644 vendor/opener/release.toml create mode 100644 vendor/opener/src/linux_and_more.rs create mode 100644 vendor/opener/src/macos.rs create mode 100644 vendor/opener/src/windows.rs mode change 100644 => 100755 vendor/opener/src/xdg-open create mode 100644 vendor/opener/tests/version-numbers.rs create mode 100644 vendor/pin-project-lite/tests/expand/pinned_drop/enum.expanded.rs create mode 100644 vendor/pin-project-lite/tests/expand/pinned_drop/enum.rs create mode 100644 vendor/pin-project-lite/tests/expand/pinned_drop/struct.expanded.rs create mode 100644 vendor/pin-project-lite/tests/expand/pinned_drop/struct.rs create mode 100644 vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.rs create mode 100644 vendor/pin-project-lite/tests/ui/pinned_drop/call-drop-inner.stderr create mode 100644 vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.rs create mode 100644 vendor/pin-project-lite/tests/ui/pinned_drop/conditional-drop-impl.stderr delete mode 100644 vendor/regex-1.4.3/.cargo-checksum.json delete mode 100644 vendor/regex-1.4.3/Cargo.lock delete mode 100644 vendor/regex-1.4.3/LICENSE-APACHE delete mode 100644 vendor/regex-1.4.3/rustfmt.toml delete mode 100644 vendor/regex-1.4.3/src/cache.rs create mode 100644 vendor/regex-1.4.6/.cargo-checksum.json rename vendor/{regex-1.4.3 => regex-1.4.6}/CHANGELOG.md (95%) create mode 100644 vendor/regex-1.4.6/Cargo.lock rename vendor/{regex-1.4.3 => regex-1.4.6}/Cargo.toml (95%) rename vendor/{regex-1.4.3 => regex-1.4.6}/HACKING.md (100%) rename vendor/{hashbrown-0.9.1 => regex-1.4.6}/LICENSE-APACHE (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/LICENSE-MIT (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/PERFORMANCE.md (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/README.md (98%) rename vendor/{regex-1.4.3 => regex-1.4.6}/UNICODE.md (87%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/regexdna-input.txt (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/regexdna-output.txt (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/shootout-regex-dna-bytes.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/shootout-regex-dna-cheat.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/shootout-regex-dna-replace.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/shootout-regex-dna-single-cheat.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/shootout-regex-dna-single.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/examples/shootout-regex-dna.rs (100%) rename vendor/{byteorder => regex-1.4.6}/rustfmt.toml (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/backtrack.rs (98%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/compile.rs (98%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/dfa.rs (99%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/error.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/exec.rs (97%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/expand.rs (98%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/find_byte.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/freqs.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/input.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/lib.rs (98%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/literal/imp.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/literal/mod.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/pattern.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/pikevm.rs (100%) create mode 100644 vendor/regex-1.4.6/src/pool.rs rename vendor/{regex-1.4.3 => regex-1.4.6}/src/prog.rs (97%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/re_builder.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/re_bytes.rs (96%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/re_set.rs (99%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/re_trait.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/re_unicode.rs (96%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/sparse.rs (96%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/testdata/LICENSE (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/testdata/README (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/testdata/basic.dat (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/testdata/nullsubexpr.dat (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/testdata/repetition.dat (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/src/utf8.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/test (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/api.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/api_str.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/bytes.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/consistent.rs (98%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/crates_regex.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/crazy.rs (98%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/flags.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/fowler.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/macros.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/macros_bytes.rs (99%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/macros_str.rs (93%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/misc.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/multiline.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/noparse.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/regression.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/regression_fuzz.rs (58%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/replace.rs (60%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/searcher.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/set.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/shortest_match.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/suffix_reverse.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_backtrack.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_backtrack_bytes.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_backtrack_utf8bytes.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_crates_regex.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_default.rs (64%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_default_bytes.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_nfa.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_nfa_bytes.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/test_nfa_utf8bytes.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/unicode.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/word_boundary.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/word_boundary_ascii.rs (100%) rename vendor/{regex-1.4.3 => regex-1.4.6}/tests/word_boundary_unicode.rs (100%) create mode 100644 vendor/regex-automata/src/byteorder.rs create mode 100644 vendor/rustfix-0.5.1/.cargo-checksum.json create mode 100644 vendor/rustfix-0.5.1/Cargo.toml create mode 100644 vendor/rustfix-0.5.1/Changelog.md create mode 100644 vendor/rustfix-0.5.1/LICENSE-APACHE create mode 100644 vendor/rustfix-0.5.1/LICENSE-MIT create mode 100644 vendor/rustfix-0.5.1/Readme.md create mode 100644 vendor/rustfix-0.5.1/proptest-regressions/replace.txt create mode 100644 vendor/rustfix-0.5.1/src/diagnostics.rs create mode 100644 vendor/rustfix-0.5.1/src/lib.rs create mode 100644 vendor/rustfix-0.5.1/src/replace.rs delete mode 100644 vendor/semver-0.10.0/.cargo-checksum.json delete mode 100644 vendor/semver-0.10.0/Cargo.toml delete mode 100644 vendor/semver-0.10.0/LICENSE-APACHE delete mode 100644 vendor/semver-0.10.0/LICENSE-MIT delete mode 100644 vendor/semver-0.10.0/README.md delete mode 100644 vendor/semver-0.10.0/src/diesel_impls.rs delete mode 100644 vendor/semver-0.10.0/src/lib.rs delete mode 100644 vendor/semver-0.10.0/src/version.rs delete mode 100644 vendor/semver-0.10.0/src/version_req.rs delete mode 100644 vendor/semver-0.10.0/tests/deprecation.rs delete mode 100644 vendor/semver-0.10.0/tests/diesel.rs delete mode 100644 vendor/semver-0.10.0/tests/serde.rs delete mode 100644 vendor/semver-parser-0.7.0/.cargo-checksum.json delete mode 100644 vendor/semver-parser-0.7.0/Cargo.toml delete mode 100644 vendor/semver-parser-0.7.0/LICENSE-APACHE delete mode 100644 vendor/semver-parser-0.7.0/LICENSE-MIT delete mode 100644 vendor/semver-parser-0.7.0/src/common.rs delete mode 100644 vendor/semver-parser-0.7.0/src/lib.rs delete mode 100644 vendor/semver-parser-0.7.0/src/range.rs delete mode 100644 vendor/semver-parser-0.7.0/src/recognize.rs delete mode 100644 vendor/semver-parser-0.7.0/src/version.rs create mode 100644 vendor/tera/.cargo-checksum.json create mode 100644 vendor/tera/CHANGELOG.md create mode 100644 vendor/tera/Cargo.toml create mode 100644 vendor/tera/LICENSE create mode 100644 vendor/tera/README.md create mode 100644 vendor/tera/docs/README.md create mode 100644 vendor/tera/src/builtins/filters/array.rs create mode 100644 vendor/tera/src/builtins/filters/common.rs create mode 100644 vendor/tera/src/builtins/filters/mod.rs create mode 100644 vendor/tera/src/builtins/filters/number.rs create mode 100644 vendor/tera/src/builtins/filters/object.rs create mode 100644 vendor/tera/src/builtins/filters/string.rs create mode 100644 vendor/tera/src/builtins/functions.rs create mode 100644 vendor/tera/src/builtins/mod.rs create mode 100644 vendor/tera/src/builtins/testers.rs create mode 100644 vendor/tera/src/context.rs create mode 100644 vendor/tera/src/errors.rs create mode 100644 vendor/tera/src/filter_utils.rs create mode 100644 vendor/tera/src/lib.rs create mode 100644 vendor/tera/src/macros.rs create mode 100644 vendor/tera/src/parser/ast.rs create mode 100644 vendor/tera/src/parser/mod.rs create mode 100644 vendor/tera/src/parser/tera.pest create mode 100644 vendor/tera/src/parser/tests/errors.rs create mode 100644 vendor/tera/src/parser/tests/lexer.rs create mode 100644 vendor/tera/src/parser/tests/mod.rs create mode 100644 vendor/tera/src/parser/tests/parser.rs create mode 100644 vendor/tera/src/parser/tests/whitespace.rs create mode 100644 vendor/tera/src/parser/whitespace.rs create mode 100644 vendor/tera/src/renderer/call_stack.rs create mode 100644 vendor/tera/src/renderer/for_loop.rs create mode 100644 vendor/tera/src/renderer/macros.rs create mode 100644 vendor/tera/src/renderer/mod.rs create mode 100644 vendor/tera/src/renderer/processor.rs create mode 100644 vendor/tera/src/renderer/square_brackets.rs create mode 100644 vendor/tera/src/renderer/stack_frame.rs create mode 100644 vendor/tera/src/renderer/tests/basic.rs create mode 100644 vendor/tera/src/renderer/tests/errors.rs create mode 100644 vendor/tera/src/renderer/tests/inheritance.rs create mode 100644 vendor/tera/src/renderer/tests/macros.rs create mode 100644 vendor/tera/src/renderer/tests/mod.rs create mode 100644 vendor/tera/src/renderer/tests/square_brackets.rs create mode 100644 vendor/tera/src/renderer/tests/whitespace.rs create mode 100644 vendor/tera/src/template.rs create mode 100644 vendor/tera/src/tera.rs create mode 100644 vendor/tera/src/utils.rs create mode 100644 vendor/unicode-segmentation/benches/unicode_words.rs create mode 100644 vendor/unicode-segmentation/benches/word_bounds.rs diff --git a/Cargo.lock b/Cargo.lock index de110c55a4..085aae3d0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,7 +73,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -82,7 +82,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -111,7 +111,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -179,13 +179,14 @@ dependencies = [ "libc", "merge", "num_cpus", + "once_cell", "opener", "pretty_assertions", "serde", "serde_json", "time", "toml", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -194,7 +195,9 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" dependencies = [ + "lazy_static", "memchr", + "regex-automata", ] [[package]] @@ -240,9 +243,9 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "bytes" -version = "0.5.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" [[package]] name = "bytesize" @@ -252,7 +255,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" [[package]] name = "cargo" -version = "0.55.0" +version = "0.56.0" dependencies = [ "anyhow", "atty", @@ -266,7 +269,7 @@ dependencies = [ "crossbeam-utils 0.8.3", "curl", "curl-sys", - "env_logger 0.8.1", + "env_logger 0.9.0", "filetime", "flate2", "fwdansi", @@ -291,9 +294,8 @@ dependencies = [ "openssl", "percent-encoding 2.1.0", "pretty_env_logger", - "rand 0.8.3", "rustc-workspace-hack", - "rustfix", + "rustfix 0.6.0", "semver 1.0.3", "serde", "serde_ignored", @@ -308,7 +310,7 @@ dependencies = [ "unicode-xid", "url 2.2.2", "walkdir", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -337,7 +339,7 @@ name = "cargo-credential-wincred" version = "0.1.0" dependencies = [ "cargo-credential", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -374,17 +376,19 @@ dependencies = [ "flate2", "git2", "glob", + "itertools 0.10.0", "lazy_static", "remove_dir_all", "serde_json", "tar", + "termcolor", "toml", "url 2.2.2", ] [[package]] name = "cargo-util" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "core-foundation", @@ -394,12 +398,12 @@ dependencies = [ "jobserver", "libc", "log", - "miow 0.3.6", + "miow", "same-file", "shell-escape", "tempfile", "walkdir", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -414,17 +418,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "cargo_metadata" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89fec17b16f1ac67908af82e47d0a90a7afd0e1827b181cd77504323d3263d35" -dependencies = [ - "semver 0.10.0", - "serde", - "serde_json", -] - [[package]] name = "cargo_metadata" version = "0.12.0" @@ -442,9 +435,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" +checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" dependencies = [ "jobserver", ] @@ -528,7 +521,7 @@ dependencies = [ "num-integer", "num-traits", "time", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -549,7 +542,7 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.54" +version = "0.1.55" dependencies = [ "cargo_metadata 0.12.0", "clippy_lints", @@ -582,7 +575,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.54" +version = "0.1.55" dependencies = [ "cargo_metadata 0.12.0", "clippy_utils", @@ -597,12 +590,13 @@ dependencies = [ "serde_json", "toml", "unicode-normalization", + "unicode-script", "url 2.2.2", ] [[package]] name = "clippy_utils" -version = "0.1.54" +version = "0.1.55" dependencies = [ "if_chain", "itertools 0.9.0", @@ -629,7 +623,7 @@ checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" dependencies = [ "atty", "lazy_static", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -652,9 +646,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.45" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "787187ae221adfcda34b03006f1617099e4ae26b50e5a4db282496014ab75837" +checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2" dependencies = [ "cc", "rustc-std-workspace-core", @@ -670,16 +664,16 @@ dependencies = [ "glob", "lazy_static", "libc", - "miow 0.3.6", + "miow", "regex", - "rustfix", + "rustfix 0.6.0", "serde", "serde_json", "tracing", "tracing-subscriber", "unified-diff", "walkdir", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -694,15 +688,15 @@ dependencies = [ "lazy_static", "libc", "log", - "miow 0.3.6", + "miow", "regex", - "rustfix", + "rustfix 0.5.1", "serde", "serde_derive", "serde_json", "tempfile", "tester", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -837,7 +831,7 @@ dependencies = [ "commoncrypto", "hex 0.3.2", "openssl", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -862,24 +856,24 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.36" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bac9f84ca0977c4d9b8db998689de55b9e976656a6bc87fada2ca710d504c7" +checksum = "003cb79c1c6d1c93344c7e1201bb51c2148f24ec2bd9c253709d6b2efb796515" dependencies = [ "curl-sys", "libc", "openssl-probe", "openssl-sys", "schannel", - "socket2 0.4.0", - "winapi 0.3.9", + "socket2", + "winapi", ] [[package]] name = "curl-sys" -version = "0.4.42+curl-7.76.0" +version = "0.4.45+curl-7.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4636d8d6109c842707018a104051436bffb8991ea20b2d1293db70b6e0ee4c7c" +checksum = "de9e5a72b1c744eb5dd20b2be4d7eb84625070bb5c4ab9b347b70464ab1e62eb" dependencies = [ "cc", "libc", @@ -888,7 +882,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -986,7 +980,7 @@ checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -997,7 +991,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1100,6 +1094,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime 2.0.1", + "log", + "regex", + "termcolor", +] + [[package]] name = "error_index_generator" version = "0.0.0" @@ -1141,7 +1148,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1222,22 +1229,6 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d79238883cf0307100b90aba4a755d8051a3182305dfe7f649a1e9dc0517006f" -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "futf" version = "0.1.4" @@ -1344,7 +1335,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.4", + "pin-project-lite", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1482,6 +1473,17 @@ dependencies = [ "regex", ] +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + [[package]] name = "gsgdt" version = "0.1.2" @@ -1505,12 +1507,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" - [[package]] name = "hashbrown" version = "0.11.0" @@ -1560,7 +1556,14 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654" dependencies = [ - "winapi 0.3.9", + "winapi", +] + +[[package]] +name = "html-checker" +version = "0.1.0" +dependencies = [ + "walkdir", ] [[package]] @@ -1654,12 +1657,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", - "hashbrown 0.9.1", + "hashbrown", ] [[package]] @@ -1675,7 +1678,7 @@ dependencies = [ "remove_dir_all", "tar", "walkdir", - "winapi 0.3.9", + "winapi", "xz2", ] @@ -1685,15 +1688,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - [[package]] name = "itertools" version = "0.8.2" @@ -1770,9 +1764,9 @@ dependencies = [ [[package]] name = "jsonrpc-client-transports" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b6c6ad01c7354d60de493148c30ac8a82b759e22ae678c8705e9b8e0c566a4" +checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", "futures 0.3.12", @@ -1789,11 +1783,13 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07569945133257ff557eb37b015497104cea61a2c9edaf126c1cbd6e8332397f" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ "futures 0.3.12", + "futures-executor", + "futures-util", "log", "serde", "serde_derive", @@ -1802,9 +1798,9 @@ dependencies = [ [[package]] name = "jsonrpc-core-client" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac9d56dc729912796637c30f475bbf834594607b27740dfea6e5fa7ba40d1f1" +checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ "futures 0.3.12", "jsonrpc-client-transports", @@ -1812,9 +1808,9 @@ dependencies = [ [[package]] name = "jsonrpc-derive" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b68ba7e76e5c7796cfa4d2a30e83986550c34404c6d40551c902ca6f7bd4a137" +checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1824,9 +1820,9 @@ dependencies = [ [[package]] name = "jsonrpc-ipc-server" -version = "17.0.1" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c4cd89e5ea7e7f0884e828fc35bb83591a371b92439675eae28efa66c24a97" +checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ "futures 0.3.12", "jsonrpc-core", @@ -1839,9 +1835,9 @@ dependencies = [ [[package]] name = "jsonrpc-pubsub" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c48dbebce7a9c88ab272a4db7d6478aa4c6d9596e6c086366e89efc4e9ed89e" +checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ "futures 0.3.12", "jsonrpc-core", @@ -1854,9 +1850,9 @@ dependencies = [ [[package]] name = "jsonrpc-server-utils" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4207cce738bf713a82525065b750a008f28351324f438f56b33d698ada95bb4" +checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", "futures 0.3.12", @@ -1865,20 +1861,11 @@ dependencies = [ "lazy_static", "log", "tokio", + "tokio-stream", "tokio-util", "unicase", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -1999,9 +1986,9 @@ dependencies = [ [[package]] name = "lsp-codec" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d33c83e320715a1e7e0466a53db2238becb2e5c446deff5506abc81aeacc5ec4" +checksum = "aa939d0b62476a5a19fb7fcb423a5c6ce8c7e09b851d37531e2fe3e0e6d9d257" dependencies = [ "bytes", "serde_json", @@ -2154,9 +2141,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" @@ -2221,66 +2208,24 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.22" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", "libc", "log", - "miow 0.2.2", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-named-pipes" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" -dependencies = [ - "log", - "mio", - "miow 0.3.6", - "winapi 0.3.9", -] - -[[package]] -name = "mio-uds" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -dependencies = [ - "iovec", - "libc", - "mio", + "miow", + "ntapi", + "winapi", ] [[package]] name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "miow" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "socket2 0.3.19", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2302,23 +2247,21 @@ dependencies = [ "smallvec", ] -[[package]] -name = "net2" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "new_debug_unreachable" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + [[package]] name = "num-integer" version = "0.1.43" @@ -2361,9 +2304,9 @@ dependencies = [ [[package]] name = "object" -version = "0.25.2" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bc1d42047cf336f0f939c99e97183cf31551bf0f2865a2ec9c8d91fd4ffb5e" +checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" dependencies = [ "crc32fast", "indexmap", @@ -2394,23 +2337,24 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] name = "opener" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae" +checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952" dependencies = [ - "winapi 0.3.9", + "bstr", + "winapi", ] [[package]] name = "openssl" -version = "0.10.33" +version = "0.10.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577" +checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -2437,9 +2381,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.61" +version = "0.9.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f" +checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d" dependencies = [ "autocfg", "cc", @@ -2461,7 +2405,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2499,18 +2443,16 @@ dependencies = [ [[package]] name = "parity-tokio-ipc" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7f6c69d7687501b2205fe51ade1d7b8797bb3aa141fe5bf13dd78c0483bc89" +checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ "futures 0.3.12", "libc", "log", - "mio-named-pipes", - "miow 0.3.6", "rand 0.7.3", "tokio", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2535,7 +2477,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2656,12 +2598,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project-lite" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" - [[package]] name = "pin-project-lite" version = "0.2.4" @@ -3038,31 +2974,29 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.3" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-automata" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "byteorder", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.22" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "remote-test-client" @@ -3078,7 +3012,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3123,6 +3057,7 @@ dependencies = [ "serde_json", "tempfile", "tokio", + "tokio-stream", "tokio-util", "toml", "url 2.2.2", @@ -3286,7 +3221,7 @@ dependencies = [ "stacker", "tempfile", "tracing", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3306,7 +3241,7 @@ dependencies = [ "termize", "tracing", "unicode-width", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3546,6 +3481,7 @@ dependencies = [ name = "rustc-workspace-hack" version = "1.0.0" dependencies = [ + "bstr", "byteorder", "crossbeam-utils 0.8.3", "libc", @@ -3558,7 +3494,7 @@ dependencies = [ "smallvec", "syn", "url 2.2.2", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3687,10 +3623,8 @@ dependencies = [ "rustc_codegen_ssa", "rustc_data_structures", "rustc_errors", - "rustc_feature", "rustc_fs_util", "rustc_hir", - "rustc_incremental", "rustc_index", "rustc_llvm", "rustc_metadata", @@ -3713,7 +3647,7 @@ dependencies = [ "itertools 0.9.0", "jobserver", "libc", - "object 0.25.2", + "object 0.26.2", "pathdiff", "rustc_apfloat", "rustc_ast", @@ -3731,6 +3665,7 @@ dependencies = [ "rustc_span", "rustc_symbol_mangling", "rustc_target", + "smallvec", "tempfile", "tracing", ] @@ -3742,7 +3677,6 @@ dependencies = [ "arrayvec", "bitflags", "cfg-if 0.1.10", - "crossbeam-utils 0.8.3", "ena", "indexmap", "jobserver", @@ -3762,7 +3696,7 @@ dependencies = [ "stacker", "tempfile", "tracing", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3785,7 +3719,6 @@ dependencies = [ "rustc_metadata", "rustc_middle", "rustc_mir", - "rustc_mir_build", "rustc_parse", "rustc_plugin_impl", "rustc_save_analysis", @@ -3793,11 +3726,10 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_typeck", "tracing", "tracing-subscriber", "tracing-tree", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3819,7 +3751,7 @@ dependencies = [ "termize", "tracing", "unicode-width", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3919,10 +3851,8 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ - "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_graphviz", "rustc_hir", "rustc_index", "rustc_macros", @@ -3954,7 +3884,6 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_incremental", - "rustc_index", "rustc_lint", "rustc_metadata", "rustc_middle", @@ -3978,7 +3907,7 @@ dependencies = [ "smallvec", "tempfile", "tracing", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4022,7 +3951,6 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", - "tracing", ] [[package]] @@ -4066,9 +3994,8 @@ dependencies = [ "rustc_target", "smallvec", "snap", - "stable_deref_trait", "tracing", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4077,7 +4004,6 @@ version = "0.0.0" dependencies = [ "bitflags", "chalk-ir", - "measureme", "polonius-engine", "rustc-rayon-core", "rustc_apfloat", @@ -4167,7 +4093,6 @@ dependencies = [ "rustc_lexer", "rustc_session", "rustc_span", - "smallvec", "tracing", "unicode-normalization", ] @@ -4197,7 +4122,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_trait_selection", "tracing", ] @@ -4238,10 +4162,8 @@ dependencies = [ "measureme", "rustc-rayon-core", "rustc_ast", - "rustc_attr", "rustc_data_structures", "rustc_errors", - "rustc_feature", "rustc_hir", "rustc_index", "rustc_macros", @@ -4250,7 +4172,6 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "rustc_target", "tracing", ] @@ -4328,7 +4249,6 @@ dependencies = [ name = "rustc_session" version = "0.0.0" dependencies = [ - "bitflags", "getopts", "num_cpus", "rustc_ast", @@ -4368,7 +4288,6 @@ version = "0.0.0" dependencies = [ "punycode", "rustc-demangle", - "rustc_ast", "rustc_data_structures", "rustc_hir", "rustc_middle", @@ -4518,6 +4437,7 @@ dependencies = [ "serde_json", "smallvec", "tempfile", + "tera", "tracing", "tracing-subscriber", "tracing-tree", @@ -4554,6 +4474,18 @@ dependencies = [ "serde_json", ] +[[package]] +name = "rustfix" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0be05fc0675ef4f47119dc39cfc46636bb77d4fc4ef1bd851b9c3f7697f32a" +dependencies = [ + "anyhow", + "log", + "serde", + "serde_json", +] + [[package]] name = "rustfmt-config_proc_macro" version = "0.2.0" @@ -4597,9 +4529,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" +checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" [[package]] name = "ryu" @@ -4623,7 +4555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4671,16 +4603,6 @@ dependencies = [ "serde", ] -[[package]] -name = "semver" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "394cec28fa623e00903caf7ba4fa6fb9a0e260280bb8cdbbba029611108a0190" -dependencies = [ - "semver-parser 0.7.0", - "serde", -] - [[package]] name = "semver" version = "0.11.0" @@ -4869,17 +4791,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" -[[package]] -name = "socket2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi 0.3.9", -] - [[package]] name = "socket2" version = "0.4.0" @@ -4887,7 +4798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4906,7 +4817,7 @@ dependencies = [ "cfg-if 0.1.10", "libc", "psm", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4920,7 +4831,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.11.0", + "hashbrown", "hermit-abi", "libc", "miniz_oxide", @@ -5073,7 +4984,7 @@ dependencies = [ "rand 0.8.3", "redox_syscall", "remove_dir_all", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5088,11 +4999,18 @@ dependencies = [ ] [[package]] -name = "term" -version = "0.0.0" +name = "tera" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62" dependencies = [ - "core", - "std", + "globwalk", + "lazy_static", + "pest", + "pest_derive", + "regex", + "serde", + "serde_json", ] [[package]] @@ -5102,7 +5020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" dependencies = [ "dirs", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5113,14 +5031,14 @@ checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ "dirs-next", "rustversion", - "winapi 0.3.9", + "winapi", ] [[package]] name = "termcolor" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" dependencies = [ "winapi-util", ] @@ -5132,7 +5050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5147,7 +5065,6 @@ dependencies = [ "panic_unwind", "proc_macro", "std", - "term 0.0.0", ] [[package]] @@ -5205,7 +5122,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "cargo_metadata 0.11.1", + "cargo_metadata 0.12.0", "crossbeam-utils 0.8.3", "lazy_static", "regex", @@ -5244,7 +5161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5255,49 +5172,44 @@ checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" [[package]] name = "tokio" -version = "0.2.24" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48" +checksum = "c2602b8af3767c285202012822834005f596c811042315fa7e9f5b12b2a43207" dependencies = [ + "autocfg", "bytes", - "futures-core", - "iovec", - "lazy_static", "libc", "memchr", "mio", - "mio-named-pipes", - "mio-uds", "num_cpus", - "pin-project-lite 0.1.11", + "once_cell", + "pin-project-lite", "signal-hook-registry", - "slab", - "tokio-macros", - "winapi 0.3.9", + "winapi", ] [[package]] -name = "tokio-macros" -version = "0.2.6" +name = "tokio-stream" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" +checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" dependencies = [ - "proc-macro2", - "quote", - "syn", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] name = "tokio-util" -version = "0.3.1" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" dependencies = [ "bytes", "futures-core", "futures-sink", "log", - "pin-project-lite 0.1.11", + "pin-project-lite", "tokio", ] @@ -5323,7 +5235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ "cfg-if 1.0.0", - "pin-project-lite 0.2.4", + "pin-project-lite", "tracing-attributes", "tracing-core", ] @@ -5464,9 +5376,9 @@ dependencies = [ [[package]] name = "unicode-script" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79bf4d5fc96546fdb73f9827097810bbda93b11a6770ff3a54e1f445d4135787" +checksum = "098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9" [[package]] name = "unicode-security" @@ -5620,7 +5532,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" dependencies = [ "same-file", - "winapi 0.3.9", + "winapi", "winapi-util", ] @@ -5635,12 +5547,6 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -5651,12 +5557,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -5669,7 +5569,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5678,16 +5578,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "xattr" version = "0.2.2" @@ -5750,5 +5640,5 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" dependencies = [ - "winapi 0.3.9", + "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 327afe35c2..dedfe45aca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,11 +34,13 @@ members = [ "src/tools/unicode-table-generator", "src/tools/expand-yaml-anchors", "src/tools/jsondocck", + "src/tools/html-checker", ] exclude = [ "build", "compiler/rustc_codegen_cranelift", + "src/test/rustdoc-gui", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", # The `x` binary is a thin wrapper that calls `x.py`, which initializes diff --git a/README.md b/README.md index af6a4090a2..32fab9fc25 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Read ["Installation"] from [The Book]. The Rust build system uses a Python script called `x.py` to build the compiler, which manages the bootstrapping process. It lives in the root of the project. -The `x.py` command can be run directly on most systems in the following format: +The `x.py` command can be run directly on most systems in the following format: ```sh ./x.py [flags] @@ -272,15 +272,14 @@ See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and ## Trademark -The Rust programming language is an open source, community project governed -by a core team. It is also sponsored by the Mozilla Foundation (“Mozilla”), -which owns and protects the Rust and Cargo trademarks and logos -(the “Rust Trademarks”). +[The Rust Foundation][rust-foundation] owns and protects the Rust and Cargo +trademarks and logos (the “Rust Trademarks”). If you want to use these names or brands, please read the [media guide][media-guide]. Third-party logos may be subject to third-party copyrights and trademarks. See [Licenses][policies-licenses] for details. +[rust-foundation]: https://foundation.rust-lang.org/ [media-guide]: https://www.rust-lang.org/policies/media-guide [policies-licenses]: https://www.rust-lang.org/policies/licenses diff --git a/RELEASES.md b/RELEASES.md index 36d6a5276f..046608ea8f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,21 +1,150 @@ +Version 1.55.0 (2021-09-09) +============================ + +Language +-------- +- [You can now write open "from" range patterns (`X..`), which will start at `X` and + will end at the maximum value of the integer.][83918] +- [You can now explicitly import the prelude of different editions + through `std::prelude` (e.g. `use std::prelude::rust_2021::*;`).][86294] + +Compiler +-------- +- [Added tier 3\* support for `powerpc64le-unknown-freebsd`.][83572] + +\* Refer to Rust's [platform support page][platform-support-doc] for more + information on Rust's tiered platform support. + +Libraries +--------- + +- [Updated std's float parsing to use the Eisel-Lemire algorithm.][86761] + These improvements should in general provide faster string parsing of floats, + no longer reject certain valid floating point values, and reduce + the produced code size for non-stripped artifacts. +- [`string::Drain` now implements `AsRef` and `AsRef<[u8]>`.][86858] + +Stabilised APIs +--------------- + +- [`Bound::cloned`] +- [`Drain::as_str`] +- [`IntoInnerError::into_error`] +- [`IntoInnerError::into_parts`] +- [`MaybeUninit::assume_init_mut`] +- [`MaybeUninit::assume_init_ref`] +- [`MaybeUninit::write`] +- [`array::map`] +- [`ops::ControlFlow`] +- [`x86::_bittest`] +- [`x86::_bittestandcomplement`] +- [`x86::_bittestandreset`] +- [`x86::_bittestandset`] +- [`x86_64::_bittest64`] +- [`x86_64::_bittestandcomplement64`] +- [`x86_64::_bittestandreset64`] +- [`x86_64::_bittestandset64`] + +The following previously stable functions are now `const`. + +- [`str::from_utf8_unchecked`] +- [`mem::transmute`] + + +Cargo +----- +- [Cargo will now deduplicate compiler diagnostics to the terminal when invoking + rustc in parallel such as when using `cargo test`.][cargo/9675] +- [The package definition in `cargo metadata` now includes the `"default_run"` + field from the manifest.][cargo/9550] +- [Added `cargo d` as an alias for `cargo doc`.][cargo/9680] +- [Added `{lib}` as formatting option for `cargo tree` to print the `"lib_name"` + of packages.][cargo/9663] + +Rustdoc +------- +- [Added "Go to item on exact match" search option.][85876] +- [The "Implementors" section on traits no longer shows redundant + method definitions.][85970] +- [Trait implementations are toggled open by default.][86260] This should make the + implementations more searchable by tools like `CTRL+F` in your browser. +- [Intra-doc links should now correctly resolve associated items (e.g. methods) + through type aliases.][86334] +- [Traits which are marked with `#[doc(hidden)]` will no longer appear in the + "Trait Implementations" section.][86513] + + +Compatibility Notes +------------------- +- [std functions that return an `io::Error` will no longer use the + `ErrorKind::Other` variant.][85746] This is to better reflect that these + kinds of errors could be categorised [into newer more specific `ErrorKind` + variants][79965], and that they do not represent a user error. +- [Using environment variable names with `process::Command` on Windows now + behaves as expected.][85270] Previously using envionment variables with + `Command` would cause them to be ASCII-uppercased. +- [Rustdoc will now warn on using rustdoc lints that aren't prefixed + with `rustdoc::`][86849] + +[86849]: https://github.com/rust-lang/rust/pull/86849 +[86513]: https://github.com/rust-lang/rust/pull/86513 +[86334]: https://github.com/rust-lang/rust/pull/86334 +[86260]: https://github.com/rust-lang/rust/pull/86260 +[85970]: https://github.com/rust-lang/rust/pull/85970 +[85876]: https://github.com/rust-lang/rust/pull/85876 +[83572]: https://github.com/rust-lang/rust/pull/83572 +[86294]: https://github.com/rust-lang/rust/pull/86294 +[86858]: https://github.com/rust-lang/rust/pull/86858 +[86761]: https://github.com/rust-lang/rust/pull/86761 +[85769]: https://github.com/rust-lang/rust/pull/85769 +[85746]: https://github.com/rust-lang/rust/pull/85746 +[85305]: https://github.com/rust-lang/rust/pull/85305 +[85270]: https://github.com/rust-lang/rust/pull/85270 +[84111]: https://github.com/rust-lang/rust/pull/84111 +[83918]: https://github.com/rust-lang/rust/pull/83918 +[79965]: https://github.com/rust-lang/rust/pull/79965 +[87370]: https://github.com/rust-lang/rust/pull/87370 +[87298]: https://github.com/rust-lang/rust/pull/87298 +[cargo/9663]: https://github.com/rust-lang/cargo/pull/9663 +[cargo/9675]: https://github.com/rust-lang/cargo/pull/9675 +[cargo/9550]: https://github.com/rust-lang/cargo/pull/9550 +[cargo/9680]: https://github.com/rust-lang/cargo/pull/9680 +[cargo/9663]: https://github.com/rust-lang/cargo/pull/9663 +[`array::map`]: https://doc.rust-lang.org/stable/std/primitive.array.html#method.map +[`Bound::cloned`]: https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.cloned +[`Drain::as_str`]: https://doc.rust-lang.org/stable/std/string/struct.Drain.html#method.as_str +[`IntoInnerError::into_error`]: https://doc.rust-lang.org/stable/std/io/struct.IntoInnerError.html#method.into_error +[`IntoInnerError::into_parts`]: https://doc.rust-lang.org/stable/std/io/struct.IntoInnerError.html#method.into_parts +[`MaybeUninit::assume_init_mut`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_mut +[`MaybeUninit::assume_init_ref`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref +[`MaybeUninit::write`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.write +[`Seek::rewind`]: https://doc.rust-lang.org/stable/std/io/trait.Seek.html#method.rewind +[`mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html +[`ops::ControlFlow`]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html +[`str::from_utf8_unchecked`]: https://doc.rust-lang.org/stable/std/str/fn.from_utf8_unchecked.html +[`x86::_bittest`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittest.html +[`x86::_bittestandcomplement`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittestandcomplement.html +[`x86::_bittestandreset`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittestandreset.html +[`x86::_bittestandset`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittestandset.html +[`x86_64::_bittest64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittest64.html +[`x86_64::_bittestandcomplement64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittestandcomplement64.html +[`x86_64::_bittestandreset64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittestandreset64.html +[`x86_64::_bittestandset64`]: https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bittestandset64.html + + Version 1.54.0 (2021-07-29) ============================ Language ----------------------- -- [You can now use macros for values in built-in attribute macros.][83366] - While a seemingly minor addition on its own, this enables a lot of - powerful functionality when combined correctly. Most notably you can - now include external documentation in your crate by writing the following. +- [You can now use macros for values in some built-in attributes.][83366] + This primarily allows you to call macros within the `#[doc]` attribute. For + example, to include external documentation in your crate, you can now write + the following: ```rust #![doc = include_str!("README.md")] ``` - You can also use this to include auto-generated modules: - ```rust - #[path = concat!(env!("OUT_DIR"), "/generated.rs")] - mod generated; - ``` - [You can now cast between unsized slice types (and types which contain unsized slices) in `const fn`.][85078] @@ -37,6 +166,7 @@ Compiler - [Improved debugger output for enums on Windows MSVC platforms.][85292] - [Added tier 3\* support for `bpfel-unknown-none` and `bpfeb-unknown-none`.][79608] +- [`-Zmutable-noalias=yes`][82834] is enabled by default when using LLVM 12 or above. \* Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. @@ -106,6 +236,7 @@ Compatibility Notes [83366]: https://github.com/rust-lang/rust/pull/83366 [83278]: https://github.com/rust-lang/rust/pull/83278 [85292]: https://github.com/rust-lang/rust/pull/85292 +[82834]: https://github.com/rust-lang/rust/pull/82834 [cargo/9520]: https://github.com/rust-lang/cargo/pull/9520 [cargo/9499]: https://github.com/rust-lang/cargo/pull/9499 [cargo/9488]: https://github.com/rust-lang/cargo/pull/9488 @@ -168,7 +299,7 @@ Libraries - [`leading_zeros`, and `trailing_zeros` are now available on all `NonZero` integer types.][84082] - [`{f32, f64}::from_str` now parse and print special values - (`NaN`, `-0`) according to IEEE RFC 754.][78618] + (`NaN`, `-0`) according to IEEE 754.][78618] - [You can now index into slices using `(Bound, Bound)`.][77704] - [Add the `BITS` associated constant to all numeric types.][82565] diff --git a/compiler/rustc_apfloat/tests/ieee.rs b/compiler/rustc_apfloat/tests/ieee.rs index 63d925cce9..f8fac0c235 100644 --- a/compiler/rustc_apfloat/tests/ieee.rs +++ b/compiler/rustc_apfloat/tests/ieee.rs @@ -552,7 +552,7 @@ fn fma() { assert!(f1.is_negative() && f1.is_zero()); } - // Test x87 extended precision case from http://llvm.org/PR20728. + // Test x87 extended precision case from https://llvm.org/PR20728. { let mut m1 = X87DoubleExtended::from_u128(1).value; let m2 = X87DoubleExtended::from_u128(1).value; @@ -1939,7 +1939,7 @@ fn add() { (m_smallest_normalized, m_smallest_normalized, "-0x1p-125", Status::OK, Category::Normal), ]; - for &(x, y, e_result, e_status, e_category) in &special_cases[..] { + for (x, y, e_result, e_status, e_category) in special_cases { let status; let result = unpack!(status=, x + y); assert_eq!(status, e_status); @@ -2262,7 +2262,7 @@ fn subtract() { (m_smallest_normalized, m_smallest_normalized, "0x0p+0", Status::OK, Category::Zero), ]; - for &(x, y, e_result, e_status, e_category) in &special_cases[..] { + for (x, y, e_result, e_status, e_category) in special_cases { let status; let result = unpack!(status=, x - y); assert_eq!(status, e_status); @@ -2538,7 +2538,7 @@ fn multiply() { (m_smallest_normalized, m_smallest_normalized, "0x0p+0", underflow_status, Category::Zero), ]; - for &(x, y, e_result, e_status, e_category) in &special_cases[..] { + for (x, y, e_result, e_status, e_category) in special_cases { let status; let result = unpack!(status=, x * y); assert_eq!(status, e_status); @@ -2814,7 +2814,7 @@ fn divide() { (m_smallest_normalized, m_smallest_normalized, "0x1p+0", Status::OK, Category::Normal), ]; - for &(x, y, e_result, e_status, e_category) in &special_cases[..] { + for (x, y, e_result, e_status, e_category) in special_cases { let status; let result = unpack!(status=, x / y); assert_eq!(status, e_status); diff --git a/compiler/rustc_apfloat/tests/ppc.rs b/compiler/rustc_apfloat/tests/ppc.rs index 5a8de71cb3..c769d26543 100644 --- a/compiler/rustc_apfloat/tests/ppc.rs +++ b/compiler/rustc_apfloat/tests/ppc.rs @@ -64,7 +64,7 @@ fn ppc_double_double_add_special() { (0x7ff8000000000000, 0x3ff0000000000000, Category::NaN, Round::NearestTiesToEven), ]; - for &(op1, op2, expected, round) in &data { + for (op1, op2, expected, round) in data { { let mut a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); @@ -135,7 +135,7 @@ fn ppc_double_double_add() { ), ]; - for &(op1, op2, expected, round) in &data { + for (op1, op2, expected, round) in data { { let mut a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); @@ -172,7 +172,7 @@ fn ppc_double_double_subtract() { ), ]; - for &(op1, op2, expected, round) in &data { + for (op1, op2, expected, round) in data { let mut a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); a1 = a1.sub_r(a2, round).value; @@ -204,7 +204,7 @@ fn ppc_double_double_multiply_special() { (0, 0x3ff0000000000000, Category::Zero, Round::NearestTiesToEven), ]; - for &(op1, op2, expected, round) in &data { + for (op1, op2, expected, round) in data { { let mut a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); @@ -290,7 +290,7 @@ fn ppc_double_double_multiply() { ), ]; - for &(op1, op2, expected, round) in &data { + for (op1, op2, expected, round) in data { { let mut a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); @@ -322,7 +322,7 @@ fn ppc_double_double_divide() { ), ]; - for &(op1, op2, expected, round) in &data { + for (op1, op2, expected, round) in data { let mut a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); a1 = a1.div_r(a2, round).value; @@ -348,7 +348,7 @@ fn ppc_double_double_remainder() { ), ]; - for &(op1, op2, expected) in &data { + for (op1, op2, expected) in data { let a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); let result = a1.ieee_rem(a2).value; @@ -376,7 +376,7 @@ fn ppc_double_double_mod() { ), ]; - for &(op1, op2, expected) in &data { + for (op1, op2, expected) in data { let a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); let r = (a1 % a2).value; @@ -426,7 +426,7 @@ fn ppc_double_double_compare() { (0x7ff0000000000000, 0x7ff0000000000000, Some(Ordering::Equal)), ]; - for &(op1, op2, expected) in &data { + for (op1, op2, expected) in data { let a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); assert_eq!(expected, a1.partial_cmp(&a2), "compare({:#x}, {:#x})", op1, op2,); @@ -448,7 +448,7 @@ fn ppc_double_double_bitwise_eq() { (0x7ff0000000000000, 0x7ff0000000000000, true), ]; - for &(op1, op2, expected) in &data { + for (op1, op2, expected) in data { let a1 = DoubleDouble::from_bits(op1); let a2 = DoubleDouble::from_bits(op2); assert_eq!(expected, a1.bitwise_eq(a2), "{:#x} = {:#x}", op1, op2); diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 93d7a59768..f851725058 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -677,7 +677,9 @@ pub enum BindingMode { #[derive(Clone, Encodable, Decodable, Debug)] pub enum RangeEnd { + /// `..=` or `...` Included(RangeSyntax), + /// `..` Excluded, } @@ -689,6 +691,7 @@ pub enum RangeSyntax { DotDotEq, } +/// All the different flavors of pattern that Rust recognizes. #[derive(Clone, Encodable, Decodable, Debug)] pub enum PatKind { /// Represents a wildcard pattern (`_`). @@ -729,7 +732,7 @@ pub enum PatKind { /// A literal. Lit(P), - /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). + /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`). Range(Option>, Option>, Spanned), /// A slice pattern `[a, b, c]`. @@ -1017,7 +1020,7 @@ pub struct Local { /// ``` #[derive(Clone, Encodable, Decodable, Debug)] pub struct Arm { - pub attrs: Vec, + pub attrs: AttrVec, /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }` pub pat: P, /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }` @@ -1935,6 +1938,7 @@ bitflags::bitflags! { const NORETURN = 1 << 4; const NOSTACK = 1 << 5; const ATT_SYNTAX = 1 << 6; + const RAW = 1 << 7; } } @@ -2293,7 +2297,7 @@ pub struct EnumDef { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Variant { /// Attributes of the variant. - pub attrs: Vec, + pub attrs: AttrVec, /// Id of the variant (not the constructor, see `VariantData::ctor_id()`). pub id: NodeId, /// Span @@ -2474,7 +2478,7 @@ impl VisibilityKind { /// E.g., `bar: usize` as in `struct Foo { bar: usize }`. #[derive(Clone, Encodable, Decodable, Debug)] pub struct FieldDef { - pub attrs: Vec, + pub attrs: AttrVec, pub id: NodeId, pub span: Span, pub vis: Visibility, diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index 290f6006de..c0a837985f 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -1,3 +1,4 @@ +#[derive(Debug)] pub enum EntryPointType { None, MainNamed, diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index cd27f958e4..1976e4ad3c 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -1,6 +1,6 @@ use rustc_span::symbol::{sym, Symbol}; -#[derive(Clone, Copy)] +#[derive(Clone, Debug, Copy, HashStable_Generic)] pub enum AllocatorKind { Global, Default, diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 7c79b4aab3..3207aee6d2 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -10,7 +10,6 @@ )] #![feature(box_syntax)] #![feature(box_patterns)] -#![cfg_attr(bootstrap, feature(const_fn_unsize))] #![feature(const_fn_transmute)] #![feature(crate_visibility_modifier)] #![feature(iter_zip)] diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0b6099fd33..87950b4408 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -420,7 +420,7 @@ pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> { let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm; - visit_attrs(attrs, vis); + visit_thin_attrs(attrs, vis); vis.visit_id(id); vis.visit_pat(pat); visit_opt(guard, |guard| vis.visit_expr(guard)); @@ -504,7 +504,7 @@ pub fn noop_flat_map_variant( let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; visitor.visit_ident(ident); visitor.visit_vis(vis); - visit_attrs(attrs, visitor); + visit_thin_attrs(attrs, visitor); visitor.visit_id(id); visitor.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr)); @@ -918,7 +918,7 @@ pub fn noop_flat_map_field_def( visitor.visit_vis(vis); visitor.visit_id(id); visitor.visit_ty(ty); - visit_attrs(attrs, visitor); + visit_thin_attrs(attrs, visitor); smallvec![fd] } @@ -1347,12 +1347,6 @@ pub fn noop_visit_expr( } ExprKind::Paren(expr) => { vis.visit_expr(expr); - - // Nodes that are equal modulo `Paren` sugar no-ops should have the same IDs. - *id = expr.id; - vis.visit_span(span); - visit_thin_attrs(attrs, vis); - return; } ExprKind::Yield(expr) => { visit_opt(expr, |expr| vis.visit_expr(expr)); diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs index d20bace608..7f928cb576 100644 --- a/compiler/rustc_ast/src/node_id.rs +++ b/compiler/rustc_ast/src/node_id.rs @@ -1,4 +1,4 @@ -use rustc_span::ExpnId; +use rustc_span::LocalExpnId; use std::fmt; rustc_index::newtype_index! { @@ -24,12 +24,12 @@ pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0); pub const DUMMY_NODE_ID: NodeId = NodeId::MAX; impl NodeId { - pub fn placeholder_from_expn_id(expn_id: ExpnId) -> Self { + pub fn placeholder_from_expn_id(expn_id: LocalExpnId) -> Self { NodeId::from_u32(expn_id.as_u32()) } - pub fn placeholder_to_expn_id(self) -> ExpnId { - ExpnId::from_u32(self.as_u32()) + pub fn placeholder_to_expn_id(self) -> LocalExpnId { + LocalExpnId::from_u32(self.as_u32()) } } diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs index 98ab653e45..6d137f3774 100644 --- a/compiler/rustc_ast/src/util/comments/tests.rs +++ b/compiler/rustc_ast/src/util/comments/tests.rs @@ -1,9 +1,9 @@ use super::*; -use rustc_span::with_default_session_globals; +use rustc_span::create_default_session_globals_then; #[test] fn test_block_doc_comment_1() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let comment = "\n * Test \n ** Test\n * Test\n"; let stripped = beautify_doc_string(Symbol::intern(comment)); assert_eq!(stripped.as_str(), " Test \n* Test\n Test"); @@ -12,7 +12,7 @@ fn test_block_doc_comment_1() { #[test] fn test_block_doc_comment_2() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let comment = "\n * Test\n * Test\n"; let stripped = beautify_doc_string(Symbol::intern(comment)); assert_eq!(stripped.as_str(), " Test\n Test"); @@ -21,7 +21,7 @@ fn test_block_doc_comment_2() { #[test] fn test_block_doc_comment_3() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let comment = "\n let a: *i32;\n *a = 5;\n"; let stripped = beautify_doc_string(Symbol::intern(comment)); assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;"); @@ -30,7 +30,7 @@ fn test_block_doc_comment_3() { #[test] fn test_line_doc_comment() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let stripped = beautify_doc_string(Symbol::intern(" test")); assert_eq!(stripped.as_str(), " test"); let stripped = beautify_doc_string(Symbol::intern("! test")); diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 1c3fae2afe..9ea09a2cf3 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -199,6 +199,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ); + // Some register classes can only be used as clobbers. This + // means that we disallow passing a value in/out of the asm and + // require that the operand name an explicit register, not a + // register class. + if reg_class.is_clobber_only(asm_arch.unwrap()) + && !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_))) + { + let msg = format!( + "register class `{}` can only be used as a clobber, \ + not as an input or output", + reg_class.name() + ); + sess.struct_span_err(op_sp, &msg).emit(); + continue; + } + if !is_clobber { // Validate register classes against currently enabled target // features. We check that at least one type is available for diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b9dcd083c0..7fecf537cf 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1067,6 +1067,15 @@ impl<'hir> LoweringContext<'_, 'hir> { eq_sign_span: Span, assignments: &mut Vec>, ) -> &'hir hir::Pat<'hir> { + self.arena.alloc(self.destructure_assign_mut(lhs, eq_sign_span, assignments)) + } + + fn destructure_assign_mut( + &mut self, + lhs: &Expr, + eq_sign_span: Span, + assignments: &mut Vec>, + ) -> hir::Pat<'hir> { match &lhs.kind { // Underscore pattern. ExprKind::Underscore => { @@ -1080,7 +1089,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (before, after) = pats.split_at(i); hir::PatKind::Slice( before, - Some(self.pat_without_dbm(span, hir::PatKind::Wild)), + Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))), after, ) } else { @@ -1165,14 +1174,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let tuple_pat = hir::PatKind::Tuple(&[], Some(0)); return self.pat_without_dbm(lhs.span, tuple_pat); } else { - return self.destructure_assign(e, eq_sign_span, assignments); + return self.destructure_assign_mut(e, eq_sign_span, assignments); } } _ => {} } // Treat all other cases as normal lvalue. let ident = Ident::new(sym::lhs, lhs.span); - let (pat, binding) = self.pat_ident(lhs.span, ident); + let (pat, binding) = self.pat_ident_mut(lhs.span, ident); let ident = self.expr_ident(lhs.span, ident, binding); let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, eq_sign_span); let expr = self.expr(lhs.span, assign, ThinVec::new()); @@ -1191,7 +1200,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ctx: &str, eq_sign_span: Span, assignments: &mut Vec>, - ) -> (&'hir [&'hir hir::Pat<'hir>], Option<(usize, Span)>) { + ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) { let mut rest = None; let elements = self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| { @@ -1204,7 +1213,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } None } else { - Some(self.destructure_assign(e, eq_sign_span, assignments)) + Some(self.destructure_assign_mut(e, eq_sign_span, assignments)) } })); (elements, rest) @@ -1559,13 +1568,14 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Desugar `ExprKind::Try` from: `?` into: /// ```rust - /// match Try::into_result() { - /// Ok(val) => #[allow(unreachable_code)] val, - /// Err(err) => #[allow(unreachable_code)] - /// // If there is an enclosing `try {...}`: - /// break 'catch_target Try::from_error(From::from(err)), - /// // Otherwise: - /// return Try::from_error(From::from(err)), + /// match Try::branch() { + /// ControlFlow::Continue(val) => #[allow(unreachable_code)] val,, + /// ControlFlow::Break(residual) => + /// #[allow(unreachable_code)] + /// // If there is an enclosing `try {...}`: + /// break 'catch_target Try::from_residual(residual), + /// // Otherwise: + /// return Try::from_residual(residual), /// } /// ``` fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 292643d6d7..880692516e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -343,9 +343,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // opaque type Foo1: Trait let ty = self.lower_ty( ty, - ImplTraitContext::OtherOpaqueTy { + ImplTraitContext::TypeAliasesOpaqueTy { capturable_lifetimes: &mut FxHashSet::default(), - origin: hir::OpaqueTyOrigin::TyAlias, }, ); let generics = self.lower_generics(gen, ImplTraitContext::disallowed()); @@ -484,17 +483,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let mut capturable_lifetimes; - let itctx = if self.sess.features_untracked().impl_trait_in_bindings { - capturable_lifetimes = FxHashSet::default(); - ImplTraitContext::OtherOpaqueTy { - capturable_lifetimes: &mut capturable_lifetimes, - origin: hir::OpaqueTyOrigin::Misc, - } - } else { - ImplTraitContext::Disallowed(ImplTraitPosition::Binding) - }; - let ty = self.lower_ty(ty, itctx); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)); (ty, self.lower_const_body(span, body)) } @@ -926,9 +915,8 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(ty) => { let ty = self.lower_ty( ty, - ImplTraitContext::OtherOpaqueTy { + ImplTraitContext::TypeAliasesOpaqueTy { capturable_lifetimes: &mut FxHashSet::default(), - origin: hir::OpaqueTyOrigin::TyAlias, }, ); hir::ImplItemKind::TyAlias(ty) @@ -1385,50 +1373,34 @@ impl<'hir> LoweringContext<'_, 'hir> { itctx: ImplTraitContext<'_, 'hir>, ) -> GenericsCtor<'hir> { // Collect `?Trait` bounds in where clause and move them to parameter definitions. - // FIXME: this could probably be done with less rightward drift. It also looks like two - // control paths where `report_error` is called are the only paths that advance to after the - // match statement, so the error reporting could probably just be moved there. let mut add_bounds: NodeMap> = Default::default(); for pred in &generics.where_clause.predicates { if let WherePredicate::BoundPredicate(ref bound_pred) = *pred { 'next_bound: for bound in &bound_pred.bounds { if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound { - let report_error = |this: &mut Self| { - this.diagnostic().span_err( - bound_pred.bounded_ty.span, - "`?Trait` bounds are only permitted at the \ - point where a type parameter is declared", - ); - }; // Check if the where clause type is a plain type parameter. - match bound_pred.bounded_ty.kind { - TyKind::Path(None, ref path) - if path.segments.len() == 1 - && bound_pred.bound_generic_params.is_empty() => + match self + .resolver + .get_partial_res(bound_pred.bounded_ty.id) + .map(|d| (d.base_res(), d.unresolved_segments())) + { + Some((Res::Def(DefKind::TyParam, def_id), 0)) + if bound_pred.bound_generic_params.is_empty() => { - if let Some(Res::Def(DefKind::TyParam, def_id)) = self - .resolver - .get_partial_res(bound_pred.bounded_ty.id) - .map(|d| d.base_res()) - { - if let Some(def_id) = def_id.as_local() { - for param in &generics.params { - if let GenericParamKind::Type { .. } = param.kind { - if def_id == self.resolver.local_def_id(param.id) { - add_bounds - .entry(param.id) - .or_default() - .push(bound.clone()); - continue 'next_bound; - } - } - } + for param in &generics.params { + if def_id == self.resolver.local_def_id(param.id).to_def_id() { + add_bounds.entry(param.id).or_default().push(bound.clone()); + continue 'next_bound; } } - report_error(self) } - _ => report_error(self), + _ => {} } + self.diagnostic().span_err( + bound_pred.bounded_ty.span, + "`?Trait` bounds are only permitted at the \ + point where a type parameter is declared", + ); } } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0ff1efd816..d4caba9241 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -48,7 +48,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::intravisit; use rustc_hir::{ConstArg, GenericArg, ParamName}; @@ -59,7 +59,7 @@ use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::ExpnId; -use rustc_span::source_map::{respan, DesugaringKind}; +use rustc_span::source_map::{respan, CachingSourceMapView, DesugaringKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; @@ -204,6 +204,8 @@ pub trait ResolverAstLowering { fn local_def_id(&self, node: NodeId) -> LocalDefId; + fn def_path_hash(&self, def_id: DefId) -> DefPathHash; + fn create_def( &mut self, parent: LocalDefId, @@ -214,6 +216,32 @@ pub trait ResolverAstLowering { ) -> LocalDefId; } +struct LoweringHasher<'a> { + source_map: CachingSourceMapView<'a>, + resolver: &'a dyn ResolverAstLowering, +} + +impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> { + #[inline] + fn hash_spans(&self) -> bool { + true + } + + #[inline] + fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + self.resolver.def_path_hash(def_id) + } + + #[inline] + fn span_data_to_lines_and_cols( + &mut self, + span: &rustc_span::SpanData, + ) -> Option<(Lrc, usize, rustc_span::BytePos, usize, rustc_span::BytePos)> + { + self.source_map.span_data_to_lines_and_cols(span) + } +} + /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug)] @@ -236,8 +264,8 @@ enum ImplTraitContext<'b, 'a> { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, }, - /// Impl trait in type aliases, consts and statics. - OtherOpaqueTy { + /// Impl trait in type aliases. + TypeAliasesOpaqueTy { /// Set of lifetimes that this opaque type can capture, if it uses /// them. This includes lifetimes bound since we entered this context. /// For example: @@ -252,8 +280,6 @@ enum ImplTraitContext<'b, 'a> { // FIXME(impl_trait): but `required_region_bounds` will ICE later // anyway. capturable_lifetimes: &'b mut FxHashSet, - /// Origin: Either OpaqueTyOrigin::Misc or OpaqueTyOrigin::Binding, - origin: hir::OpaqueTyOrigin, }, /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), @@ -282,8 +308,8 @@ impl<'a> ImplTraitContext<'_, 'a> { ReturnPositionOpaqueTy { fn_def_id, origin } => { ReturnPositionOpaqueTy { fn_def_id: *fn_def_id, origin: *origin } } - OtherOpaqueTy { capturable_lifetimes, origin } => { - OtherOpaqueTy { capturable_lifetimes, origin: *origin } + TypeAliasesOpaqueTy { capturable_lifetimes } => { + TypeAliasesOpaqueTy { capturable_lifetimes } } Disallowed(pos) => Disallowed(*pos), } @@ -296,7 +322,7 @@ pub fn lower_crate<'a, 'hir>( resolver: &'a mut dyn ResolverAstLowering, nt_to_tokenstream: NtToTokenstream, arena: &'hir Arena<'hir>, -) -> hir::Crate<'hir> { +) -> &'hir hir::Crate<'hir> { let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); LoweringContext { @@ -331,7 +357,7 @@ pub fn lower_crate<'a, 'hir>( lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), - allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()), + allow_try_trait: Some([sym::try_trait_v2][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), } .lower_crate(krate) @@ -403,7 +429,7 @@ enum AnonymousLifetimeMode { } impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn lower_crate(mut self, c: &Crate) -> hir::Crate<'hir> { + fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> { /// Full-crate AST visitor that inserts into a fresh /// `LoweringContext` any information that may be /// needed from arbitrary locations in the crate, @@ -417,7 +443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) { match tree.kind { UseTreeKind::Simple(_, id1, id2) => { - for &id in &[id1, id2] { + for id in [id1, id2] { self.lctx.allocate_hir_id_counter(id); } } @@ -530,7 +556,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - hir::Crate { + let krate = hir::Crate { item: module, exported_macros: self.arena.alloc_from_iter(self.exported_macros), non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), @@ -545,7 +571,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { proc_macros, trait_map, attrs: self.attrs, - } + }; + self.arena.alloc(krate) } fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { @@ -564,6 +591,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lowered } + fn create_stable_hashing_context(&self) -> LoweringHasher<'_> { + LoweringHasher { + source_map: CachingSourceMapView::new(self.sess.source_map()), + resolver: self.resolver, + } + } + fn lower_node_id_generic( &mut self, ast_node_id: NodeId, @@ -683,7 +717,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, allow_internal_unstable: Option>, ) -> Span { - span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition()) + span.mark_with_reason( + allow_internal_unstable, + reason, + self.sess.edition(), + self.create_stable_hashing_context(), + ) } fn with_anonymous_lifetime_mode( @@ -1085,7 +1124,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // fn foo() -> impl Iterator ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::OtherOpaqueTy { .. } => (true, itctx), + | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx), // We are in the argument position, but within a dyn type: // @@ -1109,9 +1148,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { capturable_lifetimes = FxHashSet::default(); ( true, - ImplTraitContext::OtherOpaqueTy { + ImplTraitContext::TypeAliasesOpaqueTy { capturable_lifetimes: &mut capturable_lifetimes, - origin: hir::OpaqueTyOrigin::Misc, }, ) } @@ -1375,18 +1413,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, |this| this.lower_param_bounds(bounds, itctx), ), - ImplTraitContext::OtherOpaqueTy { ref capturable_lifetimes, origin } => { + ImplTraitContext::TypeAliasesOpaqueTy { ref capturable_lifetimes } => { // Reset capturable lifetimes, any nested impl trait // types will inherit lifetimes from this opaque type, // so don't need to capture them again. - let nested_itctx = ImplTraitContext::OtherOpaqueTy { + let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy { capturable_lifetimes: &mut FxHashSet::default(), - origin, }; self.lower_opaque_impl_trait( span, None, - origin, + hir::OpaqueTyOrigin::TyAlias, def_node_id, Some(capturable_lifetimes), |this| this.lower_param_bounds(bounds, nested_itctx), @@ -1423,25 +1460,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), )) } - ImplTraitContext::Disallowed(pos) => { - let allowed_in = if self.sess.features_untracked().impl_trait_in_bindings { - "bindings or function and inherent method return types" - } else { - "function and inherent method return types" - }; + ImplTraitContext::Disallowed(_) => { let mut err = struct_span_err!( self.sess, t.span, E0562, "`impl Trait` not allowed outside of {}", - allowed_in, + "function and method return types", ); - if pos == ImplTraitPosition::Binding && self.sess.is_nightly_build() { - err.help( - "add `#![feature(impl_trait_in_bindings)]` to the crate \ - attributes to enable", - ); - } err.emit(); hir::TyKind::Err } @@ -1726,21 +1752,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_local(&mut self, l: &Local) -> hir::Local<'hir> { - let ty = l.ty.as_ref().map(|t| { - let mut capturable_lifetimes; - self.lower_ty( - t, - if self.sess.features_untracked().impl_trait_in_bindings { - capturable_lifetimes = FxHashSet::default(); - ImplTraitContext::OtherOpaqueTy { - capturable_lifetimes: &mut capturable_lifetimes, - origin: hir::OpaqueTyOrigin::Binding, - } - } else { - ImplTraitContext::Disallowed(ImplTraitPosition::Binding) - }, - ) - }); + let ty = l + .ty + .as_ref() + .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding))); let init = l.init.as_ref().map(|e| self.lower_expr(e)); let hir_id = self.lower_node_id(l.id); self.lower_attrs(hir_id, &l.attrs); @@ -2291,13 +2306,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { )), _ => None, }); - if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx { + if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes, .. } = + itctx + { capturable_lifetimes.extend(lt_def_names.clone()); } let res = this.lower_trait_ref(&p.trait_ref, itctx.reborrow()); - if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx { + if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes, .. } = + itctx + { for param in lt_def_names { capturable_lifetimes.remove(¶m); } @@ -2536,21 +2555,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated) } + fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) { + self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated) + } + fn pat_ident_binding_mode( &mut self, span: Span, ident: Ident, bm: hir::BindingAnnotation, ) -> (&'hir hir::Pat<'hir>, hir::HirId) { + let (pat, hir_id) = self.pat_ident_binding_mode_mut(span, ident, bm); + (self.arena.alloc(pat), hir_id) + } + + fn pat_ident_binding_mode_mut( + &mut self, + span: Span, + ident: Ident, + bm: hir::BindingAnnotation, + ) -> (hir::Pat<'hir>, hir::HirId) { let hir_id = self.next_id(); ( - self.arena.alloc(hir::Pat { + hir::Pat { hir_id, kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None), span, default_binding_modes: true, - }), + }, hir_id, ) } @@ -2568,13 +2601,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } - fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> { - self.arena.alloc(hir::Pat { - hir_id: self.next_id(), - kind, - span, - default_binding_modes: false, - }) + fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> { + hir::Pat { hir_id: self.next_id(), kind, span, default_binding_modes: false } } fn ty_path( diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 66e623528f..d81ddd2c08 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -10,7 +10,11 @@ use rustc_span::symbol::Ident; use rustc_span::{source_map::Spanned, Span}; impl<'a, 'hir> LoweringContext<'a, 'hir> { - crate fn lower_pat(&mut self, mut pattern: &Pat) -> &'hir hir::Pat<'hir> { + crate fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> { + self.arena.alloc(self.lower_pat_mut(pattern)) + } + + crate fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { ensure_sufficient_stack(|| { // loop here to avoid recursion let node = loop { @@ -34,7 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } PatKind::Or(ref pats) => { break hir::PatKind::Or( - self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat(x))), + self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat_mut(x))), ); } PatKind::Path(ref qself, ref path) => { @@ -101,7 +105,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, pats: &[P], ctx: &str, - ) -> (&'hir [&'hir hir::Pat<'hir>], Option) { + ) -> (&'hir [hir::Pat<'hir>], Option) { let mut elems = Vec::with_capacity(pats.len()); let mut rest = None; @@ -140,7 +144,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // It was not a sub-tuple pattern so lower it normally. - elems.push(self.lower_pat(pat)); + elems.push(self.lower_pat_mut(pat)); } for (_, pat) in iter { @@ -149,7 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // ...but there was one again, so error. self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx); } else { - elems.push(self.lower_pat(pat)); + elems.push(self.lower_pat_mut(pat)); } } @@ -189,11 +193,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Record, lower it to `$binding_mode $ident @ _`, and stop here. PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { prev_rest_span = Some(sub.span); - slice = Some(lower_rest_sub(self, pat, bm, ident, sub)); + slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub))); break; } // It was not a subslice pattern so lower it normally. - _ => before.push(self.lower_pat(pat)), + _ => before.push(self.lower_pat_mut(pat)), } } @@ -214,7 +218,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice"); } else { // Lower the pattern normally. - after.push(self.lower_pat(pat)); + after.push(self.lower_pat_mut(pat)); } } @@ -268,17 +272,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> { - self.pat_with_node_id_of(p, hir::PatKind::Wild) + self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild)) } /// Construct a `Pat` with the `HirId` of `p.id` lowered. - fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> { - self.arena.alloc(hir::Pat { + fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> { + hir::Pat { hir_id: self.lower_node_id(p.id), kind, span: p.span, default_binding_modes: true, - }) + } } /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern. diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index fe9f1fb20f..55173c6f86 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -336,6 +336,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { insertion_sp, suggestion, ); + err.note("assuming a `'static` lifetime..."); err.emit(); } AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 30aa51a121..acc41d9f64 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -652,7 +652,7 @@ impl<'a> AstValidator<'a> { self.err_handler() .struct_span_err( *span, - "only foreign or `unsafe extern \"C\" functions may be C-variadic", + "only foreign or `unsafe extern \"C\"` functions may be C-variadic", ) .emit(); } @@ -889,35 +889,32 @@ fn validate_generic_param_order( ) { let mut max_param: Option = None; let mut out_of_order = FxHashMap::default(); - let mut param_idents = vec![]; + let mut param_idents = Vec::with_capacity(generics.len()); - for param in generics { - let ident = Some(param.ident.to_string()); - let (kind, bounds, span) = (¶m.kind, Some(&*param.bounds), param.ident.span); + for (idx, param) in generics.iter().enumerate() { + let ident = param.ident; + let (kind, bounds, span) = (¶m.kind, ¶m.bounds, ident.span); let (ord_kind, ident) = match ¶m.kind { - GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident), - GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), + GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident.to_string()), + GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); let unordered = sess.features_untracked().unordered_const_ty_params(); - (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty))) + (ParamKindOrd::Const { unordered }, format!("const {}: {}", ident, ty)) } }; - if let Some(ident) = ident { - param_idents.push((kind, ord_kind, bounds, param_idents.len(), ident)); - } - let max_param = &mut max_param; + param_idents.push((kind, ord_kind, bounds, idx, ident)); match max_param { - Some(max_param) if *max_param > ord_kind => { - let entry = out_of_order.entry(ord_kind).or_insert((*max_param, vec![])); + Some(max_param) if max_param > ord_kind => { + let entry = out_of_order.entry(ord_kind).or_insert((max_param, vec![])); entry.1.push(span); } - Some(_) | None => *max_param = Some(ord_kind), + Some(_) | None => max_param = Some(ord_kind), }; } - let mut ordered_params = "<".to_string(); if !out_of_order.is_empty() { + let mut ordered_params = "<".to_string(); param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i)); let mut first = true; for (kind, _, bounds, _, ident) in param_idents { @@ -925,12 +922,12 @@ fn validate_generic_param_order( ordered_params += ", "; } ordered_params += &ident; - if let Some(bounds) = bounds { - if !bounds.is_empty() { - ordered_params += ": "; - ordered_params += &pprust::bounds_to_string(&bounds); - } + + if !bounds.is_empty() { + ordered_params += ": "; + ordered_params += &pprust::bounds_to_string(&bounds); } + match kind { GenericParamKind::Type { default: Some(default) } => { ordered_params += " = "; @@ -946,32 +943,32 @@ fn validate_generic_param_order( } first = false; } - } - ordered_params += ">"; - for (param_ord, (max_param, spans)) in &out_of_order { - let mut err = - handler.struct_span_err( + ordered_params += ">"; + + for (param_ord, (max_param, spans)) in &out_of_order { + let mut err = handler.struct_span_err( spans.clone(), &format!( "{} parameters must be declared prior to {} parameters", param_ord, max_param, ), ); - err.span_suggestion( - span, - &format!( - "reorder the parameters: lifetimes, {}", - if sess.features_untracked().unordered_const_ty_params() { - "then consts and types" - } else { - "then types, then consts" - } - ), - ordered_params.clone(), - Applicability::MachineApplicable, - ); - err.emit(); + err.span_suggestion( + span, + &format!( + "reorder the parameters: lifetimes, {}", + if sess.features_untracked().unordered_const_ty_params() { + "then consts and types" + } else { + "then types, then consts" + } + ), + ordered_params.clone(), + Applicability::MachineApplicable, + ); + err.emit(); + } } } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 3f98944d85..3e757e3843 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -565,6 +565,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_pat(&mut self, pattern: &'a ast::Pat) { match &pattern.kind { + PatKind::Slice(pats) => { + for pat in pats { + let inner_pat = match &pat.kind { + PatKind::Ident(.., Some(pat)) => pat, + _ => pat, + }; + if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind { + gate_feature_post!( + &self, + half_open_range_patterns, + pat.span, + "`X..` patterns in slices are experimental" + ); + } + } + } PatKind::Box(..) => { gate_feature_post!( &self, @@ -573,7 +589,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "box pattern syntax is experimental" ); } - PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => { + PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => { gate_feature_post!( &self, exclusive_range_pattern, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3d2785faad..8b7b306a54 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -136,11 +136,11 @@ pub fn print_crate<'a>( s.s.eof() } -// This makes printed token streams look slightly nicer, -// and also addresses some specific regressions described in #63896 and #73345. +/// This makes printed token streams look slightly nicer, +/// and also addresses some specific regressions described in #63896 and #73345. fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { if let TokenTree::Token(token) = prev { - if matches!(token.kind, token::Dot) { + if matches!(token.kind, token::Dot | token::Dollar) { return false; } if let token::DocComment(comment_kind, ..) = token.kind { @@ -1954,7 +1954,6 @@ impl<'a> State<'a> { self.word_space(":"); } self.head("loop"); - self.s.space(); self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Match(ref expr, ref arms) => { @@ -2284,6 +2283,9 @@ impl<'a> State<'a> { if opts.contains(InlineAsmOptions::ATT_SYNTAX) { options.push("att_syntax"); } + if opts.contains(InlineAsmOptions::RAW) { + options.push("raw"); + } s.commasep(Inconsistent, &options, |s, &opt| { s.word(opt); }); diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs index b1a73a0bf0..6c8d42f33e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/tests.rs +++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs @@ -1,8 +1,8 @@ use super::*; use rustc_ast as ast; +use rustc_span::create_default_session_globals_then; use rustc_span::symbol::Ident; -use rustc_span::with_default_session_globals; fn fun_to_string( decl: &ast::FnDecl, @@ -24,7 +24,7 @@ fn variant_to_string(var: &ast::Variant) -> String { #[test] fn test_fun_to_string() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let abba_ident = Ident::from_str("abba"); let decl = @@ -39,7 +39,7 @@ fn test_fun_to_string() { #[test] fn test_variant_to_string() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let ident = Ident::from_str("principal_skinner"); let var = ast::Variant { @@ -49,7 +49,7 @@ fn test_variant_to_string() { kind: ast::VisibilityKind::Inherited, tokens: None, }, - attrs: Vec::new(), + attrs: ast::AttrVec::new(), id: ast::DUMMY_NODE_ID, data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), disr_expr: None, diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index e58b266fdb..b7b053cd5d 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -862,18 +862,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { if let Some(items) = attr.meta_item_list() { sess.mark_attr_used(attr); for item in items { - if !item.is_meta_item() { - handle_errors( - &sess.parse_sess, - item.span(), - AttrError::UnsupportedLiteral( - "meta item in `repr` must be an identifier", - false, - ), - ); - continue; - } - let mut recognised = false; if item.is_word() { let hint = match item.name_or_empty() { @@ -882,6 +870,23 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { sym::simd => Some(ReprSimd), sym::transparent => Some(ReprTransparent), sym::no_niche => Some(ReprNoNiche), + sym::align => { + let mut err = struct_span_err!( + diagnostic, + item.span(), + E0589, + "invalid `repr(align)` attribute: `align` needs an argument" + ); + err.span_suggestion( + item.span(), + "supply an argument here", + "align(...)".to_string(), + Applicability::HasPlaceholders, + ); + err.emit(); + recognised = true; + None + } name => int_type_of_word(name).map(ReprInt), }; @@ -890,23 +895,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { acc.push(h); } } else if let Some((name, value)) = item.name_value_literal() { - let parse_alignment = |node: &ast::LitKind| -> Result { - if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node { - if literal.is_power_of_two() { - // rustc_middle::ty::layout::Align restricts align to <= 2^29 - if *literal <= 1 << 29 { - Ok(*literal as u32) - } else { - Err("larger than 2^29") - } - } else { - Err("not a power of two") - } - } else { - Err("not an unsuffixed integer") - } - }; - let mut literal_error = None; if name == sym::align { recognised = true; @@ -920,33 +908,47 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { Ok(literal) => acc.push(ReprPacked(literal)), Err(message) => literal_error = Some(message), }; + } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche) + || int_type_of_word(name).is_some() + { + recognised = true; + struct_span_err!( + diagnostic, + item.span(), + E0552, + "invalid representation hint: `{}` does not take a parenthesized argument list", + name.to_ident_string(), + ).emit(); } if let Some(literal_error) = literal_error { struct_span_err!( diagnostic, item.span(), E0589, - "invalid `repr(align)` attribute: {}", + "invalid `repr({})` attribute: {}", + name.to_ident_string(), literal_error ) .emit(); } } else if let Some(meta_item) = item.meta_item() { - if meta_item.has_name(sym::align) { - if let MetaItemKind::NameValue(ref value) = meta_item.kind { + if let MetaItemKind::NameValue(ref value) = meta_item.kind { + if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) { + let name = meta_item.name_or_empty().to_ident_string(); recognised = true; let mut err = struct_span_err!( diagnostic, item.span(), E0693, - "incorrect `repr(align)` attribute format" + "incorrect `repr({})` attribute format", + name, ); match value.kind { ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { err.span_suggestion( item.span(), "use parentheses instead", - format!("align({})", int), + format!("{}({})", name, int), Applicability::MachineApplicable, ); } @@ -954,25 +956,76 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { err.span_suggestion( item.span(), "use parentheses instead", - format!("align({})", s), + format!("{}({})", name, s), Applicability::MachineApplicable, ); } _ => {} } err.emit(); + } else { + if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent | sym::no_niche + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0552, + "invalid representation hint: `{}` does not take a value", + meta_item.name_or_empty().to_ident_string(), + ) + .emit(); + } + } + } else if let MetaItemKind::List(_) = meta_item.kind { + if meta_item.has_name(sym::align) { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0693, + "incorrect `repr(align)` attribute format: \ + `align` takes exactly one argument in parentheses" + ) + .emit(); + } else if meta_item.has_name(sym::packed) { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0552, + "incorrect `repr(packed)` attribute format: \ + `packed` takes exactly one parenthesized argument, \ + or no parentheses at all" + ) + .emit(); + } else if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent | sym::no_niche + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0552, + "invalid representation hint: `{}` does not take a parenthesized argument list", + meta_item.name_or_empty().to_ident_string(), + ).emit(); } } } if !recognised { - // Not a word we recognize - struct_span_err!( - diagnostic, - item.span(), - E0552, - "unrecognized representation hint" - ) - .emit(); + // Not a word we recognize. This will be caught and reported by + // the `check_mod_attrs` pass, but this pass doesn't always run + // (e.g. if we only pretty-print the source), so we have to gate + // the `delay_span_bug` call as follows: + if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) { + diagnostic.delay_span_bug(item.span(), "unrecognized representation hint"); + } } } } @@ -1080,3 +1133,16 @@ fn allow_unstable<'a>( name }) } + +pub fn parse_alignment(node: &ast::LitKind) -> Result { + if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node { + if literal.is_power_of_two() { + // rustc_middle::ty::layout::Align restricts align to <= 2^29 + if *literal <= 1 << 29 { Ok(*literal as u32) } else { Err("larger than 2^29") } + } else { + Err("not a power of two") + } + } else { + Err("not an unsuffixed integer") + } +} diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index b28c6f0d99..ff13f0d4e4 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -356,6 +356,8 @@ fn parse_options<'a>( try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK); } else if p.eat_keyword(sym::att_syntax) { try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX); + } else if p.eat_keyword(kw::Raw) { + try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW); } else { return p.unexpected(); } @@ -453,7 +455,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option, args: AsmArgs) -> Option Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); - cfg_eval(ecx, annotatable) + vec![cfg_eval(ecx, annotatable)] } -crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec { - let mut visitor = CfgEval { +crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable { + CfgEval { cfg: &mut StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, config_tokens: true, }, - }; - let annotatable = visitor.configure_annotatable(annotatable); - vec![annotatable] + } + .configure_annotatable(annotatable) + // Since the item itself has already been configured by the `InvocationCollector`, + // we know that fold result vector will contain exactly one element. + .unwrap() } struct CfgEval<'a, 'b> { cfg: &'a mut StripUnconfigured<'b>, } -fn flat_map_annotatable(vis: &mut impl MutVisitor, annotatable: Annotatable) -> Annotatable { - // Since the item itself has already been configured by the InvocationCollector, - // we know that fold result vector will contain exactly one element +fn flat_map_annotatable( + vis: &mut impl MutVisitor, + annotatable: Annotatable, +) -> Option { match annotatable { - Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()), + Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item), Annotatable::TraitItem(item) => { - Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap()) + vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem) } Annotatable::ImplItem(item) => { - Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap()) + vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem) } Annotatable::ForeignItem(item) => { - Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap()) + vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem) } Annotatable::Stmt(stmt) => { - Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap())) + vis.flat_map_stmt(stmt.into_inner()).pop().map(P).map(Annotatable::Stmt) } - Annotatable::Expr(mut expr) => Annotatable::Expr({ + Annotatable::Expr(mut expr) => { vis.visit_expr(&mut expr); - expr - }), - Annotatable::Arm(arm) => Annotatable::Arm(vis.flat_map_arm(arm).pop().unwrap()), - Annotatable::ExprField(field) => { - Annotatable::ExprField(vis.flat_map_expr_field(field).pop().unwrap()) + Some(Annotatable::Expr(expr)) } - Annotatable::PatField(fp) => { - Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap()) + Annotatable::Arm(arm) => vis.flat_map_arm(arm).pop().map(Annotatable::Arm), + Annotatable::ExprField(field) => { + vis.flat_map_expr_field(field).pop().map(Annotatable::ExprField) } + Annotatable::PatField(fp) => vis.flat_map_pat_field(fp).pop().map(Annotatable::PatField), Annotatable::GenericParam(param) => { - Annotatable::GenericParam(vis.flat_map_generic_param(param).pop().unwrap()) - } - Annotatable::Param(param) => Annotatable::Param(vis.flat_map_param(param).pop().unwrap()), - Annotatable::FieldDef(sf) => { - Annotatable::FieldDef(vis.flat_map_field_def(sf).pop().unwrap()) + vis.flat_map_generic_param(param).pop().map(Annotatable::GenericParam) } - Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()), + Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param), + Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef), + Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant), } } @@ -123,11 +122,11 @@ impl CfgEval<'_, '_> { self.cfg.configure(node) } - pub fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Annotatable { + fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option { // Tokenizing and re-parsing the `Annotatable` can have a significant // performance impact, so try to avoid it if possible if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) { - return annotatable; + return Some(annotatable); } // The majority of parsed attribute targets will never need to have early cfg-expansion diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 1bb050a40c..e0389f448e 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -26,6 +26,8 @@ impl MultiItemModifier for Expander { return ExpandResult::Ready(vec![item]); } + let item = cfg_eval(ecx, item); + let result = ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { let template = @@ -54,12 +56,12 @@ impl MultiItemModifier for Expander { report_path_args(sess, &meta); meta.path }) - .map(|path| (path, None)) + .map(|path| (path, item.clone(), None)) .collect() }); match result { - Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)), + Ok(()) => ExpandResult::Ready(vec![item]), Err(Indeterminate) => ExpandResult::Retry(item), } } @@ -82,8 +84,10 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { sess, span, E0774, - "`derive` may only be applied to structs, enums and unions", + "`derive` may only be applied to `struct`s, `enum`s and `union`s", ) + .span_label(span, "not applicable here") + .span_label(item.span(), "not a `struct`, `enum` or `union`") .emit(); } bad_target @@ -97,6 +101,7 @@ fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), }; struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal",) + .span_label(lit.span, "not a trait") .help(&help_msg) .emit(); } diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index ca1226b445..2e5ad66c60 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -36,8 +36,9 @@ pub fn expand_deriving_clone( Annotatable::Item(ref annitem) => match annitem.kind { ItemKind::Struct(_, Generics { ref params, .. }) | ItemKind::Enum(_, Generics { ref params, .. }) => { - let container_id = cx.current_expansion.id.expn_data().parent; - if cx.resolver.has_derive_copy(container_id) + let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); + let has_derive_copy = cx.resolver.has_derive_copy(container_id); + if has_derive_copy && !params .iter() .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) @@ -148,11 +149,7 @@ fn cs_clone_shallow( } _ => cx.span_bug( trait_span, - &format!( - "unexpected substructure in \ - shallow `derive({})`", - name - ), + &format!("unexpected substructure in shallow `derive({})`", name), ), } } diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index 01a57bea14..c5f3a9d337 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -124,12 +124,7 @@ pub fn expand_deriving_rustc_encodable( explicit_self: borrowed_explicit_self(), args: vec![( Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - // FIXME: we could use `sym::s` here, but making `s` a static - // symbol changes the symbol index ordering in a way that makes - // ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs - // fail. The linting code should be fixed so that its output - // does not depend on the symbol index ordering. - Symbol::intern("s"), + sym::s, )], ret_ty: Literal(Path::new_( pathvec_std!(result::Result), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index a3decff3ae..417dedab60 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -410,7 +410,7 @@ impl<'a> TraitDef<'a> { .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })), _ => unreachable!(), }; - let container_id = cx.current_expansion.id.expn_data().parent; + let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id); let use_temporaries = is_packed && always_copy; diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 6b7d0e1f20..00d75be439 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -72,13 +72,9 @@ impl Path { ) -> ast::Path { let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect(); let lt = mk_lifetimes(cx, span, &self.lifetime); - let tys: Vec> = - self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); - let params = lt - .into_iter() - .map(GenericArg::Lifetime) - .chain(tys.into_iter().map(GenericArg::Type)) - .collect(); + let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)); + let params = + lt.into_iter().map(GenericArg::Lifetime).chain(tys.map(GenericArg::Type)).collect(); match self.kind { PathKind::Global => cx.path_all(span, true, idents, params), diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 7e88b58c0e..00f2f37146 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -939,6 +939,7 @@ pub fn expand_preparsed_format_args( 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 (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)); @@ -989,7 +990,19 @@ pub fn expand_preparsed_format_args( if !parser.errors.is_empty() { let err = parser.errors.remove(0); - let sp = fmt_span.from_inner(err.span); + let sp = if efmt_kind_is_lit { + fmt_span.from_inner(err.span) + } else { + // The format string could be another macro invocation, e.g.: + // format!(concat!("abc", "{}"), 4); + // However, `err.span` is an inner span relative to the *result* of + // the macro invocation, which is why we would get a nonsensical + // result calling `fmt_span.from_inner(err.span)` as above, and + // might even end up inside a multibyte character (issue #86085). + // Therefore, we conservatively report the error for the entire + // argument span here. + fmt_span + }; let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description)); e.span_label(sp, err.label + " in format string"); if let Some(note) = err.note { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 2393e0b9eb..ba27f10330 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -19,7 +19,6 @@ use crate::deriving::*; use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; -use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::sym; mod asm; @@ -113,8 +112,5 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { } let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); - register( - sym::quote, - SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client, krate: LOCAL_CRATE })), - ); + register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }))); } diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 71bbae1161..f83329ecba 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -5,7 +5,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; use rustc_ast_pretty::pprust; -use rustc_expand::base::{ExtCtxt, ResolverExpand}; +use rustc_expand::base::{parse_macro_name_and_helper_attrs, ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_session::Session; use rustc_span::hygiene::AstPass; @@ -109,86 +109,17 @@ impl<'a> CollectProcMacros<'a> { } fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) { - // Once we've located the `#[proc_macro_derive]` attribute, verify - // that it's of the form `#[proc_macro_derive(Foo)]` or - // `#[proc_macro_derive(Foo, attributes(A, ..))]` - let list = match attr.meta_item_list() { - Some(list) => list, - None => return, - }; - if list.len() != 1 && list.len() != 2 { - self.handler.span_err(attr.span, "attribute must have either one or two arguments"); - return; - } - let trait_attr = match list[0].meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(list[0].span(), "not a meta item"); - return; - } - }; - let trait_ident = match trait_attr.ident() { - Some(trait_ident) if trait_attr.is_word() => trait_ident, - _ => { - self.handler.span_err(trait_attr.span, "must only be one word"); - return; - } - }; - - if !trait_ident.name.can_be_raw() { - self.handler.span_err( - trait_attr.span, - &format!("`{}` cannot be a name of derive macro", trait_ident), - ); - } - - let attributes_attr = list.get(1); - let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { - if !attr.has_name(sym::attributes) { - self.handler.span_err(attr.span(), "second argument must be `attributes`") - } - attr.meta_item_list() - .unwrap_or_else(|| { - self.handler - .span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`"); - &[] - }) - .iter() - .filter_map(|attr| { - let attr = match attr.meta_item() { - Some(meta_item) => meta_item, - _ => { - self.handler.span_err(attr.span(), "not a meta item"); - return None; - } - }; - - let ident = match attr.ident() { - Some(ident) if attr.is_word() => ident, - _ => { - self.handler.span_err(attr.span, "must only be one word"); - return None; - } - }; - if !ident.name.can_be_raw() { - self.handler.span_err( - attr.span, - &format!("`{}` cannot be a name of derive helper attribute", ident), - ); - } - - Some(ident.name) - }) - .collect() - } else { - Vec::new() - }; + let (trait_name, proc_attrs) = + match parse_macro_name_and_helper_attrs(self.handler, attr, "derive") { + Some(name_and_attrs) => name_and_attrs, + None => return, + }; if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Derive(ProcMacroDerive { id: item.id, span: item.span, - trait_name: trait_ident.name, + trait_name, function_name: item.ident, attrs: proc_attrs, })); @@ -373,7 +304,7 @@ fn mk_decls( &[sym::rustc_attrs, sym::proc_macro_internals], None, ); - let span = DUMMY_SP.with_def_site_ctxt(expn_id); + let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); let proc_macro = Ident::new(sym::proc_macro, span); let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None)); diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index ccb9f15b0f..1ea2c8843d 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -159,7 +159,7 @@ pub fn expand_include<'cx>( } } - Box::new(ExpandResult { p, node_id: cx.resolver.lint_node_id(cx.current_expansion.id) }) + Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id }) } // include_str! : read the given file, insert it as a literal string expr diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index fbd8be22a9..e0d5726752 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -34,8 +34,8 @@ pub fn inject( &[sym::prelude_import], None, ); - let span = DUMMY_SP.with_def_site_ctxt(expn_id); - let call_site = DUMMY_SP.with_call_site_ctxt(expn_id); + let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); + let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id()); let ecfg = ExpansionConfig::default("std_lib_injection".to_string()); let cx = ExtCtxt::new(sess, ecfg, resolver, None); diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index c8a7ff67b4..74a97a4058 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -126,7 +126,8 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { for test in &mut tests { // See the comment on `mk_main` for why we're using // `apply_mark` directly. - test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque); + test.ident.span = + test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque); } self.cx.test_cases.extend(tests); } @@ -223,7 +224,7 @@ fn generate_test_harness( &[sym::test, sym::rustc_attrs], None, ); - let def_site = DUMMY_SP.with_def_site_ctxt(expn_id); + let def_site = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); // Remove the entry points let mut cleaner = EntryPointCleaner { sess, depth: 0, def_site }; diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml index e173df423a..61da6a2491 100644 --- a/compiler/rustc_codegen_cranelift/.cirrus.yml +++ b/compiler/rustc_codegen_cranelift/.cirrus.yml @@ -14,7 +14,7 @@ task: - . $HOME/.cargo/env - git config --global user.email "user@example.com" - git config --global user.name "User" - - ./prepare.sh + - ./y.rs prepare test_script: - . $HOME/.cargo/env - # Enable backtraces for easier debugging diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 4d45e36c95..f81ac87726 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -19,6 +19,9 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-pc-windows-gnu + - os: ubuntu-latest + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu steps: - uses: actions/checkout@v2 @@ -49,11 +52,19 @@ jobs: sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable rustup target add x86_64-pc-windows-gnu + - name: Install AArch64 toolchain and qemu + if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu' + run: | + sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user + - name: Prepare dependencies run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.rs prepare + + - name: Build + run: ./y.rs build --sysroot none - name: Test env: @@ -87,3 +98,63 @@ jobs: with: name: cg_clif-${{ runner.os }}-cross-x86_64-mingw path: cg_clif.tar.xz + + build_windows: + runs-on: windows-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v2 + + #- name: Cache cargo installed crates + # uses: actions/cache@v2 + # with: + # path: ~/.cargo/bin + # key: ${{ runner.os }}-cargo-installed-crates + + #- name: Cache cargo registry and index + # uses: actions/cache@v2 + # with: + # path: | + # ~/.cargo/registry + # ~/.cargo/git + # key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} + + #- name: Cache cargo target dir + # uses: actions/cache@v2 + # with: + # path: target + # key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + 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 + #name: Test + run: | + # Enable backtraces for easier debugging + #export RUST_BACKTRACE=1 + + # Reduce amount of benchmark runs as they are slow + #export COMPILE_RUNS=2 + #export RUN_RUNS=2 + + # Enable extra checks + #export CG_CLIF_ENABLE_VERIFIER=1 + + ./y.exe build + + #- name: Package prebuilt cg_clif + # run: tar cvfJ cg_clif.tar.xz build + + #- name: Upload prebuilt cg_clif + # uses: actions/upload-artifact@v2 + # with: + # name: cg_clif-${{ runner.os }} + # path: cg_clif.tar.xz diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml index e01a92598b..1c08e5ece3 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml @@ -34,7 +34,7 @@ jobs: run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.rs prepare - name: Test run: | @@ -72,7 +72,7 @@ jobs: run: | git config --global user.email "user@example.com" git config --global user.name "User" - ./prepare.sh + ./y.rs prepare - name: Test run: | diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json index 9009a532c5..f62e59cefc 100644 --- a/compiler/rustc_codegen_cranelift/.vscode/settings.json +++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json @@ -1,7 +1,9 @@ { // source for rustc_* is not included in the rust-src component; disable the errors about this "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"], - "rust-analyzer.assist.importMergeBehavior": "last", + "rust-analyzer.assist.importGranularity": "module", + "rust-analyzer.assist.importEnforceGranularity": true, + "rust-analyzer.assist.importPrefix": "crate", "rust-analyzer.cargo.runBuildScripts": true, "rust-analyzer.linkedProjects": [ "./Cargo.toml", @@ -49,6 +51,23 @@ "cfg": [], }, ] + }, + { + "roots": ["./y.rs"], + "crates": [ + { + "root_module": "./y.rs", + "edition": "2018", + "deps": [{ "crate": 1, "name": "std" }], + "cfg": [], + }, + { + "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs", + "edition": "2018", + "deps": [], + "cfg": [], + }, + ] } ] } diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index a6f5925149..56d0974b25 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -33,16 +33,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -57,8 +57,8 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -66,18 +66,18 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" [[package]] name = "cranelift-entity" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" [[package]] name = "cranelift-frontend" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen", "log", @@ -87,8 +87,8 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -104,8 +104,8 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -115,17 +115,18 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "cranelift-codegen", + "libc", "target-lexicon", ] [[package]] name = "cranelift-object" -version = "0.74.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600" +version = "0.75.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8" dependencies = [ "anyhow", "cranelift-codegen", @@ -171,9 +172,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" [[package]] name = "libloading" @@ -203,14 +204,21 @@ dependencies = [ "libc", ] +[[package]] +name = "memchr" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" + [[package]] name = "object" -version = "0.24.0" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" +checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" dependencies = [ "crc32fast", "indexmap", + "memchr", ] [[package]] diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index fd149af454..ef68d7ee53 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind"] } +cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind", "all-arch"] } cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } @@ -17,7 +17,7 @@ cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", bran cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" } target-lexicon = "0.12.0" gimli = { version = "0.24.0", default-features = false, features = ["write"]} -object = { version = "0.24.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.25.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.0.2" diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 08f9373be6..dad8ed90b5 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -10,8 +10,8 @@ If not please open an issue. ```bash $ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git $ cd rustc_codegen_cranelift -$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking -$ ./build.sh +$ ./y.rs prepare # download and patch sysroot src and install hyperfine for benchmarking +$ ./y.rs build ``` To run the test suite replace the last command with: @@ -20,7 +20,7 @@ To run the test suite replace the last command with: $ ./test.sh ``` -This will implicitly build cg_clif too. Both `build.sh` and `test.sh` accept a `--debug` argument to +This will implicitly build cg_clif too. Both `y.rs build` and `test.sh` accept a `--debug` argument to build in debug mode. Alternatively you can download a pre built version from [GHA]. It is listed in the artifacts section @@ -32,12 +32,12 @@ of workflow runs. Unfortunately due to GHA restrictions you need to be logged in rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. -Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`). +Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`). In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo.sh build +$ $cg_clif_dir/build/cargo build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. diff --git a/compiler/rustc_codegen_cranelift/build.sh b/compiler/rustc_codegen_cranelift/build.sh deleted file mode 100755 index 76bc188433..0000000000 --- a/compiler/rustc_codegen_cranelift/build.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env bash -set -e - -# Settings -export CHANNEL="release" -build_sysroot="clif" -target_dir='build' -while [[ $# != 0 ]]; do - case $1 in - "--debug") - export CHANNEL="debug" - ;; - "--sysroot") - build_sysroot=$2 - shift - ;; - "--target-dir") - target_dir=$2 - shift - ;; - *) - echo "Unknown flag '$1'" - echo "Usage: ./build.sh [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]" - exit 1 - ;; - esac - shift -done - -# Build cg_clif -unset CARGO_TARGET_DIR -unamestr=$(uname) -if [[ "$unamestr" == 'Linux' || "$unamestr" == "FreeBSD" ]]; then - export RUSTFLAGS='-Clink-arg=-Wl,-rpath=$ORIGIN/../lib '$RUSTFLAGS -elif [[ "$unamestr" == 'Darwin' ]]; then - export RUSTFLAGS='-Csplit-debuginfo=unpacked -Clink-arg=-Wl,-rpath,@loader_path/../lib -Zosx-rpath-install-name '$RUSTFLAGS - dylib_ext='dylib' -else - echo "Unsupported os $unamestr" - exit 1 -fi -if [[ "$CHANNEL" == "release" ]]; then - cargo build --release -else - cargo build -fi - -source scripts/ext_config.sh - -rm -rf "$target_dir" -mkdir "$target_dir" -mkdir "$target_dir"/bin "$target_dir"/lib -ln target/$CHANNEL/cg_clif{,_build_sysroot} "$target_dir"/bin -ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib -ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir" - -mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" -mkdir -p "$target_dir/lib/rustlib/$HOST_TRIPLE/lib/" -if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then - cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" -fi - -case "$build_sysroot" in - "none") - ;; - "llvm") - cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/" - if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - cp -r $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/lib "$target_dir/lib/rustlib/$HOST_TRIPLE/" - fi - ;; - "clif") - echo "[BUILD] sysroot" - dir=$(pwd) - cd "$target_dir" - time "$dir/build_sysroot/build_sysroot.sh" - if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - time TARGET_TRIPLE="$HOST_TRIPLE" "$dir/build_sysroot/build_sysroot.sh" - fi - cp lib/rustlib/*/lib/libstd-* lib/ - ;; - *) - echo "Unknown sysroot kind \`$build_sysroot\`." - echo "The allowed values are:" - echo " none A sysroot that doesn't contain the standard library" - echo " llvm Copy the sysroot from rustc compiled by cg_llvm" - echo " clif Build a new sysroot using cg_clif" - exit 1 -esac diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index 923deb9aec..46f661107e 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.43" +version = "0.1.46" dependencies = [ "rustc-std-workspace-core", ] @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "compiler_builtins", "libc", @@ -132,9 +132,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" dependencies = [ "rustc-std-workspace-core", ] @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce" +checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh deleted file mode 100755 index 0354304e55..0000000000 --- a/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -# Requires the CHANNEL env var to be set to `debug` or `release.` - -set -e - -source ./config.sh - -dir=$(pwd) - -# Use rustc with cg_clif as hotpluggable backend instead of the custom cg_clif driver so that -# build scripts are still compiled using cg_llvm. -export RUSTC=$dir"/bin/cg_clif_build_sysroot" -export RUSTFLAGS=$RUSTFLAGS" --clif" - -cd "$(dirname "$0")" - -# Cleanup for previous run -# v Clean target dir except for build scripts and incremental cache -rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true - -# We expect the target dir in the default location. Guard against the user changing it. -export CARGO_TARGET_DIR=target - -# Build libs -export RUSTFLAGS="$RUSTFLAGS -Zforce-unstable-if-unmarked -Cpanic=abort" -export __CARGO_DEFAULT_LIB_METADATA="cg_clif" -if [[ "$1" != "--debug" ]]; then - sysroot_channel='release' - # FIXME Enable incremental again once rust-lang/rust#74946 is fixed - CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target "$TARGET_TRIPLE" --release -else - sysroot_channel='debug' - cargo build --target "$TARGET_TRIPLE" -fi - -# Copy files to sysroot -ln "target/$TARGET_TRIPLE/$sysroot_channel/deps/"* "$dir/lib/rustlib/$TARGET_TRIPLE/lib/" -rm "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"*.{rmeta,d} diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh deleted file mode 100755 index 54b7a94750..0000000000 --- a/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -e -cd "$(dirname "$0")" - -SRC_DIR="$(dirname "$(rustup which rustc)")/../lib/rustlib/src/rust/" -DST_DIR="sysroot_src" - -if [ ! -e "$SRC_DIR" ]; then - echo "Please install rust-src component" - exit 1 -fi - -rm -rf $DST_DIR -mkdir -p $DST_DIR/library -cp -a "$SRC_DIR/library" $DST_DIR/ - -pushd $DST_DIR -echo "[GIT] init" -git init -echo "[GIT] add" -git add . -echo "[GIT] commit" -git commit -m "Initial commit" -q -for file in $(ls ../../patches/ | grep -v patcha); do -echo "[GIT] apply" "$file" -git apply ../../patches/"$file" -git add -A -git commit --no-gpg-sign -m "Patch $file" -done -popd - -git clone https://github.com/rust-lang/compiler-builtins.git || echo "rust-lang/compiler-builtins has already been cloned" -pushd compiler-builtins -git checkout -- . -git checkout 0.1.43 -git apply ../../crate_patches/000*-compiler-builtins-*.patch -popd - -echo "Successfully prepared sysroot source for building" diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs new file mode 100644 index 0000000000..1df2bcc454 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs @@ -0,0 +1,40 @@ +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; + +pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf { + let mut cmd = Command::new("cargo"); + cmd.arg("build").arg("--target").arg(host_triple); + + match channel { + "debug" => {} + "release" => { + cmd.arg("--release"); + } + _ => unreachable!(), + } + + if cfg!(unix) { + if cfg!(target_os = "macos") { + cmd.env( + "RUSTFLAGS", + "-Csplit-debuginfo=unpacked \ + -Clink-arg=-Wl,-rpath,@loader_path/../lib \ + -Zosx-rpath-install-name" + .to_string() + + env::var("RUSTFLAGS").as_deref().unwrap_or(""), + ); + } else { + cmd.env( + "RUSTFLAGS", + "-Clink-arg=-Wl,-rpath=$ORIGIN/../lib ".to_string() + + env::var("RUSTFLAGS").as_deref().unwrap_or(""), + ); + } + } + + eprintln!("[BUILD] rustc_codegen_cranelift"); + crate::utils::spawn_and_wait(cmd); + + Path::new("target").join(host_triple).join(channel) +} diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs new file mode 100644 index 0000000000..9fb88c2796 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -0,0 +1,216 @@ +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::{self, Command}; + +use crate::rustc_info::{get_file_name, get_rustc_version}; +use crate::utils::{spawn_and_wait, try_hard_link}; +use crate::SysrootKind; + +pub(crate) fn build_sysroot( + channel: &str, + sysroot_kind: SysrootKind, + target_dir: &Path, + cg_clif_build_dir: PathBuf, + host_triple: &str, + target_triple: &str, +) { + if target_dir.exists() { + fs::remove_dir_all(target_dir).unwrap(); + } + fs::create_dir_all(target_dir.join("bin")).unwrap(); + fs::create_dir_all(target_dir.join("lib")).unwrap(); + + // Copy the backend + for file in ["cg_clif", "cg_clif_build_sysroot"] { + try_hard_link( + cg_clif_build_dir.join(get_file_name(file, "bin")), + target_dir.join("bin").join(get_file_name(file, "bin")), + ); + } + + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib"); + try_hard_link( + cg_clif_build_dir.join(&cg_clif_dylib), + target_dir + .join(if cfg!(windows) { + // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the + // binaries. + "bin" + } else { + "lib" + }) + .join(cg_clif_dylib), + ); + + // Build and copy cargo wrapper + let mut build_cargo_wrapper_cmd = Command::new("rustc"); + build_cargo_wrapper_cmd + .arg("scripts/cargo.rs") + .arg("-o") + .arg(target_dir.join("cargo")) + .arg("-g"); + spawn_and_wait(build_cargo_wrapper_cmd); + + let default_sysroot = crate::rustc_info::get_default_sysroot(); + + let rustlib = target_dir.join("lib").join("rustlib"); + let host_rustlib_lib = rustlib.join(host_triple).join("lib"); + let target_rustlib_lib = rustlib.join(target_triple).join("lib"); + fs::create_dir_all(&host_rustlib_lib).unwrap(); + fs::create_dir_all(&target_rustlib_lib).unwrap(); + + if target_triple == "x86_64-pc-windows-gnu" { + if !default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib").exists() { + eprintln!( + "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \ + to compile a sysroot for it.", + ); + process::exit(1); + } + for file in fs::read_dir( + default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"), + ) + .unwrap() + { + let file = file.unwrap().path(); + if file.extension().map_or(true, |ext| ext.to_str().unwrap() != "o") { + continue; // only copy object files + } + try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap())); + } + } + + match sysroot_kind { + SysrootKind::None => {} // Nothing to do + SysrootKind::Llvm => { + for file in fs::read_dir( + default_sysroot.join("lib").join("rustlib").join(host_triple).join("lib"), + ) + .unwrap() + { + let file = file.unwrap().path(); + let file_name_str = file.file_name().unwrap().to_str().unwrap(); + if file_name_str.contains("rustc_") + || file_name_str.contains("chalk") + || file_name_str.contains("tracing") + || file_name_str.contains("regex") + { + // These are large crates that are part of the rustc-dev component and are not + // necessary to run regular programs. + continue; + } + try_hard_link(&file, host_rustlib_lib.join(file.file_name().unwrap())); + } + + if target_triple != host_triple { + for file in fs::read_dir( + default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"), + ) + .unwrap() + { + let file = file.unwrap().path(); + try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap())); + } + } + } + SysrootKind::Clif => { + build_clif_sysroot_for_triple(channel, target_dir, host_triple, None); + + if host_triple != target_triple { + // When cross-compiling it is often necessary to manually pick the right linker + let linker = if target_triple == "aarch64-unknown-linux-gnu" { + Some("aarch64-linux-gnu-gcc") + } else { + None + }; + build_clif_sysroot_for_triple(channel, target_dir, target_triple, linker); + } + + // Copy std for the host to the lib dir. This is necessary for the jit mode to find + // libstd. + for file in fs::read_dir(host_rustlib_lib).unwrap() { + let file = file.unwrap().path(); + if file.file_name().unwrap().to_str().unwrap().contains("std-") { + try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap())); + } + } + } + } +} + +fn build_clif_sysroot_for_triple( + channel: &str, + target_dir: &Path, + triple: &str, + linker: Option<&str>, +) { + match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) { + Err(e) => { + eprintln!("Failed to get rustc version for patched sysroot source: {}", e); + eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source"); + process::exit(1); + } + Ok(source_version) => { + let rustc_version = get_rustc_version(); + if source_version != rustc_version { + eprintln!("The patched sysroot source is outdated"); + eprintln!("Source version: {}", source_version.trim()); + eprintln!("Rustc version: {}", rustc_version.trim()); + eprintln!("Hint: Try `./y.rs prepare` to update the patched sysroot source"); + process::exit(1); + } + } + } + + let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel); + + if !crate::config::get_bool("keep_sysroot") { + // Cleanup the target dir with the exception of build scripts and the incremental cache + for dir in ["build", "deps", "examples", "native"] { + if build_dir.join(dir).exists() { + fs::remove_dir_all(build_dir.join(dir)).unwrap(); + } + } + } + + // Build sysroot + let mut build_cmd = Command::new("cargo"); + build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot"); + let mut rustflags = "--clif -Zforce-unstable-if-unmarked".to_string(); + if channel == "release" { + build_cmd.arg("--release"); + rustflags.push_str(" -Zmir-opt-level=3"); + } + if let Some(linker) = linker { + use std::fmt::Write; + write!(rustflags, " -Clinker={}", linker).unwrap(); + } + build_cmd.env("RUSTFLAGS", rustflags); + build_cmd.env( + "RUSTC", + env::current_dir().unwrap().join(target_dir).join("bin").join("cg_clif_build_sysroot"), + ); + // FIXME Enable incremental again once rust-lang/rust#74946 is fixed + build_cmd.env("CARGO_INCREMENTAL", "0").env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); + spawn_and_wait(build_cmd); + + // Copy all relevant files to the sysroot + for entry in + fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps")) + .unwrap() + { + let entry = entry.unwrap(); + if let Some(ext) = entry.path().extension() { + if ext == "rmeta" || ext == "d" || ext == "dSYM" { + continue; + } + } else { + continue; + }; + try_hard_link( + entry.path(), + target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()), + ); + } +} diff --git a/compiler/rustc_codegen_cranelift/build_system/config.rs b/compiler/rustc_codegen_cranelift/build_system/config.rs new file mode 100644 index 0000000000..ef540cf1f8 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/config.rs @@ -0,0 +1,55 @@ +use std::{fs, process}; + +fn load_config_file() -> Vec<(String, Option)> { + fs::read_to_string("config.txt") + .unwrap() + .lines() + .map(|line| if let Some((line, _comment)) = line.split_once('#') { line } else { line }) + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + .map(|line| { + if let Some((key, val)) = line.split_once('=') { + (key.trim().to_owned(), Some(val.trim().to_owned())) + } else { + (line.to_owned(), None) + } + }) + .collect() +} + +pub(crate) fn get_bool(name: &str) -> bool { + let values = load_config_file() + .into_iter() + .filter(|(key, _)| key == name) + .map(|(_, val)| val) + .collect::>(); + if values.is_empty() { + false + } else { + if values.iter().any(|val| val.is_some()) { + eprintln!("Boolean config `{}` has a value", name); + process::exit(1); + } + true + } +} + +pub(crate) fn get_value(name: &str) -> Option { + let values = load_config_file() + .into_iter() + .filter(|(key, _)| key == name) + .map(|(_, val)| val) + .collect::>(); + if values.is_empty() { + None + } else if values.len() == 1 { + if values[0].is_none() { + eprintln!("Config `{}` missing value", name); + process::exit(1); + } + values.into_iter().next().unwrap() + } else { + eprintln!("Config `{}` given multiple values: {:?}", name, values); + process::exit(1); + } +} diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs new file mode 100644 index 0000000000..401b8271ab --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -0,0 +1,133 @@ +use std::env; +use std::ffi::OsStr; +use std::ffi::OsString; +use std::fs; +use std::path::Path; +use std::process::Command; + +use crate::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; +use crate::utils::{copy_dir_recursively, spawn_and_wait}; + +pub(crate) fn prepare() { + prepare_sysroot(); + + eprintln!("[INSTALL] hyperfine"); + Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap(); + + clone_repo( + "rand", + "https://github.com/rust-random/rand.git", + "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", + ); + apply_patches("rand", Path::new("rand")); + + clone_repo( + "regex", + "https://github.com/rust-lang/regex.git", + "341f207c1071f7290e3f228c710817c280c8dca1", + ); + + clone_repo( + "simple-raytracer", + "https://github.com/ebobby/simple-raytracer", + "804a7a21b9e673a482797aa289a18ed480e4d813", + ); + + 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"); + spawn_and_wait(build_cmd); + fs::copy( + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), + // FIXME use get_file_name here too once testing is migrated to rust + "simple-raytracer/raytracer_cg_llvm", + ) + .unwrap(); +} + +fn prepare_sysroot() { + let rustc_path = get_rustc_path(); + let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust"); + let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src"); + + assert!(sysroot_src_orig.exists()); + + if sysroot_src.exists() { + fs::remove_dir_all(&sysroot_src).unwrap(); + } + fs::create_dir_all(sysroot_src.join("library")).unwrap(); + eprintln!("[COPY] sysroot src"); + copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library")); + + let rustc_version = get_rustc_version(); + fs::write( + Path::new("build_sysroot").join("rustc_version"), + &rustc_version, + ) + .unwrap(); + + eprintln!("[GIT] init"); + let mut git_init_cmd = Command::new("git"); + git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src); + spawn_and_wait(git_init_cmd); + + let mut git_add_cmd = Command::new("git"); + git_add_cmd.arg("add").arg(".").current_dir(&sysroot_src); + spawn_and_wait(git_add_cmd); + + let mut git_commit_cmd = Command::new("git"); + git_commit_cmd + .arg("commit") + .arg("-m") + .arg("Initial commit") + .arg("-q") + .current_dir(&sysroot_src); + spawn_and_wait(git_commit_cmd); + + apply_patches("sysroot", &sysroot_src); + + clone_repo( + "build_sysroot/compiler-builtins", + "https://github.com/rust-lang/compiler-builtins.git", + "0.1.46", + ); + apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins")); +} + +fn clone_repo(target_dir: &str, 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(); + + let mut clean_cmd = Command::new("git"); + clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_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); + spawn_and_wait(checkout_cmd); +} + +fn get_patches(crate_name: &str) -> Vec { + let mut patches: Vec<_> = fs::read_dir("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) + }) + .collect(); + patches.sort(); + patches +} + +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); + let mut apply_patch_cmd = Command::new("git"); + apply_patch_cmd.arg("am").arg(patch_arg).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 new file mode 100644 index 0000000000..9206bb02bd --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs @@ -0,0 +1,65 @@ +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; + +pub(crate) fn get_rustc_version() -> String { + let version_info = + Command::new("rustc").stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout; + String::from_utf8(version_info).unwrap() +} + +pub(crate) fn get_host_triple() -> String { + let version_info = + Command::new("rustc").stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout; + String::from_utf8(version_info) + .unwrap() + .lines() + .to_owned() + .find(|line| line.starts_with("host")) + .unwrap() + .split(":") + .nth(1) + .unwrap() + .trim() + .to_owned() +} + +pub(crate) fn get_rustc_path() -> PathBuf { + let rustc_path = Command::new("rustup") + .stderr(Stdio::inherit()) + .args(&["which", "rustc"]) + .output() + .unwrap() + .stdout; + Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned() +} + +pub(crate) fn get_default_sysroot() -> PathBuf { + let default_sysroot = Command::new("rustc") + .stderr(Stdio::inherit()) + .args(&["--print", "sysroot"]) + .output() + .unwrap() + .stdout; + Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned() +} + +pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { + let file_name = Command::new("rustc") + .stderr(Stdio::inherit()) + .args(&[ + "--crate-name", + crate_name, + "--crate-type", + crate_type, + "--print", + "file-names", + "-", + ]) + .output() + .unwrap() + .stdout; + let file_name = String::from_utf8(file_name).unwrap().trim().to_owned(); + assert!(!file_name.contains('\n')); + assert!(file_name.contains(crate_name)); + file_name +} diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs new file mode 100644 index 0000000000..12b5d70fad --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs @@ -0,0 +1,35 @@ +use std::fs; +use std::path::Path; +use std::process::{self, Command}; + +#[track_caller] +pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { + let src = src.as_ref(); + let dst = dst.as_ref(); + if let Err(_) = fs::hard_link(src, dst) { + fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed + } +} + +#[track_caller] +pub(crate) fn spawn_and_wait(mut cmd: Command) { + if !cmd.spawn().unwrap().wait().unwrap().success() { + process::exit(1); + } +} + +pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { + for entry in fs::read_dir(from).unwrap() { + let entry = entry.unwrap(); + let filename = entry.file_name(); + if filename == "." || filename == ".." { + continue; + } + if entry.metadata().unwrap().is_dir() { + fs::create_dir(to.join(&filename)).unwrap(); + copy_dir_recursively(&from.join(&filename), &to.join(&filename)); + } else { + fs::copy(from.join(&filename), to.join(&filename)).unwrap(); + } + } +} diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh index a7bbeb05ca..f4f8c82d69 100755 --- a/compiler/rustc_codegen_cranelift/clean_all.sh +++ b/compiler/rustc_codegen_cranelift/clean_all.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash set -e -rm -rf target/ build/ build_sysroot/{sysroot_src/,target/,compiler-builtins/} perf.data{,.old} +rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} +rm -rf target/ build/ perf.data{,.old} rm -rf rand/ regex/ simple-raytracer/ diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt new file mode 100644 index 0000000000..b14db27d62 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -0,0 +1,17 @@ +# This file allows configuring the build system. + +# Which triple to produce a compiler toolchain for. +# +# Defaults to the default triple of rustc on the host system. +#host = x86_64-unknown-linux-gnu + +# Which triple to build libraries (core/alloc/std/test/proc_macro) for. +# +# Defaults to `host`. +#target = x86_64-unknown-linux-gnu + +# Disables cleaning of the sysroot dir. This will cause old compiled artifacts to be re-used when +# the sysroot source hasn't changed. This is useful when the codegen backend hasn't been modified. +# This option can be changed while the build system is already running for as long as sysroot +# building hasn't started yet. +#keep_sysroot diff --git a/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md index 3eee3b554e..956d5905a9 100644 --- a/compiler/rustc_codegen_cranelift/docs/usage.md +++ b/compiler/rustc_codegen_cranelift/docs/usage.md @@ -2,14 +2,14 @@ rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. -Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`). +Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`). ## Cargo In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo.sh build +$ $cg_clif_dir/build/cargo build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. @@ -30,7 +30,7 @@ In jit mode cg_clif will immediately execute your code without creating an execu > The jit mode will probably need cargo integration to make this possible. ```bash -$ $cg_clif_dir/build/cargo.sh jit +$ $cg_clif_dir/build/cargo jit ``` or @@ -40,11 +40,10 @@ $ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate. ``` There is also an experimental lazy jit mode. In this mode functions are only compiled once they are -first called. It currently does not work with multi-threaded programs. When a not yet compiled -function is called from another thread than the main thread, you will get an ICE. +first called. ```bash -$ $cg_clif_dir/build/cargo.sh lazy-jit +$ $cg_clif_dir/build/cargo lazy-jit ``` ## Shell 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 6570f2bf9f..d997ce6d1b 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -292,7 +292,7 @@ fn main() { #[cfg(not(any(jit, windows)))] test_tls(); - #[cfg(all(not(jit), target_os = "linux"))] + #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] unsafe { global_asm_test(); } @@ -303,12 +303,12 @@ fn main() { assert_eq!(*REF1, *REF2); } -#[cfg(all(not(jit), target_os = "linux"))] +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] extern "C" { fn global_asm_test(); } -#[cfg(all(not(jit), target_os = "linux"))] +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] global_asm! { " .global global_asm_test diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index 7d608df925..5bc51a541b 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -15,8 +15,6 @@ fn main() { let stderr = ::std::io::stderr(); let mut stderr = stderr.lock(); - // FIXME support lazy jit when multi threading - #[cfg(not(lazy_jit))] std::thread::spawn(move || { println!("Hello from another thread!"); }); diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch rename to compiler/rustc_codegen_cranelift/patches/0001-compiler-builtins-Disable-128bit-atomic-operations.patch diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch b/compiler/rustc_codegen_cranelift/patches/0001-rand-Enable-c2-chacha-simd-feature.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/crate_patches/0001-rand-Enable-c2-chacha-simd-feature.patch rename to compiler/rustc_codegen_cranelift/patches/0001-rand-Enable-c2-chacha-simd-feature.patch diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0002-rand-Disable-failing-test.patch b/compiler/rustc_codegen_cranelift/patches/0002-rand-Disable-failing-test.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/crate_patches/0002-rand-Disable-failing-test.patch rename to compiler/rustc_codegen_cranelift/patches/0002-rand-Disable-failing-test.patch diff --git a/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch rename to compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch diff --git a/compiler/rustc_codegen_cranelift/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/patches/0023-core-Ignore-failing-tests.patch rename to compiler/rustc_codegen_cranelift/patches/0023-sysroot-Ignore-failing-tests.patch diff --git a/compiler/rustc_codegen_cranelift/patches/0027-Disable-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch similarity index 100% rename from compiler/rustc_codegen_cranelift/patches/0027-Disable-128bit-atomic-operations.patch rename to compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch diff --git a/compiler/rustc_codegen_cranelift/prepare.sh b/compiler/rustc_codegen_cranelift/prepare.sh deleted file mode 100755 index 64c097261c..0000000000 --- a/compiler/rustc_codegen_cranelift/prepare.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -set -e - -./build_sysroot/prepare_sysroot_src.sh -cargo install hyperfine || echo "Skipping hyperfine install" - -git clone https://github.com/rust-random/rand.git || echo "rust-random/rand has already been cloned" -pushd rand -git checkout -- . -git checkout 0f933f9c7176e53b2a3c7952ded484e1783f0bf1 -git am ../crate_patches/*-rand-*.patch -popd - -git clone https://github.com/rust-lang/regex.git || echo "rust-lang/regex has already been cloned" -pushd regex -git checkout -- . -git checkout 341f207c1071f7290e3f228c710817c280c8dca1 -popd - -git clone https://github.com/ebobby/simple-raytracer || echo "ebobby/simple-raytracer has already been cloned" -pushd simple-raytracer -git checkout -- . -git checkout 804a7a21b9e673a482797aa289a18ed480e4d813 - -# build with cg_llvm for perf comparison -unset CARGO_TARGET_DIR -cargo build -mv target/debug/main raytracer_cg_llvm -popd diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 9fe6e093a7..f806f7bdcd 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-05-26" +channel = "nightly-2021-07-07" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.rs b/compiler/rustc_codegen_cranelift/scripts/cargo.rs new file mode 100644 index 0000000000..b7e8dd4497 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/scripts/cargo.rs @@ -0,0 +1,70 @@ +use std::env; +#[cfg(unix)] +use std::os::unix::process::CommandExt; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + if env::var("RUSTC_WRAPPER").map_or(false, |wrapper| wrapper.contains("sccache")) { + eprintln!( + "\x1b[1;93m=== Warning: Unsetting RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m" + ); + env::remove_var("RUSTC_WRAPPER"); + } + + let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + + env::set_var("RUSTC", sysroot.join("bin/cg_clif".to_string() + env::consts::EXE_SUFFIX)); + + let mut rustdoc_flags = env::var("RUSTDOCFLAGS").unwrap_or(String::new()); + rustdoc_flags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend="); + rustdoc_flags.push_str( + sysroot + .join(if cfg!(windows) { "bin" } else { "lib" }) + .join( + env::consts::DLL_PREFIX.to_string() + + "rustc_codegen_cranelift" + + env::consts::DLL_SUFFIX, + ) + .to_str() + .unwrap(), + ); + rustdoc_flags.push_str(" --sysroot "); + rustdoc_flags.push_str(sysroot.to_str().unwrap()); + env::set_var("RUSTDOCFLAGS", rustdoc_flags); + + // Ensure that the right toolchain is used + env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN")); + + let args: Vec<_> = match env::args().nth(1).as_deref() { + Some("jit") => { + env::set_var( + "RUSTFLAGS", + env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", + ); + std::array::IntoIter::new(["rustc".to_string()]) + .chain(env::args().skip(2)) + .chain(["--".to_string(), "-Cllvm-args=mode=jit".to_string()]) + .collect() + } + Some("lazy-jit") => { + env::set_var( + "RUSTFLAGS", + env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", + ); + std::array::IntoIter::new(["rustc".to_string()]) + .chain(env::args().skip(2)) + .chain(["--".to_string(), "-Cllvm-args=mode=jit-lazy".to_string()]) + .collect() + } + _ => env::args().skip(1).collect(), + }; + + #[cfg(unix)] + Command::new("cargo").args(args).exec(); + + #[cfg(not(unix))] + std::process::exit( + Command::new("cargo").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1), + ); +} diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.sh b/compiler/rustc_codegen_cranelift/scripts/cargo.sh deleted file mode 100755 index 1daa5a78f7..0000000000 --- a/compiler/rustc_codegen_cranelift/scripts/cargo.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash - -dir=$(dirname "$0") -source "$dir/config.sh" - -# read nightly compiler from rust-toolchain file -TOOLCHAIN=$(cat "$dir/rust-toolchain" | grep channel | sed "s/channel = \"\(.*\)\"/\1/") - -cmd=$1 -shift || true - -if [[ "$cmd" = "jit" ]]; then -cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit -Cprefer-dynamic -elif [[ "$cmd" = "lazy-jit" ]]; then -cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit-lazy -Cprefer-dynamic -else -cargo "+${TOOLCHAIN}" "$cmd" "$@" -fi diff --git a/compiler/rustc_codegen_cranelift/scripts/config.sh b/compiler/rustc_codegen_cranelift/scripts/config.sh index 99b302ee1d..53ada369b0 100644 --- a/compiler/rustc_codegen_cranelift/scripts/config.sh +++ b/compiler/rustc_codegen_cranelift/scripts/config.sh @@ -2,26 +2,5 @@ set -e -dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -) - -if echo "$RUSTC_WRAPPER" | grep sccache; then -echo -echo -e "\x1b[1;93m=== Warning: Unset RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m" -echo -export RUSTC_WRAPPER= -fi - -dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd) - -export RUSTC=$dir"/bin/cg_clif" - -export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\ -'-Zcodegen-backend='$dir'/lib/'$dylib' --sysroot '$dir - -# FIXME fix `#[linkage = "extern_weak"]` without this -if [[ "$(uname)" == 'Darwin' ]]; then - export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" -fi - -export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:"$dir"/lib" -export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH +export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH" +export DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH" diff --git a/compiler/rustc_codegen_cranelift/scripts/ext_config.sh b/compiler/rustc_codegen_cranelift/scripts/ext_config.sh index 3f98d77d76..11d6c4c831 100644 --- a/compiler/rustc_codegen_cranelift/scripts/ext_config.sh +++ b/compiler/rustc_codegen_cranelift/scripts/ext_config.sh @@ -1,6 +1,6 @@ # Note to people running shellcheck: this file should only be sourced, not executed directly. -# Various env vars that should only be set for the build system but not for cargo.sh +# Various env vars that should only be set for the build system set -e @@ -25,3 +25,8 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then echo "Unknown non-native platform" fi fi + +# FIXME fix `#[linkage = "extern_weak"]` without this +if [[ "$(uname)" == 'Darwin' ]]; then + export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" +fi diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs index 15388926ec..9e196afbe4 100755 --- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs +++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs @@ -2,9 +2,10 @@ #![forbid(unsafe_code)]/* This line is ignored by bash # This block is ignored by rustc pushd $(dirname "$0")/../ -source build/config.sh +source scripts/config.sh +RUSTC="$(pwd)/build/bin/cg_clif" popd -PROFILE=$1 OUTPUT=$2 exec $RUSTC $RUSTFLAGS -Cllvm-args=mode=jit -Cprefer-dynamic $0 +PROFILE=$1 OUTPUT=$2 exec $RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic $0 #*/ //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index fa7557653d..cc34c08088 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -17,7 +17,7 @@ case $1 in done ./clean_all.sh - ./prepare.sh + ./y.rs prepare (cd build_sysroot && cargo update) diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index 43c4887669..52adaaa8de 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -1,8 +1,8 @@ #!/bin/bash set -e -./build.sh -source build/config.sh +./y.rs build +source scripts/config.sh echo "[SETUP] Rust fork" git clone https://github.com/rust-lang/rust.git || true @@ -33,7 +33,7 @@ index d95b5b7f17f..00b6f0e3635 100644 [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "0.1.43", features = ['rustc-dep-of-std', 'no-asm'] } ++compiler_builtins = { version = "0.1.45", features = ['rustc-dep-of-std', 'no-asm'] } [dev-dependencies] rand = "0.7" diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 347fb40e6f..2f5c2cf737 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -38,7 +38,8 @@ rm src/test/ui/threads-sendsync/task-stderr.rs rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs rm src/test/ui/drop/drop-trait-enum.rs rm src/test/ui/numbers-arithmetic/issue-8460.rs -rm src/test/incremental/change_crate_dep_kind.rs # requires -Cpanic=unwind +rm src/test/ui/rt-explody-panic-payloads.rs +rm src/test/incremental/change_crate_dep_kind.rs rm src/test/ui/issues/issue-28950.rs # depends on stack size optimizations rm src/test/ui/init-large-type.rs # same @@ -64,6 +65,7 @@ rm src/test/incremental/lto.rs # requires lto rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/ rm -r src/test/run-make/unstable-flag-required # same +rm -r src/test/run-make/emit-named-files # requires full --emit support rm src/test/pretty/asm.rs # inline asm rm src/test/pretty/raw-str-nonexpr.rs # same diff --git a/compiler/rustc_codegen_cranelift/scripts/tests.sh b/compiler/rustc_codegen_cranelift/scripts/tests.sh index 0d99d2c507..5df04c533a 100755 --- a/compiler/rustc_codegen_cranelift/scripts/tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/tests.sh @@ -2,9 +2,10 @@ set -e -source build/config.sh +source scripts/config.sh source scripts/ext_config.sh -MY_RUSTC="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2" +export RUSTC=false # ensure that cg_llvm isn't accidentally used +MY_RUSTC="$(pwd)/build/bin/cg_clif $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2" function no_sysroot_tests() { echo "[BUILD] mini_core" @@ -46,7 +47,7 @@ function base_sysroot_tests() { $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" echo "[JIT-lazy] std_example" - $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --cfg lazy_jit --target "$HOST_TRIPLE" + $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" else echo "[JIT] std_example (skipped)" fi @@ -75,63 +76,64 @@ function base_sysroot_tests() { function extended_sysroot_tests() { pushd rand - cargo clean + ../build/cargo clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-random/rand" - ../build/cargo.sh test --workspace + ../build/cargo test --workspace else echo "[AOT] rust-random/rand" - ../build/cargo.sh build --workspace --target $TARGET_TRIPLE --tests + ../build/cargo build --workspace --target $TARGET_TRIPLE --tests fi popd pushd simple-raytracer if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[BENCH COMPILE] ebobby/simple-raytracer" - hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \ + hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo clean" \ "RUSTC=rustc RUSTFLAGS='' cargo build" \ - "../build/cargo.sh build" + "../build/cargo build" echo "[BENCH RUN] ebobby/simple-raytracer" cp ./target/debug/main ./raytracer_cg_clif hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif else + ../build/cargo clean echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[COMPILE] ebobby/simple-raytracer" - ../build/cargo.sh build --target $TARGET_TRIPLE + ../build/cargo build --target $TARGET_TRIPLE echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" fi popd pushd build_sysroot/sysroot_src/library/core/tests echo "[TEST] libcore" - cargo clean + ../../../../../build/cargo clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../../../../../build/cargo.sh test + ../../../../../build/cargo test else - ../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests + ../../../../../build/cargo build --target $TARGET_TRIPLE --tests fi popd pushd regex echo "[TEST] rust-lang/regex example shootout-regex-dna" - cargo clean + ../build/cargo clean export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning # Make sure `[codegen mono items] start` doesn't poison the diff - ../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE + ../build/cargo build --example shootout-regex-dna --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then cat examples/regexdna-input.txt \ - | ../build/cargo.sh run --example shootout-regex-dna --target $TARGET_TRIPLE \ + | ../build/cargo run --example shootout-regex-dna --target $TARGET_TRIPLE \ | grep -v "Spawned thread" > res.txt diff -u res.txt examples/regexdna-output.txt fi if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-lang/regex tests" - ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + ../build/cargo test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q else echo "[AOT] rust-lang/regex tests" - ../build/cargo.sh build --tests --target $TARGET_TRIPLE + ../build/cargo build --tests --target $TARGET_TRIPLE fi popd } diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 357a9f2daf..d39486c2f1 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -19,7 +19,7 @@ pub(crate) fn codegen( }); if any_dynamic_crate { false - } else if let Some(kind) = tcx.allocator_kind() { + } else if let Some(kind) = tcx.allocator_kind(()) { codegen_inner(module, unwind_context, kind); true } else { diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index ec3e17e5b7..3d78eed77b 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -21,6 +21,11 @@ pub(crate) fn codegen_fn<'tcx>( debug_assert!(!instance.substs.needs_infer()); let mir = tcx.instance_mir(instance.def); + let _mir_guard = crate::PrintOnPanic(|| { + let mut buf = Vec::new(); + rustc_mir::util::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap(); + String::from_utf8_lossy(&buf).into_owned() + }); // Declare function let symbol_name = tcx.symbol_name(instance); @@ -52,7 +57,6 @@ pub(crate) fn codegen_fn<'tcx>( module, tcx, pointer_type, - vtables: FxHashMap::default(), constants_cx: ConstantCx::new(), instance, @@ -105,7 +109,14 @@ pub(crate) fn codegen_fn<'tcx>( let context = &mut cx.cached_context; context.func = func; - crate::pretty_clif::write_clif_file(tcx, "unopt", None, instance, &context, &clif_comments); + crate::pretty_clif::write_clif_file( + tcx, + "unopt", + module.isa(), + instance, + &context, + &clif_comments, + ); // Verify function verify_func(tcx, &clif_comments, &context.func); @@ -122,7 +133,13 @@ pub(crate) fn codegen_fn<'tcx>( // Perform rust specific optimizations tcx.sess.time("optimize clif ir", || { - crate::optimize::optimize_function(tcx, instance, context, &mut clif_comments); + crate::optimize::optimize_function( + tcx, + module.isa(), + instance, + context, + &mut clif_comments, + ); }); // Define function @@ -137,7 +154,7 @@ pub(crate) fn codegen_fn<'tcx>( crate::pretty_clif::write_clif_file( tcx, "opt", - Some(module.isa()), + module.isa(), instance, &context, &clif_comments, diff --git a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs index 983839d48d..a044b43b86 100644 --- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs @@ -1,4 +1,4 @@ -#![feature(rustc_private)] +#![feature(rustc_private, once_cell)] extern crate rustc_data_structures; extern crate rustc_driver; @@ -6,12 +6,33 @@ extern crate rustc_interface; extern crate rustc_session; extern crate rustc_target; +use std::lazy::SyncLazy; +use std::panic; + use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_interface::interface; use rustc_session::config::ErrorOutputType; use rustc_session::early_error; use rustc_target::spec::PanicStrategy; +const BUG_REPORT_URL: &str = "https://github.com/bjorn3/rustc_codegen_cranelift/issues/new"; + +static DEFAULT_HOOK: SyncLazy) + Sync + Send + 'static>> = + SyncLazy::new(|| { + let hook = panic::take_hook(); + panic::set_hook(Box::new(|info| { + // Invoke the default handler, which prints the actual panic message and optionally a backtrace + (*DEFAULT_HOOK)(info); + + // Separate the output with an empty line + eprintln!(); + + // Print the ICE message + rustc_driver::report_ice(info, BUG_REPORT_URL); + })); + hook + }); + #[derive(Default)] pub struct CraneliftPassesCallbacks { time_passes: bool, @@ -37,7 +58,7 @@ fn main() { let start_rss = get_resident_set_size(); rustc_driver::init_rustc_env_logger(); let mut callbacks = CraneliftPassesCallbacks::default(); - rustc_driver::install_ice_hook(); + SyncLazy::force(&DEFAULT_HOOK); // Install ice hook let exit_code = rustc_driver::catch_with_exit_code(|| { let args = std::env::args_os() .enumerate() diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 488ff6e134..892ccf27f6 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -233,7 +233,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) module: &'m mut dyn Module, pub(crate) tcx: TyCtxt<'tcx>, pub(crate) pointer_type: Type, // Cached from module - pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option>), DataId>, pub(crate) constants_cx: ConstantCx, pub(crate) instance: Instance<'tcx>, diff --git a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs index 177f850afb..100c3b4316 100644 --- a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs +++ b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs @@ -7,7 +7,7 @@ macro builtin_functions($register:ident; $(fn $name:ident($($arg_name:ident: $ar #[cfg(feature = "jit")] pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) { - for &(name, val) in &[$((stringify!($name), $name as *const u8)),*] { + for (name, val) in [$((stringify!($name), $name as *const u8)),*] { builder.symbol(name, val); } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 3ba12c4e96..c87309e222 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -1,16 +1,13 @@ //! Handling of `static`s, `const`s and promoted allocations -use rustc_span::DUMMY_SP; - -use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::ErrorReported; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{ - alloc_range, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, - Scalar, + read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar, }; use rustc_middle::ty::ConstKind; +use rustc_span::DUMMY_SP; use cranelift_codegen::ir::GlobalValueData; use cranelift_module::*; @@ -171,66 +168,75 @@ pub(crate) fn codegen_const_value<'tcx>( } match const_val { - ConstValue::Scalar(x) => { - if fx.clif_type(layout.ty).is_none() { - let (size, align) = (layout.size, layout.align.pref); - let mut alloc = Allocation::from_bytes( - std::iter::repeat(0).take(size.bytes_usize()).collect::>(), - align, - Mutability::Not, - ); - alloc.write_scalar(fx, alloc_range(Size::ZERO, size), x.into()).unwrap(); - let alloc = fx.tcx.intern_const_alloc(alloc); - return CValue::by_ref(pointer_for_allocation(fx, alloc), layout); - } - - match x { - Scalar::Int(int) => CValue::const_val(fx, layout, int), - Scalar::Ptr(ptr) => { - let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id); - let base_addr = match alloc_kind { - Some(GlobalAlloc::Memory(alloc)) => { - fx.constants_cx.todo.push(TodoItem::Alloc(ptr.alloc_id)); - let data_id = data_id_for_alloc_id( - &mut fx.constants_cx, - fx.module, - ptr.alloc_id, - alloc.mutability, - ); - 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!("{:?}", ptr.alloc_id)); - } - fx.bcx.ins().global_value(fx.pointer_type, local_data_id) - } - Some(GlobalAlloc::Function(instance)) => { - let func_id = crate::abi::import_function(fx.tcx, fx.module, instance); - let local_func_id = - fx.module.declare_func_in_func(func_id, &mut fx.bcx.func); - fx.bcx.ins().func_addr(fx.pointer_type, local_func_id) - } - Some(GlobalAlloc::Static(def_id)) => { - assert!(fx.tcx.is_static(def_id)); - 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)); - } - fx.bcx.ins().global_value(fx.pointer_type, local_data_id) + ConstValue::Scalar(x) => match x { + Scalar::Int(int) => { + if fx.clif_type(layout.ty).is_some() { + return CValue::const_val(fx, layout, int); + } else { + let raw_val = int.to_bits(int.size()).unwrap(); + let val = match int.size().bytes() { + 1 => fx.bcx.ins().iconst(types::I8, raw_val as i64), + 2 => fx.bcx.ins().iconst(types::I16, raw_val as i64), + 4 => fx.bcx.ins().iconst(types::I32, raw_val as i64), + 8 => fx.bcx.ins().iconst(types::I64, raw_val as i64), + 16 => { + let lsb = fx.bcx.ins().iconst(types::I64, raw_val as u64 as i64); + let msb = + fx.bcx.ins().iconst(types::I64, (raw_val >> 64) as u64 as i64); + fx.bcx.ins().iconcat(lsb, msb) } - None => bug!("missing allocation {:?}", ptr.alloc_id), - }; - let val = if ptr.offset.bytes() != 0 { - fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap()) - } else { - base_addr + _ => unreachable!(), }; - CValue::by_val(val, layout) + + let place = CPlace::new_stack_slot(fx, layout); + place.to_ptr().store(fx, val, MemFlags::trusted()); + place.to_cvalue(fx) } } - } + Scalar::Ptr(ptr, _size) => { + let (alloc_id, offset) = ptr.into_parts(); // we know the `offset` is relative + let alloc_kind = fx.tcx.get_global_alloc(alloc_id); + let base_addr = match alloc_kind { + Some(GlobalAlloc::Memory(alloc)) => { + let data_id = data_id_for_alloc_id( + &mut fx.constants_cx, + fx.module, + alloc_id, + alloc.mutability, + ); + 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!("{:?}", alloc_id)); + } + fx.bcx.ins().global_value(fx.pointer_type, local_data_id) + } + Some(GlobalAlloc::Function(instance)) => { + let func_id = crate::abi::import_function(fx.tcx, fx.module, instance); + let local_func_id = + fx.module.declare_func_in_func(func_id, &mut fx.bcx.func); + fx.bcx.ins().func_addr(fx.pointer_type, local_func_id) + } + Some(GlobalAlloc::Static(def_id)) => { + assert!(fx.tcx.is_static(def_id)); + 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)); + } + fx.bcx.ins().global_value(fx.pointer_type, local_data_id) + } + None => bug!("missing allocation {:?}", alloc_id), + }; + let val = if offset.bytes() != 0 { + fx.bcx.ins().iadd_imm(base_addr, i64::try_from(offset.bytes()).unwrap()) + } else { + base_addr + }; + CValue::by_val(val, layout) + } + }, ConstValue::ByRef { alloc, offset } => CValue::by_ref( pointer_for_allocation(fx, alloc) .offset_i64(fx, i64::try_from(offset.bytes()).unwrap()), @@ -249,12 +255,11 @@ pub(crate) fn codegen_const_value<'tcx>( } } -fn pointer_for_allocation<'tcx>( +pub(crate) fn pointer_for_allocation<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, alloc: &'tcx Allocation, ) -> crate::pointer::Pointer { let alloc_id = fx.tcx.create_memory_alloc(alloc); - fx.constants_cx.todo.push(TodoItem::Alloc(alloc_id)); let data_id = data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, alloc.mutability); @@ -266,12 +271,13 @@ fn pointer_for_allocation<'tcx>( crate::pointer::Pointer::new(global_ptr) } -fn data_id_for_alloc_id( +pub(crate) fn data_id_for_alloc_id( cx: &mut ConstantCx, module: &mut dyn Module, alloc_id: AllocId, mutability: rustc_hir::Mutability, ) -> DataId { + cx.todo.push(TodoItem::Alloc(alloc_id)); *cx.anon_allocs.entry(alloc_id).or_insert_with(|| { module.declare_anonymous_data(mutability == rustc_hir::Mutability::Mut, false).unwrap() }) @@ -352,7 +358,14 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant GlobalAlloc::Memory(alloc) => alloc, GlobalAlloc::Function(_) | GlobalAlloc::Static(_) => unreachable!(), }; - let data_id = data_id_for_alloc_id(cx, module, alloc_id, alloc.mutability); + let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| { + module + .declare_anonymous_data( + alloc.mutability == rustc_hir::Mutability::Mut, + false, + ) + .unwrap() + }); (data_id, alloc, None) } TodoItem::Static(def_id) => { @@ -394,7 +407,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); data_ctx.define(bytes.into_boxed_slice()); - for &(offset, (_tag, reloc)) in alloc.relocations().iter() { + for &(offset, alloc_id) in alloc.relocations().iter() { let addend = { let endianness = tcx.data_layout.endian; let offset = offset.bytes() as usize; @@ -405,7 +418,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant read_target_uint(endianness, bytes).unwrap() }; - let reloc_target_alloc = tcx.get_global_alloc(reloc).unwrap(); + let reloc_target_alloc = tcx.get_global_alloc(alloc_id).unwrap(); let data_id = match reloc_target_alloc { GlobalAlloc::Function(instance) => { assert_eq!(addend, 0); @@ -415,8 +428,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant continue; } GlobalAlloc::Memory(target_alloc) => { - cx.todo.push(TodoItem::Alloc(reloc)); - data_id_for_alloc_id(cx, module, reloc, target_alloc.mutability) + data_id_for_alloc_id(cx, module, alloc_id, target_alloc.mutability) } GlobalAlloc::Static(def_id) => { if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs index 9eb0677063..c7e15f81e0 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs @@ -10,7 +10,7 @@ use rustc_span::{ }; use cranelift_codegen::binemit::CodeOffset; -use cranelift_codegen::machinst::MachSrcLoc; +use cranelift_codegen::MachSrcLoc; use gimli::write::{ Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable, diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 61e54a76f2..c67336eb3f 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -61,9 +61,11 @@ impl<'tcx> DebugContext<'tcx> { let mut dwarf = DwarfUnit::new(encoding); - // FIXME: how to get version when building out of tree? - // Normally this would use option_env!("CFG_VERSION"). - let producer = format!("cg_clif (rustc {})", "unknown version"); + let producer = format!( + "cg_clif (rustc {}, cranelift {})", + rustc_interface::util::version_str().unwrap_or("unknown version"), + cranelift_codegen::VERSION, + ); let comp_dir = tcx.sess.working_dir.to_string_lossy(false).into_owned(); let (name, file_info) = match tcx.sess.local_crate_source_file.clone() { Some(path) => { diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 6676d88602..a8b802f449 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -4,7 +4,6 @@ use std::path::PathBuf; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; -use rustc_codegen_ssa::back::linker::LinkerInfo; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -290,14 +289,16 @@ pub(crate) fn run_aot( None }; + // FIXME handle `-Ctarget-cpu=native` + let target_cpu = + tcx.sess.opts.cg.target_cpu.as_ref().unwrap_or(&tcx.sess.target.cpu).to_owned(); Box::new(( CodegenResults { modules, allocator_module, metadata_module, metadata, - linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()), - crate_info: CrateInfo::new(tcx), + crate_info: CrateInfo::new(tcx, target_cpu), }, work_products, )) diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 4a99cb727c..76fbc9ad51 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -3,11 +3,14 @@ use std::cell::RefCell; use std::ffi::CString; +use std::lazy::{Lazy, SyncOnceCell}; use std::os::raw::{c_char, c_int}; +use std::sync::{mpsc, Mutex}; use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; +use rustc_session::Session; use cranelift_jit::{JITBuilder, JITModule}; @@ -23,12 +26,48 @@ thread_local! { static LAZY_JIT_STATE: RefCell> = RefCell::new(None); } +/// The Sender owned by the rustc thread +static GLOBAL_MESSAGE_SENDER: SyncOnceCell>> = + SyncOnceCell::new(); + +/// A message that is sent from the jitted runtime to the rustc thread. +/// Senders are responsible for upholding `Send` semantics. +enum UnsafeMessage { + /// Request that the specified `Instance` be lazily jitted. + /// + /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after + /// this message is sent. + JitFn { + instance_ptr: *const Instance<'static>, + trampoline_ptr: *const u8, + tx: mpsc::Sender<*const u8>, + }, +} +unsafe impl Send for UnsafeMessage {} + +impl UnsafeMessage { + /// Send the message. + fn send(self) -> Result<(), mpsc::SendError> { + thread_local! { + /// The Sender owned by the local thread + static LOCAL_MESSAGE_SENDER: Lazy> = Lazy::new(|| + GLOBAL_MESSAGE_SENDER + .get().unwrap() + .lock().unwrap() + .clone() + ); + } + LOCAL_MESSAGE_SENDER.with(|sender| sender.send(self)) + } +} + fn create_jit_module<'tcx>( tcx: TyCtxt<'tcx>, backend_config: &BackendConfig, hotswap: bool, ) -> (JITModule, CodegenCx<'tcx>) { - let imported_symbols = load_imported_symbols_for_jit(tcx); + 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()); @@ -116,11 +155,6 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { .chain(backend_config.jit_args.iter().map(|arg| &**arg)) .map(|arg| CString::new(arg).unwrap()) .collect::>(); - let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); - - // Push a null pointer as a terminating argument. This is required by POSIX and - // useful as some dynamic linkers use it as a marker to jump over. - argv.push(std::ptr::null()); let start_sig = Signature { params: vec![ @@ -128,7 +162,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { AbiParam::new(jit_module.target_config().pointer_type()), ], returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)], - call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)), + call_conv: jit_module.target_config().default_call_conv, }; let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap(); let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id); @@ -141,12 +175,51 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { let f: extern "C" fn(c_int, *const *const c_char) -> c_int = unsafe { ::std::mem::transmute(finalized_start) }; - let ret = f(args.len() as c_int, argv.as_ptr()); - std::process::exit(ret); + + let (tx, rx) = mpsc::channel(); + GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap(); + + // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages + // (eg to lazily JIT further functions as required) + std::thread::spawn(move || { + let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); + + // Push a null pointer as a terminating argument. This is required by POSIX and + // useful as some dynamic linkers use it as a marker to jump over. + argv.push(std::ptr::null()); + + let ret = f(args.len() as c_int, argv.as_ptr()); + std::process::exit(ret); + }); + + // Handle messages + loop { + match rx.recv().unwrap() { + // lazy JIT compilation request - compile requested instance and return pointer to result + UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => { + tx.send(jit_fn(instance_ptr, trampoline_ptr)) + .expect("jitted runtime hung up before response to lazy JIT request was sent"); + } + } + } } #[no_mangle] -extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 { +extern "C" fn __clif_jit_fn( + instance_ptr: *const Instance<'static>, + trampoline_ptr: *const u8, +) -> *const u8 { + // send the JIT request to the rustc thread, with a channel for the response + let (tx, rx) = mpsc::channel(); + UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } + .send() + .expect("rustc thread hung up before lazy JIT request was sent"); + + // block on JIT compilation result + rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request") +} + +fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 { rustc_middle::ty::tls::with(|tcx| { // lift is used to ensure the correct lifetime for instance. let instance = tcx.lift(unsafe { *instance_ptr }).unwrap(); @@ -160,6 +233,17 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 let name = tcx.symbol_name(instance).name; let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance); let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap(); + + let current_ptr = jit_module.read_got_entry(func_id); + + // If the function's GOT entry has already been updated to point at something other + // than the shim trampoline, don't re-jit but just return the new pointer instead. + // This does not need synchronization as this code is executed only by a sole rustc + // thread. + if current_ptr != trampoline_ptr { + return current_ptr; + } + jit_module.prepare_for_function_redefine(func_id).unwrap(); let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module.isa(), false); @@ -173,26 +257,27 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 }) } -fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { +fn load_imported_symbols_for_jit( + sess: &Session, + crate_info: CrateInfo, +) -> Vec<(String, *const u8)> { use rustc_middle::middle::dependency_format::Linkage; let mut dylib_paths = Vec::new(); - let crate_info = CrateInfo::new(tcx); - let formats = tcx.dependency_formats(()); - let data = &formats + let data = &crate_info + .dependency_formats .iter() .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) .unwrap() .1; - for &(cnum, _) in &crate_info.used_crates_dynamic { + for &cnum in &crate_info.used_crates { let src = &crate_info.used_crate_source[&cnum]; match data[cnum.as_usize() - 1] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - let name = tcx.crate_name(cnum); - let mut err = - tcx.sess.struct_err(&format!("Can't load static lib {}", name.as_str())); + let name = &crate_info.crate_name[&cnum]; + let mut err = sess.struct_err(&format!("Can't load static lib {}", name.as_str())); err.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); err.emit(); } @@ -232,7 +317,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { std::mem::forget(lib) } - tcx.sess.abort_if_errors(); + sess.abort_if_errors(); imported_symbols } @@ -254,7 +339,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In Linkage::Import, &Signature { call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(pointer_type)], + params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)], returns: vec![AbiParam::new(pointer_type)], }, ) @@ -267,6 +352,7 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In let mut builder_ctx = FunctionBuilderContext::new(); let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx); + let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func); let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func); let sig_ref = trampoline_builder.func.import_signature(sig); @@ -276,7 +362,8 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In trampoline_builder.switch_to_block(entry_block); let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64); - let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr]); + let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn); + let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]); let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0]; let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args); let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec(); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index ba4ed2162c..be3704ca27 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -106,6 +106,26 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout()); dest.write_cvalue(fx, a); }; + "llvm.x86.addcarry.64", (v c_in, c a, c b) { + llvm_add_sub( + fx, + BinOp::Add, + ret, + c_in, + a, + b + ); + }; + "llvm.x86.subborrow.64", (v b_in, c a, c b) { + llvm_add_sub( + fx, + BinOp::Sub, + ret, + b_in, + a, + b + ); + }; } if let Some((_, dest)) = destination { @@ -121,3 +141,41 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( // llvm.x86.avx2.pshuf.b // llvm.x86.avx2.psrli.w // llvm.x86.sse2.psrli.w + +fn llvm_add_sub<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + bin_op: BinOp, + ret: CPlace<'tcx>, + cb_in: Value, + a: CValue<'tcx>, + b: CValue<'tcx>, +) { + assert_eq!( + a.layout().ty, + fx.tcx.types.u64, + "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64" + ); + assert_eq!( + b.layout().ty, + fx.tcx.types.u64, + "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64" + ); + + // c + carry -> c + first intermediate carry or borrow respectively + let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b); + let c = int0.value_field(fx, mir::Field::new(0)); + let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx); + + // c + carry -> c + second intermediate carry or borrow respectively + let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in); + let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64)); + let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64); + let (c, cb1) = int1.load_scalar_pair(fx); + + // carry0 | carry1 -> carry or borrow respectively + let cb_out = fx.bcx.ins().bor(cb0, cb1); + + let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter())); + let val = CValue::by_val_pair(cb_out, c, layout); + ret.write_cvalue(fx, val); +} diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 52896fc712..3979886e10 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1115,6 +1115,40 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( ); ret.write_cvalue(fx, CValue::by_val(res, ret.layout())); }; + + raw_eq, (v lhs_ref, v rhs_ref) { + fn type_by_size(size: Size) -> Option { + Type::int(size.bits().try_into().ok()?) + } + + let size = fx.layout_of(T).layout.size; + let is_eq_value = + if size == Size::ZERO { + // No bytes means they're trivially equal + fx.bcx.ins().iconst(types::I8, 1) + } else if let Some(clty) = type_by_size(size) { + // Can't use `trusted` for these loads; they could be unaligned. + let mut flags = MemFlags::new(); + flags.set_notrap(); + let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); + let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); + let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val); + fx.bcx.ins().bint(types::I8, eq) + } else { + // Just call `memcmp` (like slices do in core) when the + // size is too large or it's not a power-of-two. + let ptr_ty = pointer_ty(fx.tcx); + let signed_bytes = i64::try_from(size.bytes()).unwrap(); + let bytes_val = fx.bcx.ins().iconst(ptr_ty, signed_bytes); + let params = vec![AbiParam::new(ptr_ty); 3]; + let returns = vec![AbiParam::new(types::I32)]; + let args = &[lhs_ref, rhs_ref, bytes_val]; + let cmp = fx.lib_call("memcmp", params, returns, args)[0]; + let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0); + fx.bcx.ins().bint(types::I8, eq) + }; + ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); + }; } if let Some((_, dest)) = destination { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 6aadaf8a7c..e32dae4913 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)] +#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] @@ -14,7 +14,9 @@ extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_incremental; extern crate rustc_index; +extern crate rustc_interface; extern crate rustc_metadata; +extern crate rustc_mir; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; @@ -98,7 +100,7 @@ mod prelude { pub(crate) use cranelift_codegen::isa::{self, CallConv}; pub(crate) use cranelift_codegen::Context; pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; - pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module}; + pub(crate) use cranelift_module::{self, DataContext, FuncId, Linkage, Module}; pub(crate) use crate::abi::*; pub(crate) use crate::base::{codegen_operand, codegen_place}; @@ -219,10 +221,7 @@ impl CodegenBackend for CraneliftCodegenBackend { sess, &codegen_results, outputs, - &codegen_results.crate_info.local_crate_name.as_str(), - ); - - Ok(()) + ) } } @@ -285,10 +284,12 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap(); - // Don't use "haswell" as the default, as it implies `has_lzcnt`. - // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. - builder.enable("nehalem").unwrap(); + cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant).unwrap(); + if target_triple.architecture == target_lexicon::Architecture::X86_64 { + // Don't use "haswell" as the default, as it implies `has_lzcnt`. + // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. + builder.enable("nehalem").unwrap(); + } builder } }; diff --git a/compiler/rustc_codegen_cranelift/src/optimize/mod.rs b/compiler/rustc_codegen_cranelift/src/optimize/mod.rs index 137fb5f773..61033d85a1 100644 --- a/compiler/rustc_codegen_cranelift/src/optimize/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/optimize/mod.rs @@ -1,17 +1,20 @@ //! Various optimizations specific to cg_clif +use cranelift_codegen::isa::TargetIsa; + use crate::prelude::*; pub(crate) mod peephole; pub(crate) fn optimize_function<'tcx>( tcx: TyCtxt<'tcx>, + isa: &dyn TargetIsa, instance: Instance<'tcx>, ctx: &mut Context, clif_comments: &mut crate::pretty_clif::CommentWriter, ) { // FIXME classify optimizations over opt levels once we have more - crate::pretty_clif::write_clif_file(tcx, "preopt", None, instance, &ctx, &*clif_comments); + crate::pretty_clif::write_clif_file(tcx, "preopt", isa, instance, &ctx, &*clif_comments); crate::base::verify_func(tcx, &*clif_comments, &ctx.func); } diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index cd8c5b5160..05db74745a 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -233,7 +233,7 @@ pub(crate) fn write_ir_file( pub(crate) fn write_clif_file<'tcx>( tcx: TyCtxt<'tcx>, postfix: &str, - isa: Option<&dyn cranelift_codegen::isa::TargetIsa>, + isa: &dyn cranelift_codegen::isa::TargetIsa, instance: Instance<'tcx>, context: &cranelift_codegen::Context, mut clif_comments: &CommentWriter, @@ -242,22 +242,23 @@ pub(crate) fn write_clif_file<'tcx>( tcx, || format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix), |file| { - let value_ranges = isa - .map(|isa| context.build_value_labels_ranges(isa).expect("value location ranges")); - let mut clif = String::new(); cranelift_codegen::write::decorate_function( &mut clif_comments, &mut clif, &context.func, - &DisplayFunctionAnnotations { isa, value_ranges: value_ranges.as_ref() }, + &DisplayFunctionAnnotations { isa: Some(isa), value_ranges: None }, ) .unwrap(); - writeln!(file, "test compile")?; - writeln!(file, "set is_pic")?; - writeln!(file, "set enable_simd")?; - writeln!(file, "target {} haswell", crate::target_triple(tcx.sess))?; + for flag in isa.flags().iter() { + writeln!(file, "set {}", flag)?; + } + write!(file, "target {}", isa.triple().architecture.to_string())?; + for isa_flag in isa.isa_flags().iter() { + write!(file, " {}", isa_flag)?; + } + writeln!(file, "\n")?; writeln!(file)?; file.write_all(clif.as_bytes())?; Ok(()) diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 042583cd57..b9d379c611 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -31,9 +31,7 @@ pub(crate) fn unsized_info<'tcx>( // change to the vtable. old_info.expect("unsized_info: missing old info for trait upcast") } - (_, &ty::Dynamic(ref data, ..)) => { - crate::vtable::get_vtable(fx, fx.layout_of(source), data.principal()) - } + (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 171f39805f..ae8ccc626b 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -453,6 +453,10 @@ impl<'tcx> CPlace<'tcx> { ptr.store(fx, data, MemFlags::trusted()); ptr.load(fx, dst_ty, MemFlags::trusted()) } + + // `CValue`s should never contain SSA-only types, so if you ended + // up here having seen an error like `B1 -> I8`, then before + // calling `write_cvalue` you need to add a `bint` instruction. _ => unreachable!("write_cvalue_transmute: {:?} -> {:?}", src_ty, dst_ty), }; //fx.bcx.set_val_label(data, cranelift_codegen::ir::ValueLabel::new(var.index())); diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index bbf07ffc85..4a5f9f133a 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -1,14 +1,10 @@ //! Codegen vtables and vtable accesses. //! //! See `rustc_codegen_ssa/src/meth.rs` for reference. -// FIXME dedup this logic between miri, cg_llvm and cg_clif +use crate::constant::data_id_for_alloc_id; use crate::prelude::*; -const DROP_FN_INDEX: usize = 0; -const SIZE_INDEX: usize = 1; -const ALIGN_INDEX: usize = 2; - fn vtable_memflags() -> MemFlags { let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap. flags.set_readonly(); // A vtable is always read-only. @@ -21,7 +17,7 @@ pub(crate) fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> pointer_ty(fx.tcx), vtable_memflags(), vtable, - (DROP_FN_INDEX * usize_size) as i32, + (ty::COMMON_VTABLE_ENTRIES_DROPINPLACE * usize_size) as i32, ) } @@ -31,7 +27,7 @@ pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Val pointer_ty(fx.tcx), vtable_memflags(), vtable, - (SIZE_INDEX * usize_size) as i32, + (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32, ) } @@ -41,7 +37,7 @@ pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) - pointer_ty(fx.tcx), vtable_memflags(), vtable, - (ALIGN_INDEX * usize_size) as i32, + (ty::COMMON_VTABLE_ENTRIES_ALIGN * usize_size) as i32, ) } @@ -62,105 +58,22 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( pointer_ty(fx.tcx), vtable_memflags(), vtable, - ((idx + 3) * usize_size as usize) as i32, + (idx * usize_size as usize) as i32, ); (ptr, func_ref) } pub(crate) fn get_vtable<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - layout: TyAndLayout<'tcx>, + ty: Ty<'tcx>, trait_ref: Option>, ) -> Value { - let data_id = if let Some(data_id) = fx.vtables.get(&(layout.ty, trait_ref)) { - *data_id - } else { - let data_id = build_vtable(fx, layout, trait_ref); - fx.vtables.insert((layout.ty, trait_ref), data_id); - data_id - }; - + let alloc_id = fx.tcx.vtable_allocation(ty, trait_ref); + let data_id = + data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not); let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); - fx.bcx.ins().global_value(fx.pointer_type, local_data_id) -} - -fn build_vtable<'tcx>( - fx: &mut FunctionCx<'_, '_, 'tcx>, - layout: TyAndLayout<'tcx>, - trait_ref: Option>, -) -> DataId { - let tcx = fx.tcx; - let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; - - let drop_in_place_fn = import_function( - tcx, - fx.module, - Instance::resolve_drop_in_place(tcx, layout.ty).polymorphize(fx.tcx), - ); - - let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None]; - - let methods_root; - let methods = if let Some(trait_ref) = trait_ref { - methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, layout.ty)); - methods_root.iter() - } else { - (&[]).iter() - }; - let methods = methods.cloned().map(|opt_mth| { - opt_mth.map(|(def_id, substs)| { - import_function( - tcx, - fx.module, - Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), def_id, substs) - .unwrap() - .polymorphize(fx.tcx), - ) - }) - }); - components.extend(methods); - - let mut data_ctx = DataContext::new(); - let mut data = ::std::iter::repeat(0u8) - .take(components.len() * usize_size) - .collect::>() - .into_boxed_slice(); - - write_usize(fx.tcx, &mut data, SIZE_INDEX, layout.size.bytes()); - write_usize(fx.tcx, &mut data, ALIGN_INDEX, layout.align.abi.bytes()); - data_ctx.define(data); - - for (i, component) in components.into_iter().enumerate() { - if let Some(func_id) = component { - let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx); - data_ctx.write_function_addr((i * usize_size) as u32, func_ref); - } - } - - data_ctx.set_align(fx.tcx.data_layout.pointer_align.pref.bytes()); - - let data_id = fx.module.declare_anonymous_data(false, false).unwrap(); - - fx.module.define_data(data_id, &data_ctx).unwrap(); - - data_id -} - -fn write_usize(tcx: TyCtxt<'_>, buf: &mut [u8], idx: usize, num: u64) { - let pointer_size = - tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.usize)).unwrap().size.bytes() as usize; - let target = &mut buf[idx * pointer_size..(idx + 1) * pointer_size]; - - match tcx.data_layout.endian { - rustc_target::abi::Endian::Little => match pointer_size { - 4 => target.copy_from_slice(&(num as u32).to_le_bytes()), - 8 => target.copy_from_slice(&(num as u64).to_le_bytes()), - _ => todo!("pointer size {} is not yet supported", pointer_size), - }, - rustc_target::abi::Endian::Big => match pointer_size { - 4 => target.copy_from_slice(&(num as u32).to_be_bytes()), - 8 => target.copy_from_slice(&(num as u64).to_be_bytes()), - _ => todo!("pointer size {} is not yet supported", pointer_size), - }, + if fx.clif_comments.enabled() { + fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id)); } + fx.bcx.ins().global_value(fx.pointer_type, local_data_id) } diff --git a/compiler/rustc_codegen_cranelift/test.sh b/compiler/rustc_codegen_cranelift/test.sh index e222adc7b8..a10924628b 100755 --- a/compiler/rustc_codegen_cranelift/test.sh +++ b/compiler/rustc_codegen_cranelift/test.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash set -e -./build.sh --sysroot none "$@" +./y.rs build --sysroot none "$@" rm -r target/out || true scripts/tests.sh no_sysroot -./build.sh "$@" +./y.rs build "$@" scripts/tests.sh base_sysroot scripts/tests.sh extended_sysroot diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs new file mode 100755 index 0000000000..43937588b4 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/y.rs @@ -0,0 +1,153 @@ +#!/usr/bin/env bash +#![allow()] /*This line is ignored by bash +# This block is ignored by rustc +set -e +echo "[BUILD] y.rs" 1>&2 +rustc $0 -o ${0/.rs/.bin} -g +exec ${0/.rs/.bin} $@ +*/ + +//! The build system for cg_clif +//! +//! # Manual compilation +//! +//! If your system doesn't support shell scripts you can manually compile and run this file using +//! for example: +//! +//! ```shell +//! $ rustc y.rs -o build/y.bin +//! $ build/y.bin +//! ``` +//! +//! # Naming +//! +//! The name `y.rs` was chosen to not conflict with rustc's `x.py`. + +use std::env; +use std::path::PathBuf; +use std::process; + +#[path = "build_system/build_backend.rs"] +mod build_backend; +#[path = "build_system/build_sysroot.rs"] +mod build_sysroot; +#[path = "build_system/config.rs"] +mod config; +#[path = "build_system/prepare.rs"] +mod prepare; +#[path = "build_system/rustc_info.rs"] +mod rustc_info; +#[path = "build_system/utils.rs"] +mod utils; + +fn usage() { + eprintln!("Usage:"); + eprintln!(" ./y.rs prepare"); + eprintln!(" ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]"); +} + +macro_rules! arg_error { + ($($err:tt)*) => {{ + eprintln!($($err)*); + usage(); + std::process::exit(1); + }}; +} + +enum Command { + Build, +} + +#[derive(Copy, Clone)] +enum SysrootKind { + None, + Clif, + Llvm, +} + +fn main() { + env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1"); + env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1"); + // The target dir is expected in the default location. Guard against the user changing it. + env::set_var("CARGO_TARGET_DIR", "target"); + + let mut args = env::args().skip(1); + let command = match args.next().as_deref() { + Some("prepare") => { + if args.next().is_some() { + arg_error!("./x.rs prepare doesn't expect arguments"); + } + prepare::prepare(); + process::exit(0); + } + Some("build") => Command::Build, + Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), + Some(command) => arg_error!("Unknown command {}", command), + None => { + usage(); + process::exit(0); + } + }; + + let mut target_dir = PathBuf::from("build"); + let mut channel = "release"; + let mut sysroot_kind = SysrootKind::Clif; + while let Some(arg) = args.next().as_deref() { + match arg { + "--target-dir" => { + target_dir = PathBuf::from(args.next().unwrap_or_else(|| { + arg_error!("--target-dir requires argument"); + })) + } + "--debug" => channel = "debug", + "--sysroot" => { + sysroot_kind = match args.next().as_deref() { + Some("none") => SysrootKind::None, + Some("clif") => SysrootKind::Clif, + Some("llvm") => SysrootKind::Llvm, + Some(arg) => arg_error!("Unknown sysroot kind {}", arg), + None => arg_error!("--sysroot requires argument"), + } + } + flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag), + arg => arg_error!("Unexpected argument {}", arg), + } + } + + let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { + host_triple + } else if let Some(host_triple) = crate::config::get_value("host") { + host_triple + } else { + rustc_info::get_host_triple() + }; + let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { + if target_triple != "" { + target_triple + } else { + host_triple.clone() // Empty target triple can happen on GHA + } + } else if let Some(target_triple) = crate::config::get_value("target") { + target_triple + } else { + 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); + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + cg_clif_build_dir, + &host_triple, + &target_triple, + ); +} diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index d0eb6913ac..d78af9d413 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -21,10 +21,8 @@ rustc_attr = { path = "../rustc_attr" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_feature = { path = "../rustc_feature" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } -rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } rustc_llvm = { path = "../rustc_llvm" } rustc_metadata = { path = "../rustc_metadata" } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index ecf62ed213..7bd9397d64 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -128,6 +128,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let mut clobbers = vec![]; let mut output_types = vec![]; let mut op_idx = FxHashMap::default(); + let mut clobbered_x87 = false; for (idx, op) in operands.iter().enumerate() { match *op { InlineAsmOperandRef::Out { reg, late, place } => { @@ -150,7 +151,27 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let ty = if let Some(ref place) = place { layout = Some(&place.layout); llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout) - } else if !is_target_supported(reg.reg_class()) { + } else if matches!( + reg.reg_class(), + InlineAsmRegClass::X86( + X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::x87_reg + ) + ) { + // Special handling for x87/mmx registers: we always + // clobber the whole set if one register is marked as + // clobbered. This is due to the way LLVM handles the + // FP stack in inline assembly. + if !clobbered_x87 { + clobbered_x87 = true; + clobbers.push("~{st}".to_string()); + for i in 1..=7 { + clobbers.push(format!("~{{st({})}}", i)); + } + } + continue; + } else if !is_target_supported(reg.reg_class()) + || reg.reg_class().is_clobber_only(asm_arch) + { // We turn discarded outputs into clobber constraints // if the target feature needed by the register class is // disabled. This is necessary otherwise LLVM will try @@ -565,6 +586,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) @@ -586,6 +610,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q", InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q", @@ -593,6 +620,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk", + InlineAsmRegClass::X86( + X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg, + ) => unreachable!("clobber-only"), InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", @@ -617,6 +647,9 @@ fn modifier_to_llvm( | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { if modifier == Some('v') { None } else { modifier } } + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) @@ -639,6 +672,9 @@ fn modifier_to_llvm( InlineAsmRegClass::PowerPC(_) => None, InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None, + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier { None if arch == InlineAsmArch::X86_64 => Some('q'), @@ -663,6 +699,9 @@ fn modifier_to_llvm( _ => unreachable!(), }, InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None, + InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None, InlineAsmRegClass::Bpf(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { @@ -681,6 +720,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { cx.type_vector(cx.type_i64(), 2) } + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) @@ -704,6 +746,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(), @@ -711,6 +756,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index f1c45d8dc3..56b93f8346 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::OptLevel; use rustc_session::Session; use rustc_target::spec::abi::Abi; -use rustc_target::spec::{SanitizerSet, StackProbeType}; +use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType}; use crate::attributes; use crate::llvm::AttributePlace::Function; @@ -69,15 +69,25 @@ fn naked(val: &'ll Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } -pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { - if cx.sess().must_not_eliminate_frame_pointers() { - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - cstr!("frame-pointer"), - cstr!("all"), - ); +pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + let mut fp = cx.sess().target.frame_pointer; + // "mcount" function relies on stack pointer. + // See . + if cx.sess().instrument_mcount() || matches!(cx.sess().opts.cg.force_frame_pointers, Some(true)) + { + fp = FramePointer::Always; } + let attr_value = match fp { + FramePointer::Always => cstr!("all"), + FramePointer::NonLeaf => cstr!("non-leaf"), + FramePointer::MayOmit => return, + }; + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr!("frame-pointer"), + attr_value, + ); } /// Tell LLVM what instrument function to insert. @@ -254,7 +264,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: } // FIXME: none of these three functions interact with source level attributes. - set_frame_pointer_elimination(cx, llfn); + set_frame_pointer_type(cx, llfn); set_instrument_function(cx, llfn); set_probestack(cx, llfn); @@ -279,6 +289,9 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) { llvm::AddFunctionAttrString(llfn, Function, cstr!("cmse_nonsecure_entry")); } + if let Some(align) = codegen_fn_attrs.alignment { + llvm::set_alignment(llfn, align as usize); + } sanitize(cx, codegen_fn_attrs.no_sanitize, llfn); // Always annotate functions with the target-cpu they are compiled for. diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 64416bced3..6ac7093b7d 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -12,7 +12,7 @@ use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder}; use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_middle::middle::cstore::DllImport; +use rustc_middle::middle::cstore::{DllCallingConvention, DllImport}; use rustc_session::Session; use rustc_span::symbol::Symbol; @@ -208,10 +208,12 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { // have any \0 characters let import_name_vector: Vec = dll_imports .iter() - .map(if self.config.sess.target.arch == "x86" { - |import: &DllImport| CString::new(format!("_{}", import.name.to_string())).unwrap() - } else { - |import: &DllImport| CString::new(import.name.to_string()).unwrap() + .map(|import: &DllImport| { + if self.config.sess.target.arch == "x86" { + LlvmArchiveBuilder::i686_decorated_name(import) + } else { + CString::new(import.name.to_string()).unwrap() + } }) .collect(); @@ -391,6 +393,21 @@ impl<'a> LlvmArchiveBuilder<'a> { ret } } + + fn i686_decorated_name(import: &DllImport) -> CString { + let name = import.name; + // We verified during construction that `name` does not contain any NULL characters, so the + // conversion to CString is guaranteed to succeed. + CString::new(match import.calling_convention { + DllCallingConvention::C => format!("_{}", name), + DllCallingConvention::Stdcall(arg_list_size) => format!("_{}@{}", name, arg_list_size), + DllCallingConvention::Fastcall(arg_list_size) => format!("@{}@{}", name, arg_list_size), + DllCallingConvention::Vectorcall(arg_list_size) => { + format!("{}@@{}", name, arg_list_size) + } + }) + .unwrap() + } } fn string_to_io_error(s: String) -> io::Error { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index c8cf0116c6..5675a5d981 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -410,17 +410,17 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value { + fn load(&mut self, ty: &'ll Type, ptr: &'ll Value, align: Align) -> &'ll Value { unsafe { - let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED); + let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED); llvm::LLVMSetAlignment(load, align.bytes() as c_uint); load } } - fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value { + fn volatile_load(&mut self, ty: &'ll Type, ptr: &'ll Value) -> &'ll Value { unsafe { - let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED); + let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED); llvm::LLVMSetVolatile(load, llvm::True); load } @@ -428,6 +428,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn atomic_load( &mut self, + ty: &'ll Type, ptr: &'ll Value, order: rustc_codegen_ssa::common::AtomicOrdering, size: Size, @@ -435,6 +436,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { let load = llvm::LLVMRustBuildAtomicLoad( self.llbuilder, + ty, ptr, UNNAMED, AtomicOrdering::from_generic(order), @@ -486,7 +488,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } let llval = const_llval.unwrap_or_else(|| { - let load = self.load(place.llval, place.align); + let load = self.load(place.layout.llvm_type(self), place.llval, place.align); if let abi::Abi::Scalar(ref scalar) = place.layout.abi { scalar_load_metadata(self, load, scalar); } @@ -498,7 +500,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let mut load = |i, scalar: &abi::Scalar, align| { let llptr = self.struct_gep(place.llval, i as u64); - let load = self.load(llptr, align); + let llty = place.layout.scalar_pair_element_llvm_type(self, i, false); + let load = self.load(llty, llptr, align); scalar_load_metadata(self, load, scalar); self.to_immediate_scalar(load, scalar) }; @@ -606,7 +609,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // According to LLVM [1] building a nontemporal store must // *always* point to a metadata value of the integer 1. // - // [1]: http://llvm.org/docs/LangRef.html#store-instruction + // [1]: https://llvm.org/docs/LangRef.html#store-instruction let one = self.cx.const_i32(1); let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1); llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node); @@ -815,13 +818,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { size: &'ll Value, flags: MemFlags, ) { - if flags.contains(MemFlags::NONTEMPORAL) { - // HACK(nox): This is inefficient but there is no nontemporal memcpy. - let val = self.load(src, src_align); - let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val))); - self.store_with_flags(val, ptr, dst_align, flags); - return; - } + assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported"); let size = self.intcast(size, self.type_isize(), false); let is_volatile = flags.contains(MemFlags::VOLATILE); let dst = self.pointercast(dst, self.type_i8p()); @@ -848,13 +845,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { size: &'ll Value, flags: MemFlags, ) { - if flags.contains(MemFlags::NONTEMPORAL) { - // HACK(nox): This is inefficient but there is no nontemporal memmove. - let val = self.load(src, src_align); - let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val))); - self.store_with_flags(val, ptr, dst_align, flags); - return; - } + assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported"); let size = self.intcast(size, self.type_isize(), false); let is_volatile = flags.contains(MemFlags::VOLATILE); let dst = self.pointercast(dst, self.type_i8p()); @@ -937,8 +928,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { pers_fn: &'ll Value, num_clauses: usize, ) -> &'ll Value { + // Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while, + // LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The + // personality lives on the parent function anyway. + self.set_personality_fn(pers_fn); unsafe { - llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, num_clauses as c_uint, UNNAMED) + llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED) } } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 58af9d4cd0..35e72621c5 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -243,8 +243,9 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.const_bitcast(llval, llty) } } - Scalar::Ptr(ptr) => { - let (base_addr, base_addr_space) = match self.tcx.global_alloc(ptr.alloc_id) { + Scalar::Ptr(ptr, _size) => { + let (alloc_id, offset) = ptr.into_parts(); + let (base_addr, base_addr_space) = match self.tcx.global_alloc(alloc_id) { GlobalAlloc::Memory(alloc) => { let init = const_alloc_to_llvm(self, alloc); let value = match alloc.mutability { @@ -252,7 +253,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { _ => self.static_addr_of(init, alloc.align, None), }; if !self.sess().fewer_names() { - llvm::set_value_name(value, format!("{:?}", ptr.alloc_id).as_bytes()); + llvm::set_value_name(value, format!("{:?}", alloc_id).as_bytes()); } (value, AddressSpace::DATA) } @@ -269,7 +270,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { let llval = unsafe { llvm::LLVMConstInBoundsGEP( self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)), - &self.const_usize(ptr.offset.bytes()), + &self.const_usize(offset.bytes()), 1, ) }; @@ -282,6 +283,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } + fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value { + const_alloc_to_llvm(self, alloc) + } + fn from_const_alloc( &self, layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index e50d5506e2..3ca295f4a7 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -11,7 +11,7 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ - read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer, + read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer, Scalar as InterpScalar, }; use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::{self, Instance, Ty}; @@ -25,7 +25,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll let pointer_size = dl.pointer_size.bytes() as usize; let mut next_offset = 0; - for &(offset, ((), alloc_id)) in alloc.relocations().iter() { + for &(offset, alloc_id) in alloc.relocations().iter() { let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; @@ -55,7 +55,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll }; llvals.push(cx.scalar_to_backend( - Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(), + InterpScalar::from_pointer( + Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), + &cx.tcx, + ), &Scalar { value: Primitive::Pointer, valid_range: 0..=!0 }, cx.type_i8p_ext(address_space), )); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 6aa952462f..59259857b4 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -71,7 +71,7 @@ pub struct CodegenCx<'ll, 'tcx> { pub statics_to_rauw: RefCell>, /// Statics that will be placed in the llvm.used variable - /// See for details + /// See for details pub used_statics: RefCell>, pub lltypes: RefCell, Option), &'ll Type>>, @@ -149,11 +149,12 @@ pub unsafe fn create_module( if !custom_llvm_used && target_data_layout != llvm_data_layout { bug!( - "data-layout for builtin `{}` target, `{}`, \ - differs from LLVM default, `{}`", - sess.target.llvm_target, - target_data_layout, - llvm_data_layout + "data-layout for target `{rustc_target}`, `{rustc_layout}`, \ + differs from LLVM target's `{llvm_target}` default layout, `{llvm_layout}`", + rustc_target = sess.opts.target_triple, + rustc_layout = target_data_layout, + llvm_target = sess.target.llvm_target, + llvm_layout = llvm_data_layout ); } } @@ -385,11 +386,16 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } else { "rust_eh_personality" }; - let fty = self.type_variadic_func(&[], self.type_i32()); - self.declare_cfn(name, llvm::UnnamedAddr::Global, fty) + if let Some(llfn) = self.get_declared_value(name) { + llfn + } else { + let fty = self.type_variadic_func(&[], self.type_i32()); + let llfn = self.declare_cfn(name, llvm::UnnamedAddr::Global, fty); + attributes::apply_target_cpu_attr(self, llfn); + llfn + } } }; - attributes::apply_target_cpu_attr(self, llfn); self.eh_personality.set(Some(llfn)); llfn } @@ -410,8 +416,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { &self.used_statics } - fn set_frame_pointer_elimination(&self, llfn: &'ll Value) { - attributes::set_frame_pointer_elimination(self, llfn) + fn set_frame_pointer_type(&self, llfn: &'ll Value) { + attributes::set_frame_pointer_type(self, llfn) } fn apply_target_cpu_attr(&self, llfn: &'ll Value) { @@ -500,6 +506,7 @@ impl CodegenCx<'b, 'tcx> { let t_i32 = self.type_i32(); let t_i64 = self.type_i64(); let t_i128 = self.type_i128(); + let t_isize = self.type_isize(); let t_f32 = self.type_f32(); let t_f64 = self.type_f64(); @@ -712,6 +719,10 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.assume", fn(i1) -> void); ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void); + // This isn't an "LLVM intrinsic", but LLVM's optimization passes + // recognize it like one and we assume it exists in `core::slice::cmp` + ifn!("memcmp", fn(i8p, i8p, t_isize) -> t_i32); + // variadic intrinsics ifn!("llvm.va_start", fn(i8p) -> void); ifn!("llvm.va_end", fn(i8p) -> void); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 38f50a6d62..de3f719b81 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -20,7 +20,7 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, // LLVM to keep around the reference to the global. let indices = [bx.const_i32(0), bx.const_i32(0)]; let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices); - let volative_load_instruction = bx.volatile_load(element); + let volative_load_instruction = bx.volatile_load(bx.type_i8(), element); unsafe { llvm::LLVMSetAlignment(volative_load_instruction, 1); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1e70664e64..7e136c1b24 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1,4 +1,3 @@ -use self::EnumTagInfo::*; use self::MemberDescriptionFactory::*; use self::RecursiveTypeDescription::*; @@ -28,7 +27,7 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::ich::NodeIdHashingMode; -use rustc_middle::mir::{self, Field, GeneratorLayout}; +use rustc_middle::mir::{self, GeneratorLayout}; use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::Instance; @@ -471,21 +470,28 @@ fn trait_pointer_metadata( // type is assigned the correct name, size, namespace, and source location. // However, it does not describe the trait's methods. - let containing_scope = match trait_type.kind() { - ty::Dynamic(ref data, ..) => { - data.principal_def_id().map(|did| get_namespace_for_item(cx, did)) - } - _ => { - bug!( - "debuginfo: unexpected trait-object type in \ - trait_pointer_metadata(): {:?}", - trait_type - ); - } - }; + let (containing_scope, trait_type_name) = match trait_object_type { + Some(trait_object_type) => match trait_object_type.kind() { + ty::Adt(def, _) => ( + Some(get_namespace_for_item(cx, def.did)), + compute_debuginfo_type_name(cx.tcx, trait_object_type, false), + ), + ty::RawPtr(_) | ty::Ref(..) => { + (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_object_type, true)) + } + _ => { + bug!( + "debuginfo: unexpected trait-object type in \ + trait_pointer_metadata(): {:?}", + trait_object_type + ); + } + }, - let trait_object_type = trait_object_type.unwrap_or(trait_type); - let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false); + // No object type, use the trait type directly (no scope here since the type + // will be wrapped in the dyn$ synthetic type). + None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)), + }; let file_metadata = unknown_file_metadata(cx); @@ -525,7 +531,7 @@ fn trait_pointer_metadata( composite_type_metadata( cx, - trait_object_type, + trait_object_type.unwrap_or(trait_type), &trait_type_name[..], unique_type_id, member_descriptions, @@ -1181,7 +1187,7 @@ enum MemberDescriptionFactory<'ll, 'tcx> { TupleMDF(TupleMemberDescriptionFactory<'tcx>), EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>), UnionMDF(UnionMemberDescriptionFactory<'tcx>), - VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>), + VariantMDF(VariantMemberDescriptionFactory<'tcx>), } impl MemberDescriptionFactory<'ll, 'tcx> { @@ -1498,14 +1504,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } let variant_info = variant_info_for(index); - let (variant_type_metadata, member_description_factory) = describe_enum_variant( - cx, - self.layout, - variant_info, - None, - self_metadata, - self.span, - ); + let (variant_type_metadata, member_description_factory) = + describe_enum_variant(cx, self.layout, variant_info, self_metadata, self.span); let member_descriptions = member_description_factory.create_member_descriptions(cx); @@ -1517,7 +1517,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { Some(&self.common_members), ); vec![MemberDescription { - name: if fallback { String::new() } else { variant_info.variant_name() }, + name: variant_info.variant_name(), type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, @@ -1533,28 +1533,38 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { ref variants, .. } => { - let tag_info = if fallback { - // For MSVC, we generate a union of structs for each variant with an explicit - // discriminant field roughly equivalent to the following C: + let fallback_discr_variant = if fallback { + // For MSVC, we generate a union of structs for each variant and an + // explicit discriminant field roughly equivalent to the following C: // ```c // union enum$<{name}> { // struct {variant 0 name} { - // tag$ variant$; // // } variant0; // + // {name} discriminant; // } // ``` - // The natvis in `intrinsic.nativs` then matches on `this.variant0.variant$` to + // The natvis in `intrinsic.natvis` then matches on `this.discriminant` to // determine which variant is active and then displays it. - Some(DirectTag { - tag_field: Field::from(tag_field), - tag_type_metadata: self.tag_type_metadata.unwrap(), + let enum_layout = self.layout; + let offset = enum_layout.fields.offset(tag_field); + let discr_ty = enum_layout.field(cx, tag_field).ty; + let (size, align) = cx.size_and_align_of(discr_ty); + Some(MemberDescription { + name: "discriminant".into(), + type_metadata: self.tag_type_metadata.unwrap(), + offset, + size, + align, + flags: DIFlags::FlagZero, + discriminant: None, + source_info: None, }) } else { - // This doesn't matter in this case. None }; + variants .iter_enumerated() .map(|(i, _)| { @@ -1564,7 +1574,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, variant, variant_info, - tag_info, self_metadata, self.span, ); @@ -1598,6 +1607,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { source_info: variant_info.source_info(cx), } }) + .chain(fallback_discr_variant.into_iter()) .collect() } Variants::Multiple { @@ -1695,7 +1705,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, dataful_variant_layout, variant_info, - Some(NicheTag), self_metadata, self.span, ); @@ -1747,7 +1756,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, variant, variant_info, - Some(NicheTag), self_metadata, self.span, ); @@ -1784,39 +1792,27 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } // Creates `MemberDescription`s for the fields of a single enum variant. -struct VariantMemberDescriptionFactory<'ll, 'tcx> { +struct VariantMemberDescriptionFactory<'tcx> { /// Cloned from the `layout::Struct` describing the variant. offsets: Vec, args: Vec<(String, Ty<'tcx>)>, - tag_type_metadata: Option<&'ll DIType>, span: Span, } -impl VariantMemberDescriptionFactory<'ll, 'tcx> { +impl VariantMemberDescriptionFactory<'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { self.args .iter() .enumerate() .map(|(i, &(ref name, ty))| { - // Discriminant is always the first field of our variant - // when using the enum fallback. - let is_artificial_discr = use_enum_fallback(cx) && i == 0; let (size, align) = cx.size_and_align_of(ty); MemberDescription { name: name.to_string(), - type_metadata: if is_artificial_discr { - self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span)) - } else { - type_metadata(cx, ty, self.span) - }, + type_metadata: type_metadata(cx, ty, self.span), offset: self.offsets[i], size, align, - flags: if is_artificial_discr { - DIFlags::FlagArtificial - } else { - DIFlags::FlagZero - }, + flags: DIFlags::FlagZero, discriminant: None, source_info: None, } @@ -1825,12 +1821,6 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { } } -#[derive(Copy, Clone)] -enum EnumTagInfo<'ll> { - DirectTag { tag_field: Field, tag_type_metadata: &'ll DIType }, - NicheTag, -} - #[derive(Copy, Clone)] enum VariantInfo<'a, 'tcx> { Adt(&'tcx ty::VariantDef), @@ -1909,7 +1899,6 @@ fn describe_enum_variant( cx: &CodegenCx<'ll, 'tcx>, layout: layout::TyAndLayout<'tcx>, variant: VariantInfo<'_, 'tcx>, - discriminant_info: Option>, containing_scope: &'ll DIScope, span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { @@ -1928,50 +1917,13 @@ fn describe_enum_variant( ) }); - // Build an array of (field name, field type) pairs to be captured in the factory closure. - let (offsets, args) = if use_enum_fallback(cx) { - // If this is not a univariant enum, there is also the discriminant field. - let (discr_offset, discr_arg) = match discriminant_info { - Some(DirectTag { tag_field, .. }) => { - // We have the layout of an enum variant, we need the layout of the outer enum - let enum_layout = cx.layout_of(layout.ty); - let offset = enum_layout.fields.offset(tag_field.as_usize()); - let args = ("variant$".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty); - (Some(offset), Some(args)) - } - _ => (None, None), - }; - ( - discr_offset - .into_iter() - .chain((0..layout.fields.count()).map(|i| layout.fields.offset(i))) - .collect(), - discr_arg - .into_iter() - .chain( - (0..layout.fields.count()) - .map(|i| (variant.field_name(i), layout.field(cx, i).ty)), - ) - .collect(), - ) - } else { - ( - (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(), - (0..layout.fields.count()) - .map(|i| (variant.field_name(i), layout.field(cx, i).ty)) - .collect(), - ) - }; + let offsets = (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(); + let args = (0..layout.fields.count()) + .map(|i| (variant.field_name(i), layout.field(cx, i).ty)) + .collect(); - let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { - offsets, - args, - tag_type_metadata: match discriminant_info { - Some(DirectTag { tag_type_metadata, .. }) => Some(tag_type_metadata), - _ => None, - }, - span, - }); + let member_description_factory = + VariantMDF(VariantMemberDescriptionFactory { offsets, args, span }); (metadata_stub, member_description_factory) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 2b99a2ebad..8375d4c7ca 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -5,7 +5,6 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use self::metadata::{file_metadata, type_metadata, TypeMap}; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; use self::namespace::mangled_name_of_instance; -use self::type_names::compute_debuginfo_type_name; use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; use crate::abi::FnAbi; @@ -311,10 +310,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature) }; - // Find the enclosing function, in case this is a closure. - let def_key = self.tcx().def_key(def_id); - let mut name = def_key.disambiguated_data.data.to_string(); + let mut name = String::new(); + type_names::push_item_name(self.tcx(), def_id, false, &mut name); + // Find the enclosing function, in case this is a closure. let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id); // Get_template_parameters() will append a `<...>` clause to the function @@ -428,24 +427,16 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { substs: SubstsRef<'tcx>, name_to_append_suffix_to: &mut String, ) -> &'ll DIArray { + type_names::push_generic_params( + cx.tcx, + cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs), + name_to_append_suffix_to, + ); + if substs.types().next().is_none() { return create_DIArray(DIB(cx), &[]); } - name_to_append_suffix_to.push('<'); - for (i, actual_type) in substs.types().enumerate() { - if i != 0 { - name_to_append_suffix_to.push(','); - } - - let actual_type = - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type); - // Add actual type name to <...> clause of function name - let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true); - name_to_append_suffix_to.push_str(&actual_type_name[..]); - } - name_to_append_suffix_to.push('>'); - // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { let names = get_parameter_names(cx, generics); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs index 9945d4f428..1cbf538699 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs @@ -1,13 +1,13 @@ // Namespace Handling. use super::utils::{debug_context, DIB}; +use rustc_codegen_ssa::debuginfo::type_names; use rustc_middle::ty::{self, Instance}; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::DIScope; use rustc_hir::def_id::DefId; -use rustc_hir::definitions::DefPathData; pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, @@ -27,25 +27,18 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { .parent .map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent })); - let crate_name_as_str; - let name_to_string; - let namespace_name = match def_key.disambiguated_data.data { - DefPathData::CrateRoot => { - crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str(); - &*crate_name_as_str - } - data => { - name_to_string = data.to_string(); - &*name_to_string - } + let namespace_name_string = { + let mut output = String::new(); + type_names::push_item_name(cx.tcx, def_id, false, &mut output); + output }; let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( DIB(cx), parent_scope, - namespace_name.as_ptr().cast(), - namespace_name.len(), + namespace_name_string.as_ptr().cast(), + namespace_name_string.len(), false, // ExportSymbols (only relevant for C++ anonymous namespaces) ) }; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 22d513d66d..a48a694b63 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -162,11 +162,14 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { sym::volatile_load | sym::unaligned_volatile_load => { let tp_ty = substs.type_at(0); - let mut ptr = args[0].immediate(); - if let PassMode::Cast(ty) = fn_abi.ret.mode { - ptr = self.pointercast(ptr, self.type_ptr_to(ty.llvm_type(self))); - } - let load = self.volatile_load(ptr); + let ptr = args[0].immediate(); + let load = if let PassMode::Cast(ty) = fn_abi.ret.mode { + let llty = ty.llvm_type(self); + let ptr = self.pointercast(ptr, self.type_ptr_to(llty)); + self.volatile_load(llty, ptr) + } else { + self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr) + }; let align = if name == sym::unaligned_volatile_load { 1 } else { @@ -296,6 +299,44 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } + sym::raw_eq => { + use abi::Abi::*; + let tp_ty = substs.type_at(0); + let layout = self.layout_of(tp_ty).layout; + let use_integer_compare = match layout.abi { + Scalar(_) | ScalarPair(_, _) => true, + Uninhabited | Vector { .. } => false, + Aggregate { .. } => { + // For rusty ABIs, small aggregates are actually passed + // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), + // so we re-use that same threshold here. + layout.size <= self.data_layout().pointer_size * 2 + } + }; + + let a = args[0].immediate(); + let b = args[1].immediate(); + if layout.size.bytes() == 0 { + self.const_bool(true) + } else if use_integer_compare { + let integer_ty = self.type_ix(layout.size.bits()); + let ptr_ty = self.type_ptr_to(integer_ty); + let a_ptr = self.bitcast(a, ptr_ty); + let a_val = self.load(integer_ty, a_ptr, layout.align.abi); + let b_ptr = self.bitcast(b, ptr_ty); + let b_val = self.load(integer_ty, b_ptr, layout.align.abi); + self.icmp(IntPredicate::IntEQ, a_val, b_val) + } else { + let i8p_ty = self.type_i8p(); + let a_ptr = self.bitcast(a, i8p_ty); + let b_ptr = self.bitcast(b, i8p_ty); + let n = self.const_usize(layout.size.bytes()); + let llfn = self.get_intrinsic("memcmp"); + let cmp = self.call(llfn, &[a_ptr, b_ptr, n], None); + self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0)) + } + } + _ if name_str.starts_with("simd_") => { match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) { Ok(llval) => llval, @@ -502,7 +543,7 @@ fn codegen_msvc_try( // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang let flags = bx.const_i32(8); let funclet = catchpad_rust.catch_pad(cs, &[tydesc, flags, slot]); - let ptr = catchpad_rust.load(slot, ptr_align); + let ptr = catchpad_rust.load(bx.type_i8p(), slot, ptr_align); catchpad_rust.call(catch_func, &[data, ptr], Some(&funclet)); catchpad_rust.catch_ret(&funclet, caught.llbb()); @@ -674,7 +715,7 @@ fn gen_fn<'ll, 'tcx>( ) -> &'ll Value { let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); let llfn = cx.declare_fn(name, &fn_abi); - cx.set_frame_pointer_elimination(llfn); + cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 776cb2ee99..aa4db1622b 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,7 +8,6 @@ #![feature(bool_to_option)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(iter_zip)] @@ -293,14 +292,7 @@ impl CodegenBackend for LlvmCodegenBackend { // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - link_binary::>( - sess, - &codegen_results, - outputs, - &codegen_results.crate_info.local_crate_name.as_str(), - ); - - Ok(()) + link_binary::>(sess, &codegen_results, outputs) } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 9192325101..68d566cca0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1165,7 +1165,7 @@ extern "C" { pub fn LLVMBuildLandingPad( B: &Builder<'a>, Ty: &'a Type, - PersFn: &'a Value, + PersFn: Option<&'a Value>, NumClauses: c_uint, Name: *const c_char, ) -> &'a Value; @@ -1385,7 +1385,12 @@ extern "C" { Val: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildLoad(B: &Builder<'a>, PointerVal: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildLoad2( + B: &Builder<'a>, + Ty: &'a Type, + PointerVal: &'a Value, + Name: *const c_char, + ) -> &'a Value; pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value; @@ -1631,6 +1636,7 @@ extern "C" { // Atomic Operations pub fn LLVMRustBuildAtomicLoad( B: &Builder<'a>, + ElementType: &'a Type, PointerVal: &'a Value, Name: *const c_char, Order: AtomicOrdering, diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 38d56f8721..c1521a760b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -102,7 +102,7 @@ pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { // example happen for generics when using multiple codegen units. This function simply uses the // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the // function. -// For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52 +// For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { unsafe { let name = get_value_name(val); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 0dd3d2ae15..cb9c6269b6 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -3,13 +3,17 @@ use crate::{llvm, llvm_util}; use libc::c_int; use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxHashSet; +use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_middle::bug; use rustc_session::config::PrintRequest; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; use std::ffi::{CStr, CString}; +use tracing::debug; +use std::mem; +use std::path::Path; use std::ptr; use std::slice; use std::str; @@ -129,6 +133,16 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); + for plugin in &sess.opts.debugging_opts.llvm_plugins { + let path = Path::new(plugin); + let res = DynamicLibrary::open(path); + match res { + Ok(_) => debug!("LLVM plugin loaded succesfully {} ({})", path.display(), plugin), + Err(e) => bug!("couldn't load plugin: {}", e), + } + mem::forget(res); + } + rustc_llvm::initialize_available_targets(); llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 39d08fbee3..9df1bd7d1d 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -32,14 +32,15 @@ fn emit_direct_ptr_va_arg( slot_size: Align, allow_higher_align: bool, ) -> (&'ll Value, Align) { - let va_list_ptr_ty = bx.cx().type_ptr_to(bx.cx.type_i8p()); + let va_list_ty = bx.type_i8p(); + let va_list_ptr_ty = bx.type_ptr_to(va_list_ty); let va_list_addr = if list.layout.llvm_type(bx.cx) != va_list_ptr_ty { bx.bitcast(list.immediate(), va_list_ptr_ty) } else { list.immediate() }; - let ptr = bx.load(va_list_addr, bx.tcx().data_layout.pointer_align.abi); + let ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi); let (addr, addr_align) = if allow_higher_align && align > slot_size { (round_pointer_up_to_alignment(bx, ptr, align, bx.cx().type_i8p()), align) @@ -82,10 +83,10 @@ fn emit_ptr_va_arg( let (addr, addr_align) = emit_direct_ptr_va_arg(bx, list, llty, size, align.abi, slot_size, allow_higher_align); if indirect { - let tmp_ret = bx.load(addr, addr_align); - bx.load(tmp_ret, align.abi) + let tmp_ret = bx.load(llty, addr, addr_align); + bx.load(bx.cx.layout_of(target_ty).llvm_type(bx.cx), tmp_ret, align.abi) } else { - bx.load(addr, addr_align) + bx.load(llty, addr, addr_align) } } @@ -118,7 +119,7 @@ fn emit_aapcs_va_arg( }; // if the offset >= 0 then the value will be on the stack - let mut reg_off_v = bx.load(reg_off, offset_align); + let mut reg_off_v = bx.load(bx.type_i32(), reg_off, offset_align); let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero); bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb()); @@ -139,8 +140,9 @@ fn emit_aapcs_va_arg( let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero); maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb()); + let top_type = bx.type_i8p(); let top = in_reg.struct_gep(va_list_addr, reg_top_index); - let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi); + let top = in_reg.load(top_type, top, bx.tcx().data_layout.pointer_align.abi); // reg_value = *(@top + reg_off_v); let mut reg_addr = in_reg.gep(top, &[reg_off_v]); @@ -149,8 +151,9 @@ fn emit_aapcs_va_arg( let offset = bx.const_i32((slot_size - layout.size.bytes()) as i32); reg_addr = in_reg.gep(reg_addr, &[offset]); } - let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(layout.llvm_type(bx))); - let reg_value = in_reg.load(reg_addr, layout.align.abi); + let reg_type = layout.llvm_type(bx); + let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type)); + let reg_value = in_reg.load(reg_type, reg_addr, layout.align.abi); in_reg.br(&end.llbb()); // On Stack block diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 9bd5764f07..f1e412df86 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -9,13 +9,14 @@ test = false [dependencies] bitflags = "1.2.1" -cc = "1.0.68" +cc = "1.0.69" itertools = "0.9" tracing = "0.1" libc = "0.2.50" jobserver = "0.1.22" tempfile = "3.2" pathdiff = "0.2.0" +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } @@ -35,6 +36,6 @@ rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } [dependencies.object] -version = "0.25.2" +version = "0.26.2" default-features = false features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"] diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 6c9ec9e7b0..ab211e9daf 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,9 +1,9 @@ -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::Handler; +use rustc_errors::{ErrorReported, Handler}; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; -use rustc_middle::middle::cstore::{DllImport, LibSource}; +use rustc_middle::middle::cstore::DllImport; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; @@ -34,7 +34,6 @@ use object::write::Object; use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind}; use tempfile::Builder as TempFileBuilder; -use std::cmp::Ordering; use std::ffi::OsString; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; @@ -54,8 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( sess: &'a Session, codegen_results: &CodegenResults, outputs: &OutputFilenames, - crate_name: &str, -) { +) -> Result<(), ErrorReported> { let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); for &crate_type in sess.crate_types().iter() { @@ -87,15 +85,26 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( .tempdir() .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err))); let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps); - let out_filename = out_filename(sess, crate_type, outputs, crate_name); + let out_filename = out_filename( + sess, + crate_type, + outputs, + &codegen_results.crate_info.local_crate_name.as_str(), + ); match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); - link_rlib::(sess, codegen_results, RlibFlavor::Normal, &out_filename, &path) - .build(); + link_rlib::( + sess, + codegen_results, + RlibFlavor::Normal, + &out_filename, + &path, + )? + .build(); } CrateType::Staticlib => { - link_staticlib::(sess, codegen_results, &out_filename, &path); + link_staticlib::(sess, codegen_results, &out_filename, &path)?; } _ => { link_natively::( @@ -141,104 +150,15 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( } } }); -} - -// The third parameter is for env vars, used on windows to set up the -// path for MSVC to find its DLLs, and gcc to find its bundled -// toolchain -fn get_linker( - sess: &Session, - linker: &Path, - flavor: LinkerFlavor, - self_contained: bool, -) -> Command { - let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); - - // If our linker looks like a batch script on Windows then to execute this - // we'll need to spawn `cmd` explicitly. This is primarily done to handle - // emscripten where the linker is `emcc.bat` and needs to be spawned as - // `cmd /c emcc.bat ...`. - // - // This worked historically but is needed manually since #42436 (regression - // was tagged as #42791) and some more info can be found on #44443 for - // emscripten itself. - 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() => { - Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path())) - } - _ => Command::new(linker), - }, - }; - - // UWP apps have API restrictions enforced during Store submissions. - // 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 let Some(ref tool) = msvc_tool { - let original_path = tool.path(); - if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { - let arch = match t.arch.as_str() { - "x86_64" => Some("x64"), - "x86" => Some("x86"), - "aarch64" => Some("arm64"), - "arm" => Some("arm"), - _ => None, - }; - if let Some(ref a) = arch { - // FIXME: Move this to `fn linker_with_args`. - let mut arg = OsString::from("/LIBPATH:"); - arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a)); - cmd.arg(&arg); - } else { - warn!("arch is not supported"); - } - } else { - warn!("MSVC root path lib location not found"); - } - } else { - warn!("link.exe not found"); - } - } - - // The compiler's sysroot often has some bundled tools, so add it to the - // PATH for the child. - let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained); - let mut msvc_changed_path = false; - if sess.target.is_like_msvc { - if let Some(ref tool) = msvc_tool { - cmd.args(tool.args()); - for &(ref k, ref v) in tool.env() { - if k == "PATH" { - new_path.extend(env::split_paths(v)); - msvc_changed_path = true; - } else { - cmd.env(k, v); - } - } - } - } - if !msvc_changed_path { - if let Some(path) = env::var_os("PATH") { - new_path.extend(env::split_paths(&path)); - } - } - cmd.env("PATH", env::join_paths(new_path).unwrap()); - - cmd + Ok(()) } pub fn each_linked_rlib( info: &CrateInfo, f: &mut dyn FnMut(CrateNum, &Path), ) -> Result<(), String> { - let crates = info.used_crates_static.iter(); + let crates = info.used_crates.iter(); let mut fmts = None; for (ty, list) in info.dependency_formats.iter() { match ty { @@ -256,22 +176,23 @@ pub fn each_linked_rlib( Some(f) => f, None => return Err("could not find formats for rlibs".to_string()), }; - for &(cnum, ref path) in crates { + 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()), } let name = &info.crate_name[&cnum]; - let path = match *path { - LibSource::Some(ref p) => p, - LibSource::MetadataOnly => { - return Err(format!( - "could not find rlib for: `{}`, found rmeta (metadata) file", - name - )); - } - LibSource::None => return Err(format!("could not find rlib for: `{}`", name)), + let used_crate_source = &info.used_crate_source[&cnum]; + let path = if let Some((path, _)) = &used_crate_source.rlib { + path + } else if used_crate_source.rmeta.is_some() { + return Err(format!( + "could not find rlib for: `{}`, found rmeta (metadata) file", + name + )); + } else { + return Err(format!("could not find rlib for: `{}`", name)); }; f(cnum, &path); } @@ -306,7 +227,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( flavor: RlibFlavor, out_filename: &Path, tmpdir: &MaybeTempDir, -) -> B { +) -> Result { info!("preparing rlib to {:?}", out_filename); let mut ab = ::new(sess, out_filename, None); @@ -345,7 +266,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( } for (raw_dylib_name, raw_dylib_imports) in - collate_raw_dylibs(&codegen_results.crate_info.used_libraries) + collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)? { ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir); } @@ -398,7 +319,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( } } } - return ab; + return Ok(ab); // For rlibs we "pack" rustc metadata into a dummy object file. When rustc // creates a dylib crate type it will pass `--whole-archive` (or the @@ -537,49 +458,43 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( /// then the CodegenResults value contains one NativeLib instance for each block. However, the /// linker appears to expect only a single import library for each library used, so we need to /// collate the symbols together by library name before generating the import libraries. -fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec)> { - let mut dylib_table: FxHashMap> = FxHashMap::default(); +fn collate_raw_dylibs( + sess: &Session, + used_libraries: &[NativeLib], +) -> Result)>, ErrorReported> { + // Use index maps to preserve original order of imports and libraries. + let mut dylib_table = FxIndexMap::>::default(); for lib in used_libraries { if lib.kind == NativeLibKind::RawDylib { - let name = lib.name.unwrap_or_else(|| - bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier") - ); - let name = if matches!(lib.verbatim, Some(true)) { - name.to_string() - } else { - format!("{}.dll", name) - }; - dylib_table - .entry(name) - .or_default() - .extend(lib.dll_imports.iter().map(|import| import.name)); + let ext = if matches!(lib.verbatim, Some(true)) { "" } else { ".dll" }; + let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), ext); + let imports = dylib_table.entry(name.clone()).or_default(); + for import in &lib.dll_imports { + if let Some(old_import) = imports.insert(import.name, import) { + // 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, + ), + ); + } + } + } } } - - // FIXME: when we add support for ordinals, fix this to propagate ordinals. Also figure out - // what we should do if we have two DllImport values with the same name but different - // ordinals. - let mut result = dylib_table + sess.compile_status()?; + Ok(dylib_table .into_iter() - .map(|(lib_name, imported_names)| { - let mut names = imported_names - .iter() - .map(|name| DllImport { name: *name, ordinal: None }) - .collect::>(); - names.sort_unstable_by(|a: &DllImport, b: &DllImport| { - match a.name.as_str().cmp(&b.name.as_str()) { - Ordering::Equal => a.ordinal.cmp(&b.ordinal), - x => x, - } - }); - (lib_name, names) + .map(|(name, imports)| { + (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) }) - .collect::>(); - result.sort_unstable_by(|a: &(String, Vec), b: &(String, Vec)| { - a.0.cmp(&b.0) - }); - result + .collect()) } /// Create a static archive. @@ -598,9 +513,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( codegen_results: &CodegenResults, out_filename: &Path, tempdir: &MaybeTempDir, -) { +) -> Result<(), ErrorReported> { let mut ab = - link_rlib::(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir); + link_rlib::(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir)?; let mut all_native_libs = vec![]; let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { @@ -648,6 +563,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( print_native_static_libs(sess, &all_native_libs); } } + + Ok(()) } fn escape_stdout_stderr_string(s: &[u8]) -> String { @@ -912,14 +829,23 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); - sess.struct_err(&format!( + let escaped_output = escape_stdout_stderr_string(&output); + let mut err = sess.struct_err(&format!( "linking with `{}` failed: {}", linker_path.display(), prog.status - )) - .note(&format!("{:?}", &cmd)) - .note(&escape_stdout_stderr_string(&output)) - .emit(); + )); + 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(); // If MSVC's `link.exe` was expected but the return code // is not a Microsoft LNK error then suggest a way to fix or @@ -1750,8 +1676,19 @@ fn add_rpath_args( // where extern libraries might live, based on the // add_lib_search_paths if sess.opts.cg.rpath { + let libs = codegen_results + .crate_info + .used_crates + .iter() + .filter_map(|cnum| { + codegen_results.crate_info.used_crate_source[cnum] + .dylib + .as_ref() + .map(|(path, _)| &**path) + }) + .collect::>(); let mut rpath_config = RPathConfig { - used_crates: &codegen_results.crate_info.used_crates_dynamic, + libs: &*libs, out_filename: out_filename.to_path_buf(), has_rpath: sess.target.has_rpath, is_like_osx: sess.target.is_like_osx, @@ -1779,11 +1716,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( codegen_results: &CodegenResults, ) -> Command { let crt_objects_fallback = crt_objects_fallback(sess, crate_type); - let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback); - // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction - // to the linker args construction. - assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp"); - let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor); + let cmd = &mut *super::linker::get_linker( + sess, + path, + flavor, + crt_objects_fallback, + &codegen_results.crate_info.target_cpu, + ); let link_output_kind = link_output_kind(sess, crate_type); // ------------ Early order-dependent options ------------ @@ -1793,7 +1732,11 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( // dynamic library. // Must be passed before any libraries to prevent the symbols to export from being thrown away, // at least on some platforms (e.g. windows-gnu). - cmd.export_symbols(tmpdir, crate_type); + cmd.export_symbols( + tmpdir, + crate_type, + &codegen_results.crate_info.exported_symbols[&crate_type], + ); // Can be used for adding custom CRT objects or overriding order-dependent options above. // FIXME: In practice built-in target specs use this for arbitrary order-independent options, @@ -1965,10 +1908,10 @@ fn add_order_independent_options( if flavor == LinkerFlavor::PtxLinker { // Provide the linker with fallback to internal `target-cpu`. cmd.arg("--fallback-arch"); - cmd.arg(&codegen_results.linker_info.target_cpu); + cmd.arg(&codegen_results.crate_info.target_cpu); } else if flavor == LinkerFlavor::BpfLinker { cmd.arg("--cpu"); - cmd.arg(&codegen_results.linker_info.target_cpu); + cmd.arg(&codegen_results.crate_info.target_cpu); cmd.arg("--cpu-features"); cmd.arg(match &sess.opts.cg.target_feature { feat if !feat.is_empty() => feat, @@ -1991,7 +1934,12 @@ fn add_order_independent_options( // Try to strip as much out of the generated object by removing unused // sections if possible. See more comments in linker.rs if !sess.link_dead_code() { - let keep_metadata = crate_type == CrateType::Dylib; + // If PGO is enabled sometimes gc_sections will remove the profile data section + // as it appears to be unused. This can then cause the PGO profile file to lose + // some functions. If we are generating a profile we shouldn't strip those metadata + // sections to ensure we have all the data for PGO. + let keep_metadata = + crate_type == CrateType::Dylib || sess.opts.cg.profile_generate.enabled(); cmd.gc_sections(keep_metadata); } @@ -2112,7 +2060,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // Invoke get_used_crates to ensure that we get a topological sorting of // crates. - let deps = &codegen_results.crate_info.used_crates_dynamic; + let deps = &codegen_results.crate_info.used_crates; // There's a few internal crates in the standard library (aka libcore and // libstd) which actually have a circular dependence upon one another. This @@ -2140,7 +2088,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let mut required = FxHashSet::default(); let info = &codegen_results.crate_info; - for &(cnum, _) in deps.iter().rev() { + for &cnum in deps.iter().rev() { if let Some(missing) = info.missing_lang_items.get(&cnum) { let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied()); required.extend(missing_crates); @@ -2167,7 +2115,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let mut compiler_builtins = None; - for &(cnum, _) in deps.iter() { + for &cnum in deps.iter() { if group_start == Some(cnum) { cmd.group_start(); } @@ -2379,9 +2327,9 @@ fn add_upstream_native_libraries( .find(|(ty, _)| *ty == crate_type) .expect("failed to find crate type in dependency format list"); - let crates = &codegen_results.crate_info.used_crates_static; + let crates = &codegen_results.crate_info.used_crates; let mut last = (NativeLibKind::Unspecified, None); - for &(cnum, _) in crates { + for &cnum in crates { for lib in codegen_results.crate_info.native_libraries[&cnum].iter() { let name = match lib.name { Some(l) => l, diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 43ff664c3e..9e1c6a169f 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -7,19 +7,21 @@ use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufWriter}; -use std::mem; use std::path::{Path, PathBuf}; +use std::{env, mem, str}; -use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::ty::TyCtxt; use rustc_serialize::{json, Encoder}; use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip}; +use rustc_session::search_paths::PathKind; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor}; +use cc::windows_registry; + /// Disables non-English messages from localized linkers. /// Such messages may cause issues with text encoding on Windows (#35785) /// and prevent inspection of linker output in case of errors, which we occasionally do. @@ -33,60 +35,121 @@ pub fn disable_localization(linker: &mut Command) { linker.env("VSLANG", "1033"); } -/// For all the linkers we support, and information they might -/// need out of the shared crate context before we get rid of it. -#[derive(Encodable, Decodable)] -pub struct LinkerInfo { - pub(super) target_cpu: String, - exports: FxHashMap>, -} - -impl LinkerInfo { - pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> LinkerInfo { - LinkerInfo { - target_cpu, - exports: tcx - .sess - .crate_types() - .iter() - .map(|&c| (c, exported_symbols(tcx, c))) - .collect(), +// The third parameter is for env vars, used on windows to set up the +// path for MSVC to find its DLLs, and gcc to find its bundled +// toolchain +pub fn get_linker<'a>( + sess: &'a Session, + linker: &Path, + flavor: LinkerFlavor, + self_contained: bool, + target_cpu: &'a str, +) -> Box { + let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); + + // If our linker looks like a batch script on Windows then to execute this + // we'll need to spawn `cmd` explicitly. This is primarily done to handle + // emscripten where the linker is `emcc.bat` and needs to be spawned as + // `cmd /c emcc.bat ...`. + // + // This worked historically but is needed manually since #42436 (regression + // was tagged as #42791) and some more info can be found on #44443 for + // emscripten itself. + 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() => { + Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path())) + } + _ => Command::new(linker), + }, + }; + + // UWP apps have API restrictions enforced during Store submissions. + // 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 let Some(ref tool) = msvc_tool { + let original_path = tool.path(); + if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { + let arch = match t.arch.as_str() { + "x86_64" => Some("x64"), + "x86" => Some("x86"), + "aarch64" => Some("arm64"), + "arm" => Some("arm"), + _ => None, + }; + if let Some(ref a) = arch { + // FIXME: Move this to `fn linker_with_args`. + let mut arg = OsString::from("/LIBPATH:"); + arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a)); + cmd.arg(&arg); + } else { + warn!("arch is not supported"); + } + } else { + warn!("MSVC root path lib location not found"); + } + } else { + warn!("link.exe not found"); } } - pub fn to_linker<'a>( - &'a self, - cmd: Command, - sess: &'a Session, - flavor: LinkerFlavor, - ) -> Box { - match flavor { - LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { - Box::new(MsvcLinker { cmd, sess, info: self }) as Box - } - LinkerFlavor::Em => Box::new(EmLinker { cmd, sess, info: self }) as Box, - LinkerFlavor::Gcc => { - Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: false }) - as Box + // The compiler's sysroot often has some bundled tools, so add it to the + // PATH for the child. + let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained); + let mut msvc_changed_path = false; + if sess.target.is_like_msvc { + if let Some(ref tool) = msvc_tool { + cmd.args(tool.args()); + for &(ref k, ref v) in tool.env() { + if k == "PATH" { + new_path.extend(env::split_paths(v)); + msvc_changed_path = true; + } else { + cmd.env(k, v); + } } + } + } - LinkerFlavor::Lld(LldFlavor::Ld) - | LinkerFlavor::Lld(LldFlavor::Ld64) - | LinkerFlavor::Ld => { - Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: true }) - as Box - } + if !msvc_changed_path { + if let Some(path) = env::var_os("PATH") { + new_path.extend(env::split_paths(&path)); + } + } + cmd.env("PATH", env::join_paths(new_path).unwrap()); - LinkerFlavor::Lld(LldFlavor::Wasm) => { - Box::new(WasmLd::new(cmd, sess, self)) as Box - } + // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction + // to the linker args construction. + assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp"); - LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box, + match flavor { + LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { + Box::new(MsvcLinker { cmd, sess }) as Box + } + LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box, + LinkerFlavor::Gcc => { + Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false }) + as Box + } - LinkerFlavor::BpfLinker => { - Box::new(BpfLinker { cmd, sess, info: self }) as Box - } + 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 } + + LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box, + + LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box, + + LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box, } } @@ -122,7 +185,7 @@ pub trait Linker { fn debuginfo(&mut self, strip: Strip); fn no_crt_objects(&mut self); fn no_default_libraries(&mut self); - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]); fn subsystem(&mut self, subsystem: &str); fn group_start(&mut self); fn group_end(&mut self); @@ -150,7 +213,7 @@ impl dyn Linker + '_ { pub struct GccLinker<'a> { cmd: Command, sess: &'a Session, - info: &'a LinkerInfo, + target_cpu: &'a str, hinted_static: bool, // Keeps track of the current hinting mode. // Link as ld is_ld: bool, @@ -225,7 +288,7 @@ impl<'a> GccLinker<'a> { }; self.linker_arg(&format!("-plugin-opt={}", opt_level)); - self.linker_arg(&format!("-plugin-opt=mcpu={}", self.info.target_cpu)); + self.linker_arg(&format!("-plugin-opt=mcpu={}", self.target_cpu)); } fn build_dylib(&mut self, out_filename: &Path) { @@ -554,7 +617,7 @@ impl<'a> Linker for GccLinker<'a> { } } - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { // Symbol visibility in object files typically takes care of this. if crate_type == CrateType::Executable && self.sess.target.override_export_symbols.is_none() { @@ -583,7 +646,7 @@ impl<'a> Linker for GccLinker<'a> { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); - for sym in self.info.exports[&crate_type].iter() { + for sym in symbols { debug!(" _{}", sym); writeln!(f, "_{}", sym)?; } @@ -598,7 +661,7 @@ impl<'a> Linker for GccLinker<'a> { // .def file similar to MSVC one but without LIBRARY section // because LD doesn't like when it's empty writeln!(f, "EXPORTS")?; - for symbol in self.info.exports[&crate_type].iter() { + for symbol in symbols { debug!(" _{}", symbol); writeln!(f, " {}", symbol)?; } @@ -611,9 +674,9 @@ impl<'a> Linker for GccLinker<'a> { let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); writeln!(f, "{{")?; - if !self.info.exports[&crate_type].is_empty() { + if !symbols.is_empty() { writeln!(f, " global:")?; - for sym in self.info.exports[&crate_type].iter() { + for sym in symbols { debug!(" {};", sym); writeln!(f, " {};", sym)?; } @@ -713,7 +776,6 @@ impl<'a> Linker for GccLinker<'a> { pub struct MsvcLinker<'a> { cmd: Command, sess: &'a Session, - info: &'a LinkerInfo, } impl<'a> Linker for MsvcLinker<'a> { @@ -887,7 +949,7 @@ impl<'a> Linker for MsvcLinker<'a> { // crates. Upstream rlibs may be linked statically to this dynamic library, // in which case they may continue to transitively be used and hence need // their symbols exported. - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) { // Symbol visibility takes care of this typically if crate_type == CrateType::Executable { return; @@ -901,7 +963,7 @@ impl<'a> Linker for MsvcLinker<'a> { // straight to exports. writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; - for symbol in self.info.exports[&crate_type].iter() { + for symbol in symbols { debug!(" _{}", symbol); writeln!(f, " {}", symbol)?; } @@ -954,7 +1016,6 @@ impl<'a> Linker for MsvcLinker<'a> { pub struct EmLinker<'a> { cmd: Command, sess: &'a Session, - info: &'a LinkerInfo, } impl<'a> Linker for EmLinker<'a> { @@ -1066,9 +1127,7 @@ impl<'a> Linker for EmLinker<'a> { self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]); } - fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) { - let symbols = &self.info.exports[&crate_type]; - + fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { debug!("EXPORTED SYMBOLS:"); self.cmd.arg("-s"); @@ -1110,11 +1169,10 @@ impl<'a> Linker for EmLinker<'a> { pub struct WasmLd<'a> { cmd: Command, sess: &'a Session, - info: &'a LinkerInfo, } impl<'a> WasmLd<'a> { - fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> { + fn new(mut cmd: Command, sess: &'a Session) -> WasmLd<'a> { // If the atomics feature is enabled for wasm then we need a whole bunch // of flags: // @@ -1147,7 +1205,7 @@ impl<'a> WasmLd<'a> { cmd.arg("--export=__tls_align"); cmd.arg("--export=__tls_base"); } - WasmLd { cmd, sess, info } + WasmLd { cmd, sess } } } @@ -1263,8 +1321,8 @@ impl<'a> Linker for WasmLd<'a> { fn no_default_libraries(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) { - for sym in self.info.exports[&crate_type].iter() { + fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + for sym in symbols { self.cmd.arg("--export").arg(&sym); } @@ -1287,7 +1345,7 @@ impl<'a> Linker for WasmLd<'a> { } } -fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec { +pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec { if let Some(ref exports) = tcx.sess.target.override_export_symbols { return exports.clone(); } @@ -1416,7 +1474,7 @@ impl<'a> Linker for PtxLinker<'a> { fn control_flow_guard(&mut self) {} - fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {} + fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {} fn subsystem(&mut self, _subsystem: &str) {} @@ -1430,7 +1488,6 @@ impl<'a> Linker for PtxLinker<'a> { pub struct BpfLinker<'a> { cmd: Command, sess: &'a Session, - info: &'a LinkerInfo, } impl<'a> Linker for BpfLinker<'a> { @@ -1517,11 +1574,11 @@ impl<'a> Linker for BpfLinker<'a> { fn control_flow_guard(&mut self) {} - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { + fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { let path = tmpdir.join("symbols"); let res: io::Result<()> = try { let mut f = BufWriter::new(File::create(&path)?); - for sym in self.info.exports[&crate_type].iter() { + for sym in symbols { writeln!(f, "{}", sym)?; } }; diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index 39b0ccd120..61c3ef62fb 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -4,11 +4,8 @@ use std::env; use std::fs; use std::path::{Path, PathBuf}; -use rustc_hir::def_id::CrateNum; -use rustc_middle::middle::cstore::LibSource; - pub struct RPathConfig<'a> { - pub used_crates: &'a [(CrateNum, LibSource)], + pub libs: &'a [&'a Path], pub out_filename: PathBuf, pub is_like_osx: bool, pub has_rpath: bool, @@ -23,9 +20,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec { debug!("preparing the RPATH!"); - let libs = config.used_crates; - let libs = libs.iter().filter_map(|&(_, ref l)| l.option()).collect::>(); - let rpaths = get_rpaths(config, &libs); + let rpaths = get_rpaths(config); let mut flags = rpaths_to_flags(&rpaths); // Use DT_RUNPATH instead of DT_RPATH if available @@ -52,17 +47,17 @@ fn rpaths_to_flags(rpaths: &[String]) -> Vec { ret } -fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec { +fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec { debug!("output: {:?}", config.out_filename.display()); debug!("libs:"); - for libpath in libs { + for libpath in config.libs { debug!(" {:?}", libpath.display()); } // Use relative paths to the libraries. Binaries can be moved // as long as they maintain the relative relationship to the // crates they depend on. - let rpaths = get_rpaths_relative_to_output(config, libs); + let rpaths = get_rpaths_relative_to_output(config); debug!("rpaths:"); for rpath in &rpaths { @@ -73,8 +68,8 @@ fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec { minimize_rpaths(&rpaths) } -fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec { - libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect() +fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec { + config.libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect() } fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> String { diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index 24c362db12..604f19144a 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -35,7 +35,7 @@ fn test_minimize2() { fn test_rpath_relative() { if cfg!(target_os = "macos") { let config = &mut RPathConfig { - used_crates: &[], + libs: &[], has_rpath: true, is_like_osx: true, linker_is_gnu: false, @@ -45,7 +45,7 @@ fn test_rpath_relative() { assert_eq!(res, "@loader_path/../lib"); } else { let config = &mut RPathConfig { - used_crates: &[], + libs: &[], out_filename: PathBuf::from("bin/rustc"), has_rpath: true, is_like_osx: false, diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index b2ecc3b0f3..4ef21449d2 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -180,7 +180,7 @@ fn exported_symbols_provider_local( symbols.push((exported_symbol, SymbolExportLevel::C)); } - if tcx.allocator_kind().is_some() { + if tcx.allocator_kind(()).is_some() { for method in ALLOCATOR_METHODS { let symbol_name = format!("__rust_{}", method.name); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); @@ -277,7 +277,7 @@ fn upstream_monomorphizations_provider( tcx: TyCtxt<'_>, (): (), ) -> DefIdMap, CrateNum>> { - let cnums = tcx.all_crate_nums(()); + let cnums = tcx.crates(()); let mut instances: DefIdMap> = Default::default(); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index ff4e640957..41823f7d80 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1,5 +1,4 @@ use super::link::{self, ensure_removed}; -use super::linker::LinkerInfo; use super::lto::{self, SerializedModule}; use super::symbol_export::symbol_name_for_instance_in_crate; @@ -430,8 +429,7 @@ pub fn start_async_codegen( let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins); let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins); - let linker_info = LinkerInfo::new(tcx, target_cpu); - let crate_info = CrateInfo::new(tcx); + let crate_info = CrateInfo::new(tcx, target_cpu); let regular_config = ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins); @@ -461,7 +459,6 @@ pub fn start_async_codegen( OngoingCodegen { backend, metadata, - linker_info, crate_info, coordinator_send, @@ -994,7 +991,7 @@ fn start_executing_work( } Lto::Fat | Lto::Thin => { exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { exported_symbols.insert(cnum, copy_symbols(cnum)); } Some(Arc::new(exported_symbols)) @@ -1799,7 +1796,6 @@ impl SharedEmitterMain { pub struct OngoingCodegen { pub backend: B, pub metadata: EncodedMetadata, - pub linker_info: LinkerInfo, pub crate_info: CrateInfo, pub coordinator_send: Sender>, pub codegen_worker_receive: Receiver>, @@ -1842,7 +1838,6 @@ impl OngoingCodegen { ( CodegenResults { metadata: self.metadata, - linker_info: self.linker_info, crate_info: self.crate_info, modules: compiled_modules.modules, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 38ab39febe..be2bf8b199 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -20,7 +20,6 @@ use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::cstore::EncodedMetadata; -use rustc_middle::middle::cstore::{self, LinkagePreference}; use rustc_middle::middle::lang_items; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; @@ -406,7 +405,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }; // `main` should respect same config for frame pointer elimination as rest of code - cx.set_frame_pointer_elimination(llfn); + cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); let llbb = Bx::append_block(&cx, llfn, "top"); @@ -518,7 +517,7 @@ pub fn codegen_crate( }); let allocator_module = if any_dynamic_crate { None - } else if let Some(kind) = tcx.allocator_kind() { + } else if let Some(kind) = tcx.allocator_kind(()) { let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); let mut modules = backend.new_metadata(tcx, &llmod_id); @@ -755,7 +754,13 @@ impl Drop for AbortCodegenOnDrop { } impl CrateInfo { - pub fn new(tcx: TyCtxt<'_>) -> CrateInfo { + pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo { + let exported_symbols = tcx + .sess + .crate_types() + .iter() + .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c))) + .collect(); let local_crate_name = tcx.crate_name(LOCAL_CRATE); let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); @@ -770,17 +775,33 @@ impl CrateInfo { subsystem.to_string() }); + // This list is used when generating the command line to pass through to + // system linker. The linker expects undefined symbols on the left of the + // command line to be defined in libraries on the right, not the other way + // around. For more info, see some comments in the add_used_library function + // below. + // + // In order to get this left-to-right dependency ordering, we use the reverse + // postorder of all crates putting the leaves at the right-most positions. + let used_crates = tcx + .postorder_cnums(()) + .iter() + .rev() + .copied() + .filter(|&cnum| !tcx.dep_kind(cnum).macros_only()) + .collect(); + let mut info = CrateInfo { + target_cpu, + exported_symbols, local_crate_name, - panic_runtime: None, compiler_builtins: None, profiler_runtime: None, is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(), crate_name: Default::default(), - used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic), - used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic), + used_crates, used_crate_source: Default::default(), lang_item_to_crate: Default::default(), missing_lang_items: Default::default(), @@ -789,7 +810,7 @@ impl CrateInfo { }; let lang_items = tcx.lang_items(); - let crates = tcx.crates(); + let crates = tcx.crates(()); let n_crates = crates.len(); info.native_libraries.reserve(n_crates); @@ -802,9 +823,6 @@ impl CrateInfo { .insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect()); info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string()); info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum)); - if tcx.is_panic_runtime(cnum) { - info.panic_runtime = Some(cnum); - } if tcx.is_compiler_builtins(cnum) { info.compiler_builtins = Some(cnum); } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 7b4b0821c4..81e905b1b5 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -1,10 +1,27 @@ // Type Names for Debug Info. +// Notes on targetting MSVC: +// In general, MSVC's debugger attempts to parse all arguments as C++ expressions, +// even if the argument is explicitly a symbol name. +// As such, there are many things that cause parsing issues: +// * `#` is treated as a special character for macros. +// * `{` or `<` at the beginning of a name is treated as an operator. +// * `>>` is always treated as a right-shift. +// * `[` in a name is treated like a regex bracket expression (match any char +// within the brackets). +// * `"` is treated as the start of a string. + use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt}; -use rustc_target::abi::{TagEncoding, Variants}; +use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_middle::ich::NodeIdHashingMode; +use rustc_middle::ty::layout::IntegerExt; +use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::ty::{self, AdtDef, ExistentialProjection, Ty, TyCtxt}; +use rustc_target::abi::{Integer, TagEncoding, Variants}; +use smallvec::SmallVec; use std::fmt::Write; @@ -17,6 +34,8 @@ pub fn compute_debuginfo_type_name<'tcx>( t: Ty<'tcx>, qualified: bool, ) -> String { + let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name"); + let mut result = String::with_capacity(64); let mut visited = FxHashSet::default(); push_debuginfo_type_name(tcx, t, qualified, &mut result, &mut visited); @@ -25,7 +44,7 @@ pub fn compute_debuginfo_type_name<'tcx>( // Pushes the name of the type as it should be stored in debuginfo on the // `output` String. See also compute_debuginfo_type_name(). -pub fn push_debuginfo_type_name<'tcx>( +fn push_debuginfo_type_name<'tcx>( tcx: TyCtxt<'tcx>, t: Ty<'tcx>, qualified: bool, @@ -34,13 +53,19 @@ pub fn push_debuginfo_type_name<'tcx>( ) { // When targeting MSVC, emit C++ style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let cpp_like_names = tcx.sess.target.is_like_msvc; + let cpp_like_names = cpp_like_names(tcx); match *t.kind() { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), - ty::Never => output.push('!'), + ty::Never => { + if cpp_like_names { + output.push_str("never$"); + } else { + output.push('!'); + } + } ty::Int(int_ty) => output.push_str(int_ty.name_str()), ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()), ty::Float(float_ty) => output.push_str(float_ty.name_str()), @@ -50,74 +75,98 @@ pub fn push_debuginfo_type_name<'tcx>( msvc_enum_fallback(tcx, t, def, substs, output, visited); } else { push_item_name(tcx, def.did, qualified, output); - push_type_params(tcx, substs, output, visited); + push_generic_params_internal(tcx, substs, output, visited); } } ty::Tuple(component_types) => { if cpp_like_names { - output.push_str("tuple<"); + output.push_str("tuple$<"); } else { output.push('('); } for component_type in component_types { push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); - output.push_str(", "); + push_arg_separator(cpp_like_names, output); } if !component_types.is_empty() { - output.pop(); - output.pop(); + pop_arg_separator(output); } if cpp_like_names { - output.push('>'); + push_close_angle_bracket(cpp_like_names, output); } else { output.push(')'); } } ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { - if !cpp_like_names { + if cpp_like_names { + match mutbl { + hir::Mutability::Not => output.push_str("ptr_const$<"), + hir::Mutability::Mut => output.push_str("ptr_mut$<"), + } + } else { output.push('*'); - } - match mutbl { - hir::Mutability::Not => output.push_str("const "), - hir::Mutability::Mut => output.push_str("mut "), + match mutbl { + hir::Mutability::Not => output.push_str("const "), + hir::Mutability::Mut => output.push_str("mut "), + } } - push_debuginfo_type_name(tcx, inner_type, true, output, visited); + push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); if cpp_like_names { - output.push('*'); + push_close_angle_bracket(cpp_like_names, output); } } ty::Ref(_, inner_type, mutbl) => { + // Slices and `&str` are treated like C++ pointers when computing debug + // info for MSVC debugger. However, wrapping these types' names in a synthetic type + // causes the .natvis engine for WinDbg to fail to display their data, so we opt these + // types out to aid debugging in MSVC. + let is_slice_or_str = match *inner_type.kind() { + ty::Slice(_) | ty::Str => true, + _ => false, + }; + if !cpp_like_names { output.push('&'); + output.push_str(mutbl.prefix_str()); + } else if !is_slice_or_str { + match mutbl { + hir::Mutability::Not => output.push_str("ref$<"), + hir::Mutability::Mut => output.push_str("ref_mut$<"), + } } - output.push_str(mutbl.prefix_str()); - push_debuginfo_type_name(tcx, inner_type, true, output, visited); + push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_names { - // Slices and `&str` are treated like C++ pointers when computing debug - // info for MSVC debugger. However, adding '*' at the end of these types' names - // causes the .natvis engine for WinDbg to fail to display their data, so we opt these - // types out to aid debugging in MSVC. - match *inner_type.kind() { - ty::Slice(_) | ty::Str => {} - _ => output.push('*'), - } + if cpp_like_names && !is_slice_or_str { + push_close_angle_bracket(cpp_like_names, output); } } ty::Array(inner_type, len) => { - output.push('['); - push_debuginfo_type_name(tcx, inner_type, true, output, visited); - output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))); - output.push(']'); + if cpp_like_names { + output.push_str("array$<"); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + match len.val { + ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(), + _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) + .unwrap(), + } + } else { + output.push('['); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + match len.val { + ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(), + _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) + .unwrap(), + } + } } ty::Slice(inner_type) => { if cpp_like_names { - output.push_str("slice<"); + output.push_str("slice$<"); } else { output.push('['); } @@ -125,19 +174,97 @@ pub fn push_debuginfo_type_name<'tcx>( push_debuginfo_type_name(tcx, inner_type, true, output, visited); if cpp_like_names { - output.push('>'); + push_close_angle_bracket(cpp_like_names, output); } else { output.push(']'); } } ty::Dynamic(ref trait_data, ..) => { + let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect(); + + let has_enclosing_parens = if cpp_like_names { + output.push_str("dyn$<"); + false + } else { + if trait_data.len() > 1 && auto_traits.len() != 0 { + // We need enclosing parens because there is more than one trait + output.push_str("(dyn "); + true + } else { + output.push_str("dyn "); + false + } + }; + if let Some(principal) = trait_data.principal() { let principal = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal); - push_item_name(tcx, principal.def_id, false, output); - push_type_params(tcx, principal.substs, output, visited); - } else { - output.push_str("dyn '_"); + push_item_name(tcx, principal.def_id, qualified, output); + let principal_has_generic_params = + push_generic_params_internal(tcx, principal.substs, output, visited); + + let projection_bounds: SmallVec<[_; 4]> = trait_data + .projection_bounds() + .map(|bound| { + let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder(); + (item_def_id, ty) + }) + .collect(); + + if projection_bounds.len() != 0 { + if principal_has_generic_params { + // push_generic_params_internal() above added a `>` but we actually + // want to add more items to that list, so remove that again. + pop_close_angle_bracket(output); + } + + for (item_def_id, ty) in projection_bounds { + push_arg_separator(cpp_like_names, output); + + if cpp_like_names { + output.push_str("assoc$<"); + push_item_name(tcx, item_def_id, false, output); + push_arg_separator(cpp_like_names, output); + push_debuginfo_type_name(tcx, ty, true, output, visited); + push_close_angle_bracket(cpp_like_names, output); + } else { + push_item_name(tcx, item_def_id, false, output); + output.push('='); + push_debuginfo_type_name(tcx, ty, true, output, visited); + } + } + + push_close_angle_bracket(cpp_like_names, output); + } + + if auto_traits.len() != 0 { + push_auto_trait_separator(cpp_like_names, output); + } + } + + if auto_traits.len() != 0 { + let mut auto_traits: SmallVec<[String; 4]> = auto_traits + .into_iter() + .map(|def_id| { + let mut name = String::with_capacity(20); + push_item_name(tcx, def_id, true, &mut name); + name + }) + .collect(); + auto_traits.sort_unstable(); + + for auto_trait in auto_traits { + output.push_str(&auto_trait); + push_auto_trait_separator(cpp_like_names, output); + } + + pop_auto_trait_separator(output); + } + + if cpp_like_names { + push_close_angle_bracket(cpp_like_names, output); + } else if has_enclosing_parens { + output.push(')'); } } ty::FnDef(..) | ty::FnPtr(_) => { @@ -155,30 +282,43 @@ pub fn push_debuginfo_type_name<'tcx>( // use a dummy string that should make it clear // that something unusual is going on if !visited.insert(t) { - output.push_str(""); + output.push_str(if cpp_like_names { + "recursive_type$" + } else { + "" + }); return; } - let sig = t.fn_sig(tcx); - output.push_str(sig.unsafety().prefix_str()); + let sig = + tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); - let abi = sig.abi(); - if abi != rustc_target::spec::abi::Abi::Rust { - output.push_str("extern \""); - output.push_str(abi.name()); - output.push_str("\" "); - } + if cpp_like_names { + // Format as a C++ function pointer: return_type (*)(params...) + if sig.output().is_unit() { + output.push_str("void"); + } else { + push_debuginfo_type_name(tcx, sig.output(), true, output, visited); + } + output.push_str(" (*)("); + } else { + output.push_str(sig.unsafety.prefix_str()); + + if sig.abi != rustc_target::spec::abi::Abi::Rust { + output.push_str("extern \""); + output.push_str(sig.abi.name()); + output.push_str("\" "); + } - output.push_str("fn("); + output.push_str("fn("); + } - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { push_debuginfo_type_name(tcx, parameter_type, true, output, visited); - output.push_str(", "); + push_arg_separator(cpp_like_names, output); } - output.pop(); - output.pop(); + pop_arg_separator(output); } if sig.c_variadic { @@ -191,7 +331,7 @@ pub fn push_debuginfo_type_name<'tcx>( output.push(')'); - if !sig.output().is_unit() { + if !cpp_like_names && !sig.output().is_unit() { output.push_str(" -> "); push_debuginfo_type_name(tcx, sig.output(), true, output, visited); } @@ -207,17 +347,14 @@ pub fn push_debuginfo_type_name<'tcx>( // processing visited.remove(t); } - ty::Closure(def_id, ..) => { - output.push_str(&format!( - "closure-{}", - tcx.def_key(def_id).disambiguated_data.disambiguator - )); - } - ty::Generator(def_id, ..) => { - output.push_str(&format!( - "generator-{}", - tcx.def_key(def_id).disambiguated_data.disambiguator - )); + ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => { + let key = tcx.def_key(def_id); + if qualified { + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + push_item_name(tcx, parent_def_id, true, output); + output.push_str("::"); + } + push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output); } // Type parameters from polymorphized functions. ty::Param(_) => { @@ -252,6 +389,10 @@ pub fn push_debuginfo_type_name<'tcx>( ) { let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error"); + output.push_str("enum$<"); + push_item_name(tcx, def.did, true, output); + push_generic_params_internal(tcx, substs, output, visited); + if let Variants::Multiple { tag_encoding: TagEncoding::Niche { dataful_variant, .. }, tag, @@ -271,57 +412,217 @@ pub fn push_debuginfo_type_name<'tcx>( let max = dataful_discriminant_range.end(); let max = tag.value.size(&tcx).truncate(*max); - output.push_str("enum$<"); - push_item_name(tcx, def.did, true, output); - push_type_params(tcx, substs, output, visited); - let dataful_variant_name = def.variants[*dataful_variant].ident.as_str(); - output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name)); + output.push_str(&format!(", {}, {}, {}", min, max, dataful_variant_name)); + } else if let Variants::Single { index: variant_idx } = &layout.variants { + // Uninhabited enums can't be constructed and should never need to be visualized so + // skip this step for them. + if def.variants.len() != 0 { + let variant = def.variants[*variant_idx].ident.as_str(); + + output.push_str(&format!(", {}", variant)); + } + } + push_close_angle_bracket(true, output); + } + + const NON_CPP_AUTO_TRAIT_SEPARATOR: &str = " + "; + + fn push_auto_trait_separator(cpp_like_names: bool, output: &mut String) { + if cpp_like_names { + push_arg_separator(cpp_like_names, output); } else { - output.push_str("enum$<"); - push_item_name(tcx, def.did, true, output); - push_type_params(tcx, substs, output, visited); - output.push('>'); + output.push_str(NON_CPP_AUTO_TRAIT_SEPARATOR); } } - fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { - if qualified { + fn pop_auto_trait_separator(output: &mut String) { + if output.ends_with(NON_CPP_AUTO_TRAIT_SEPARATOR) { + output.truncate(output.len() - NON_CPP_AUTO_TRAIT_SEPARATOR.len()); + } else { + pop_arg_separator(output); + } + } +} + +pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { + let def_key = tcx.def_key(def_id); + if qualified { + if let Some(parent) = def_key.parent { + push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); + output.push_str("::"); + } + } + + push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output); +} + +fn push_unqualified_item_name( + tcx: TyCtxt<'tcx>, + def_id: DefId, + disambiguated_data: DisambiguatedDefPathData, + output: &mut String, +) { + match disambiguated_data.data { + DefPathData::CrateRoot => { output.push_str(&tcx.crate_name(def_id.krate).as_str()); - for path_element in tcx.def_path(def_id).data { - write!(output, "::{}", path_element.data).unwrap(); + } + DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { + // Generators look like closures, but we want to treat them differently + // in the debug info. + if cpp_like_names(tcx) { + write!(output, "generator${}", disambiguated_data.disambiguator).unwrap(); + } else { + write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap(); } - } else { - output.push_str(&tcx.item_name(def_id).as_str()); } + _ => match disambiguated_data.data.name() { + DefPathDataName::Named(name) => { + output.push_str(&name.as_str()); + } + DefPathDataName::Anon { namespace } => { + if cpp_like_names(tcx) { + write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); + } else { + write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) + .unwrap(); + } + } + }, + }; +} + +// Pushes the generic parameters in the given `InternalSubsts` to the output string. +// This ignores region parameters, since they can't reliably be +// reconstructed for items from non-local crates. For local crates, this +// would be possible but with inlining and LTO we have to use the least +// common denominator - otherwise we would run into conflicts. +fn push_generic_params_internal<'tcx>( + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, + output: &mut String, + visited: &mut FxHashSet>, +) -> bool { + if substs.non_erasable_generics().next().is_none() { + return false; } - // Pushes the type parameters in the given `InternalSubsts` to the output string. - // This ignores region parameters, since they can't reliably be - // reconstructed for items from non-local crates. For local crates, this - // would be possible but with inlining and LTO we have to use the least - // common denominator - otherwise we would run into conflicts. - fn push_type_params<'tcx>( - tcx: TyCtxt<'tcx>, - substs: SubstsRef<'tcx>, - output: &mut String, - visited: &mut FxHashSet>, - ) { - if substs.types().next().is_none() { - return; + debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs)); + + let cpp_like_names = cpp_like_names(tcx); + + output.push('<'); + + for type_parameter in substs.non_erasable_generics() { + match type_parameter { + GenericArgKind::Type(type_parameter) => { + push_debuginfo_type_name(tcx, type_parameter, true, output, visited); + } + GenericArgKind::Const(ct) => { + push_const_param(tcx, ct, output); + } + other => bug!("Unexpected non-erasable generic: {:?}", other), } - output.push('<'); + push_arg_separator(cpp_like_names, output); + } + pop_arg_separator(output); + push_close_angle_bracket(cpp_like_names, output); + + true +} - for type_parameter in substs.types() { - push_debuginfo_type_name(tcx, type_parameter, true, output, visited); - output.push_str(", "); +fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: &'tcx ty::Const<'tcx>, output: &mut String) { + match ct.val { + ty::ConstKind::Param(param) => { + write!(output, "{}", param.name) } + _ => match ct.ty.kind() { + ty::Int(ity) => { + let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty); + let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; + write!(output, "{}", val) + } + ty::Uint(_) => { + let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty); + write!(output, "{}", val) + } + ty::Bool => { + let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap(); + write!(output, "{}", val) + } + _ => { + // If we cannot evaluate the constant to a known type, we fall back + // to emitting a stable hash value of the constant. This isn't very pretty + // but we get a deterministic, virtually unique value for the constant. + let hcx = &mut tcx.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(false, |hcx| { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + ct.val.hash_stable(hcx, &mut hasher); + }); + }); + // Let's only emit 64 bits of the hash value. That should be plenty for + // avoiding collisions and will make the emitted type names shorter. + let hash: u64 = hasher.finish(); + + if cpp_like_names(tcx) { + write!(output, "CONST${:x}", hash) + } else { + write!(output, "{{CONST#{:x}}}", hash) + } + } + }, + } + .unwrap(); +} +pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) { + let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name"); + let mut visited = FxHashSet::default(); + push_generic_params_internal(tcx, substs, output, &mut visited); +} + +fn push_close_angle_bracket(cpp_like_names: bool, output: &mut String) { + // MSVC debugger always treats `>>` as a shift, even when parsing templates, + // so add a space to avoid confusion. + if cpp_like_names && output.ends_with('>') { + output.push(' ') + }; + + output.push('>'); +} + +fn pop_close_angle_bracket(output: &mut String) { + assert!(output.ends_with('>'), "'output' does not end with '>': {}", output); + output.pop(); + if output.ends_with(' ') { output.pop(); - output.pop(); + } +} - output.push('>'); +fn push_arg_separator(cpp_like_names: bool, output: &mut String) { + // Natvis does not always like having spaces between parts of the type name + // and this causes issues when we need to write a typename in natvis, for example + // as part of a cast like the `HashMap` visualizer does. + if cpp_like_names { + output.push(','); + } else { + output.push_str(", "); + }; +} + +fn pop_arg_separator(output: &mut String) { + if output.ends_with(' ') { + output.pop(); } + + assert!(output.ends_with(',')); + + output.pop(); +} + +fn cpp_like_names(tcx: TyCtxt<'_>) -> bool { + tcx.sess.target.is_like_msvc } diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/glue.rs index b88de0b241..cf217b52c8 100644 --- a/compiler/rustc_codegen_ssa/src/glue.rs +++ b/compiler/rustc_codegen_ssa/src/glue.rs @@ -23,7 +23,12 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ty::Dynamic(..) => { // load size/align from vtable let vtable = info.unwrap(); - (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable)) + ( + meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE) + .get_usize(bx, vtable), + meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN) + .get_usize(bx, vtable), + ) } ty::Slice(_) | ty::Str => { let unit = layout.field(bx, 0); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index b6de12fa35..b6ee70c419 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -24,10 +24,10 @@ use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::CrateNum; use rustc_hir::LangItem; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::middle::cstore::{self, CrateSource, LibSource}; +use rustc_middle::middle::cstore::{self, CrateSource}; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::ty::query::Providers; -use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT}; +use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::utils::NativeLibKind; use rustc_span::symbol::Symbol; use std::path::{Path, PathBuf}; @@ -135,8 +135,9 @@ impl From<&cstore::NativeLib> for NativeLib { /// and the corresponding properties without referencing information outside of a `CrateInfo`. #[derive(Debug, Encodable, Decodable)] pub struct CrateInfo { + pub target_cpu: String, + pub exported_symbols: FxHashMap>, pub local_crate_name: Symbol, - pub panic_runtime: Option, pub compiler_builtins: Option, pub profiler_runtime: Option, pub is_no_builtins: FxHashSet, @@ -144,8 +145,7 @@ pub struct CrateInfo { pub crate_name: FxHashMap, pub used_libraries: Vec, pub used_crate_source: FxHashMap>, - pub used_crates_static: Vec<(CrateNum, LibSource)>, - pub used_crates_dynamic: Vec<(CrateNum, LibSource)>, + pub used_crates: Vec, pub lang_item_to_crate: FxHashMap, pub missing_lang_items: FxHashMap>, pub dependency_formats: Lrc, @@ -158,7 +158,6 @@ pub struct CodegenResults { pub allocator_module: Option, pub metadata_module: Option, pub metadata: rustc_middle::middle::cstore::EncodedMetadata, - pub linker_info: back::linker::LinkerInfo, pub crate_info: CrateInfo, } diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index bcc19c6a44..b392b2c4ab 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -1,18 +1,14 @@ use crate::traits::*; -use rustc_middle::ty::{self, Instance, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_target::abi::call::FnAbi; #[derive(Copy, Clone, Debug)] pub struct VirtualIndex(u64); -pub const DESTRUCTOR: VirtualIndex = VirtualIndex(0); -pub const SIZE: VirtualIndex = VirtualIndex(1); -pub const ALIGN: VirtualIndex = VirtualIndex(2); - impl<'a, 'tcx> VirtualIndex { pub fn from_index(index: usize) -> Self { - VirtualIndex(index as u64 + 3) + VirtualIndex(index as u64) } pub fn get_fn>( @@ -24,10 +20,11 @@ impl<'a, 'tcx> VirtualIndex { // Load the data pointer from the object. debug!("get_fn({:?}, {:?})", llvtable, self); - let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(bx.fn_ptr_backend_type(fn_abi))); + let llty = bx.fn_ptr_backend_type(fn_abi); + let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty)); let ptr_align = bx.tcx().data_layout.pointer_align.abi; let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]); - let ptr = bx.load(gep, ptr_align); + let ptr = bx.load(llty, gep, ptr_align); bx.nonnull_metadata(ptr); // Vtable loads are invariant. bx.set_invariant_load(ptr); @@ -42,10 +39,11 @@ impl<'a, 'tcx> VirtualIndex { // Load the data pointer from the object. debug!("get_int({:?}, {:?})", llvtable, self); - let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(bx.type_isize())); + let llty = bx.type_isize(); + let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty)); let usize_align = bx.tcx().data_layout.pointer_align.abi; let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]); - let ptr = bx.load(gep, usize_align); + let ptr = bx.load(llty, gep, usize_align); // Vtable loads are invariant. bx.set_invariant_load(ptr); ptr @@ -74,53 +72,13 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( return val; } - // Not in the cache; build it. - let nullptr = cx.const_null(cx.type_i8p_ext(cx.data_layout().instruction_address_space)); - - let methods_root; - let methods = if let Some(trait_ref) = trait_ref { - methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty)); - methods_root.iter() - } else { - (&[]).iter() - }; - - let methods = methods.cloned().map(|opt_mth| { - opt_mth.map_or(nullptr, |(def_id, substs)| { - cx.get_fn_addr( - ty::Instance::resolve_for_vtable( - cx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs, - ) - .unwrap() - .polymorphize(cx.tcx()), - ) - }) - }); - - let layout = cx.layout_of(ty); - // ///////////////////////////////////////////////////////////////////////////////////////////// - // If you touch this code, be sure to also make the corresponding changes to - // `get_vtable` in `rust_mir/interpret/traits.rs`. - // ///////////////////////////////////////////////////////////////////////////////////////////// - let components: Vec<_> = [ - cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)), - cx.const_usize(layout.size.bytes()), - cx.const_usize(layout.align.abi.bytes()), - ] - .iter() - .cloned() - .chain(methods) - .collect(); - - let vtable_const = cx.const_struct(&components, false); + let vtable_alloc_id = tcx.vtable_allocation(ty, trait_ref); + let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory(); + let vtable_const = cx.const_data_from_alloc(vtable_allocation); let align = cx.data_layout().pointer_align.abi; let vtable = cx.static_addr_of(vtable_const, align, Some("vtable")); cx.create_vtable_metadata(ty, vtable); - cx.vtables().borrow_mut().insert((ty, trait_ref), vtable); vtable } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 49b5e8466b..b6def164fa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -5,7 +5,7 @@ use super::FunctionCx; use crate::traits::*; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::vec::IndexVec; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Location, TerminatorKind}; @@ -16,7 +16,29 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, ) -> BitSet { let mir = fx.mir; - let mut analyzer = LocalAnalyzer::new(fx); + let dominators = mir.dominators(); + let locals = mir + .local_decls + .iter() + .map(|decl| { + let ty = fx.monomorphize(decl.ty); + let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span); + if layout.is_zst() { + LocalKind::ZST + } else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) { + LocalKind::Unused + } else { + LocalKind::Memory + } + }) + .collect(); + + let mut analyzer = LocalAnalyzer { fx, dominators, locals }; + + // Arguments get assigned to by means of the function being called + for arg in mir.args_iter() { + analyzer.assign(arg, mir::START_BLOCK.start_location()); + } // If there exists a local definition that dominates all uses of that local, // the definition should be visited first. Traverse blocks in preorder which @@ -25,76 +47,45 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( analyzer.visit_basic_block_data(bb, data); } - for (local, decl) in mir.local_decls.iter_enumerated() { - let ty = fx.monomorphize(decl.ty); - debug!("local {:?} has type `{}`", local, ty); - let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span); - if fx.cx.is_backend_immediate(layout) { - // These sorts of types are immediates that we can store - // in an Value without an alloca. - } else if fx.cx.is_backend_scalar_pair(layout) { - // We allow pairs and uses of any of their 2 fields. - } else { - // These sorts of types require an alloca. Note that - // is_llvm_immediate() may *still* be true, particularly - // for newtypes, but we currently force some types - // (e.g., structs) into an alloca unconditionally, just so - // that we don't have to deal with having two pathways - // (gep vs extractvalue etc). - analyzer.not_ssa(local); + let mut non_ssa_locals = BitSet::new_empty(analyzer.locals.len()); + for (local, kind) in analyzer.locals.iter_enumerated() { + if matches!(kind, LocalKind::Memory) { + non_ssa_locals.insert(local); } } - analyzer.non_ssa_locals + non_ssa_locals +} + +#[derive(Copy, Clone, PartialEq, Eq)] +enum LocalKind { + ZST, + /// A local that requires an alloca. + Memory, + /// A scalar or a scalar pair local that is neither defined nor used. + Unused, + /// A scalar or a scalar pair local with a single definition that dominates all uses. + SSA(mir::Location), } struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { fx: &'mir FunctionCx<'a, 'tcx, Bx>, dominators: Dominators, - non_ssa_locals: BitSet, - // The location of the first visited direct assignment to each - // local, or an invalid location (out of bounds `block` index). - first_assignment: IndexVec, + locals: IndexVec, } impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { - fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self { - let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); - let dominators = fx.mir.dominators(); - let mut analyzer = LocalAnalyzer { - fx, - dominators, - non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()), - first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls), - }; - - // Arguments get assigned to by means of the function being called - for arg in fx.mir.args_iter() { - analyzer.first_assignment[arg] = mir::START_BLOCK.start_location(); - } - - analyzer - } - - fn first_assignment(&self, local: mir::Local) -> Option { - let location = self.first_assignment[local]; - if location.block.index() < self.fx.mir.basic_blocks().len() { - Some(location) - } else { - None - } - } - - fn not_ssa(&mut self, local: mir::Local) { - debug!("marking {:?} as non-SSA", local); - self.non_ssa_locals.insert(local); - } - fn assign(&mut self, local: mir::Local, location: Location) { - if self.first_assignment(local).is_some() { - self.not_ssa(local); - } else { - self.first_assignment[local] = location; + let kind = &mut self.locals[local]; + match *kind { + LocalKind::ZST => {} + LocalKind::Memory => {} + LocalKind::Unused => { + *kind = LocalKind::SSA(location); + } + LocalKind::SSA(_) => { + *kind = LocalKind::Memory; + } } } @@ -175,11 +166,13 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> ) { debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue); - if let Some(index) = place.as_local() { - self.assign(index, location); - let decl_span = self.fx.mir.local_decls[index].source_info.span; - if !self.fx.rvalue_creates_operand(rvalue, decl_span) { - self.not_ssa(index); + if let Some(local) = place.as_local() { + self.assign(local, location); + if self.locals[local] != LocalKind::Memory { + let decl_span = self.fx.mir.local_decls[local].source_info.span; + if !self.fx.rvalue_creates_operand(rvalue, decl_span) { + self.locals[local] = LocalKind::Memory; + } } } else { self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location); @@ -204,32 +197,18 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> PlaceContext::NonMutatingUse( NonMutatingUseContext::Copy | NonMutatingUseContext::Move, - ) => { + ) => match &mut self.locals[local] { + LocalKind::ZST => {} + LocalKind::Memory => {} + LocalKind::SSA(def) if def.dominates(location, &self.dominators) => {} // Reads from uninitialized variables (e.g., in dead code, after // optimizations) require locals to be in (uninitialized) memory. // N.B., there can be uninitialized reads of a local visited after // an assignment to that local, if they happen on disjoint paths. - let ssa_read = match self.first_assignment(local) { - Some(assignment_location) => { - assignment_location.dominates(location, &self.dominators) - } - None => { - debug!("No first assignment found for {:?}", local); - // We have not seen any assignment to the local yet, - // but before marking not_ssa, check if it is a ZST, - // in which case we don't need to initialize the local. - let ty = self.fx.mir.local_decls[local].ty; - let ty = self.fx.monomorphize(ty); - - let is_zst = self.fx.cx.layout_of(ty).is_zst(); - debug!("is_zst: {}", is_zst); - is_zst - } - }; - if !ssa_read { - self.not_ssa(local); + kind @ (LocalKind::Unused | LocalKind::SSA(_)) => { + *kind = LocalKind::Memory; } - } + }, PlaceContext::MutatingUse( MutatingUseContext::Store @@ -246,16 +225,18 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> | NonMutatingUseContext::AddressOf | NonMutatingUseContext::Projection, ) => { - self.not_ssa(local); + self.locals[local] = LocalKind::Memory; } PlaceContext::MutatingUse(MutatingUseContext::Drop) => { - let ty = self.fx.mir.local_decls[local].ty; - let ty = self.fx.monomorphize(ty); - - // Only need the place if we're actually dropping it. - if self.fx.cx.type_needs_drop(ty) { - self.not_ssa(local); + let kind = &mut self.locals[local]; + if *kind != LocalKind::Memory { + let ty = self.fx.mir.local_decls[local].ty; + let ty = self.fx.monomorphize(ty); + if self.fx.cx.type_needs_drop(ty) { + // Only need the place if we're actually dropping it. + *kind = LocalKind::Memory; + } } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 93200bd1f2..b584801a62 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { PassMode::Direct(_) | PassMode::Pair(..) => { let op = self.codegen_consume(&mut bx, mir::Place::return_place().as_ref()); if let Ref(llval, _, align) = op.val { - bx.load(llval, align) + bx.load(bx.backend_type(op.layout), llval, align) } else { op.immediate_or_packed_pair(&mut bx) } @@ -287,8 +287,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { llval } }; - let addr = bx.pointercast(llslot, bx.type_ptr_to(bx.cast_backend_type(&cast_ty))); - bx.load(addr, self.fn_abi.ret.layout.align.abi) + let ty = bx.cast_backend_type(&cast_ty); + let addr = bx.pointercast(llslot, bx.type_ptr_to(ty)); + bx.load(ty, addr, self.fn_abi.ret.layout.align.abi) } }; bx.ret(llval); @@ -332,7 +333,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]); let vtable = args[1]; args = &args[..1]; - (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_abi), fn_abi) + ( + meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) + .get_fn(&mut bx, vtable, &fn_abi), + fn_abi, + ) } _ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])), }; @@ -1082,15 +1087,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if by_ref && !arg.is_indirect() { // Have to load the argument, maybe while casting it. if let PassMode::Cast(ty) = arg.mode { - let addr = bx.pointercast(llval, bx.type_ptr_to(bx.cast_backend_type(&ty))); - llval = bx.load(addr, align.min(arg.layout.align.abi)); + let llty = bx.cast_backend_type(&ty); + let addr = bx.pointercast(llval, bx.type_ptr_to(llty)); + llval = bx.load(llty, addr, align.min(arg.layout.align.abi)); } else { // We can't use `PlaceRef::load` here because the argument // may have a type we don't treat as immediate, but the ABI // used for this call is passing it by-value. In that case, // the load would just produce `OperandValue::Ref` instead // of the `OperandValue::Immediate` we need for the call. - llval = bx.load(llval, align); + llval = bx.load(bx.backend_type(arg.layout), llval, align); if let abi::Abi::Scalar(ref scalar) = arg.layout.abi { if scalar.is_bool() { bx.range_metadata(llval, 0..2); diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 6bb20545f0..c139f915e6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -274,7 +274,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match *elem { mir::ProjectionElem::Deref => { indirect_offsets.push(Size::ZERO); - place = place.project_deref(bx); + place = bx.load_operand(place).deref(bx.cx()); } mir::ProjectionElem::Field(field, _) => { let i = field.index(); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 8502309b90..56ff1b3934 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -448,15 +448,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if ty.is_unsafe_ptr() { // Some platforms do not support atomic operations on pointers, // so we cast to integer first... - let ptr_llty = bx.type_ptr_to(bx.type_isize()); + let llty = bx.type_isize(); + let ptr_llty = bx.type_ptr_to(llty); source = bx.pointercast(source, ptr_llty); - } - let result = bx.atomic_load(source, order, size); - if ty.is_unsafe_ptr() { + let result = bx.atomic_load(llty, source, order, size); // ... and then cast the result back to a pointer bx.inttoptr(result, bx.backend_type(layout)) } else { - result + bx.atomic_load(bx.backend_type(layout), source, order, size) } } else { return invalid_monomorphization(ty); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 25e84c38ed..3e8386bc88 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -90,10 +90,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { Abi::ScalarPair(ref a, _) => a, _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout), }; - let a = Scalar::from(Pointer::new( - bx.tcx().create_memory_alloc(data), - Size::from_bytes(start), - )); + let a = Scalar::from_pointer( + Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)), + &bx.tcx(), + ); let a_llval = bx.scalar_to_backend( a, a_scalar, @@ -289,6 +289,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { } match self { OperandValue::Ref(r, None, source_align) => { + if flags.contains(MemFlags::NONTEMPORAL) { + // HACK(nox): This is inefficient but there is no nontemporal memcpy. + let ty = bx.backend_type(dest.layout); + let ptr = bx.pointercast(r, bx.type_ptr_to(ty)); + let val = bx.load(ty, ptr, source_align); + bx.store_with_flags(val, dest.llval, dest.align, flags); + return; + } base::memcpy_ty(bx, dest.llval, dest.align, r, source_align, dest.layout, flags) } OperandValue::Ref(_, Some(_), _) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index a9e7ebf6d4..66d9d1a1e0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -402,18 +402,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { downcast } - pub fn project_deref>(&self, bx: &mut Bx) -> Self { - let target_ty = self.layout.ty.builtin_deref(true).expect("failed to deref"); - let layout = bx.layout_of(target_ty.ty); - - PlaceRef { - llval: bx.load(self.llval, self.align), - llextra: None, - layout, - align: layout.align.abi, - } - } - pub fn storage_live>(&self, bx: &mut Bx) { bx.lifetime_start(self.llval, self.layout.size); } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 29b2db5d4d..f0c232a97b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -137,9 +137,15 @@ pub trait BuilderMethods<'a, 'tcx>: 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 load(&mut self, ptr: Self::Value, align: Align) -> Self::Value; - fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value; - fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> 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; + fn atomic_load( + &mut self, + ty: Self::Type, + ptr: Self::Value, + order: AtomicOrdering, + size: Size, + ) -> Self::Value; fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>) -> OperandRef<'tcx, Self::Value>; diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 6b58dea794..20f6618712 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -26,6 +26,8 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_to_opt_uint(&self, v: Self::Value) -> Option; fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option; + fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value; + fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value; fn from_const_alloc( &self, diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index 6fff64bfcb..46f2adbe55 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -16,7 +16,7 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn sess(&self) -> &Session; fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>; fn used_statics(&self) -> &RefCell>; - fn set_frame_pointer_elimination(&self, llfn: Self::Function); + fn set_frame_pointer_type(&self, llfn: Self::Function); fn apply_target_cpu_attr(&self, llfn: Self::Function); fn create_used_variable(&self); /// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists. diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index c35a164bb3..112b94f6e0 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -17,7 +17,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" } rustc_graphviz = { path = "../rustc_graphviz" } cfg-if = "0.1.2" -crossbeam-utils = { version = "0.8", features = ["nightly"] } stable_deref_trait = "1.0.0" rayon = { version = "0.3.1", package = "rustc-rayon" } rayon-core = { version = "0.3.1", package = "rustc-rayon-core" } diff --git a/compiler/rustc_data_structures/src/captures.rs b/compiler/rustc_data_structures/src/captures.rs index 26b90ebfd5..677ccb3145 100644 --- a/compiler/rustc_data_structures/src/captures.rs +++ b/compiler/rustc_data_structures/src/captures.rs @@ -3,8 +3,6 @@ /// Basically a workaround; see [this comment] for details. /// /// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999 -// FIXME(eddyb) false positive, the lifetime parameter is "phantom" but needed. -#[allow(unused_lifetimes)] pub trait Captures<'a> {} impl<'a, T: ?Sized> Captures<'a> for T {} diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 16151e9dca..041d52aa20 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -7,23 +7,26 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(allow_internal_unstable)] #![feature(array_windows)] +#![feature(associated_type_bounds)] +#![feature(auto_traits)] +#![feature(bool_to_option)] +#![feature(const_panic)] #![feature(control_flow_enum)] +#![feature(core_intrinsics)] +#![feature(extend_one)] +#![feature(hash_raw_entry)] #![feature(in_band_lifetimes)] +#![feature(iter_map_while)] +#![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] -#![feature(auto_traits)] +#![feature(min_type_alias_impl_trait)] +#![feature(new_uninit)] #![feature(nll)] -#![feature(allow_internal_unstable)] -#![feature(hash_raw_entry)] -#![feature(core_intrinsics)] +#![feature(once_cell)] #![feature(test)] -#![feature(associated_type_bounds)] #![feature(thread_id_value)] -#![feature(extend_one)] -#![feature(const_panic)] -#![feature(new_uninit)] -#![feature(once_cell)] -#![feature(maybe_uninit_uninit_array)] #![allow(rustc::default_hash_types)] #![deny(unaligned_references)] diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 05b1a85381..25b7a84b3a 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -418,6 +418,7 @@ impl ObligationForest { /// be called in a loop until `outcome.stalled` is false. /// /// This _cannot_ be unrolled (presently, at least). + #[inline(never)] pub fn process_obligations(&mut self, processor: &mut P) -> OUT where P: ObligationProcessor, @@ -671,6 +672,7 @@ impl ObligationForest { self.reused_node_vec = node_rewrites; } + #[inline(never)] fn apply_rewrites(&mut self, node_rewrites: &[usize]) { let orig_nodes_len = node_rewrites.len(); diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 51f851dc94..ef101c56ab 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -94,31 +94,34 @@ use std::process; use std::sync::Arc; use std::time::{Duration, Instant}; -use measureme::{EventId, EventIdBuilder, Profiler, SerializableString, StringId}; +pub use measureme::EventId; +use measureme::{EventIdBuilder, Profiler, SerializableString, StringId}; use parking_lot::RwLock; bitflags::bitflags! { struct EventFilter: u32 { - const GENERIC_ACTIVITIES = 1 << 0; - const QUERY_PROVIDERS = 1 << 1; - const QUERY_CACHE_HITS = 1 << 2; - const QUERY_BLOCKED = 1 << 3; - const INCR_CACHE_LOADS = 1 << 4; + const GENERIC_ACTIVITIES = 1 << 0; + const QUERY_PROVIDERS = 1 << 1; + const QUERY_CACHE_HITS = 1 << 2; + const QUERY_BLOCKED = 1 << 3; + const INCR_CACHE_LOADS = 1 << 4; - const QUERY_KEYS = 1 << 5; - const FUNCTION_ARGS = 1 << 6; - const LLVM = 1 << 7; + const QUERY_KEYS = 1 << 5; + const FUNCTION_ARGS = 1 << 6; + const LLVM = 1 << 7; + const INCR_RESULT_HASHING = 1 << 8; const DEFAULT = Self::GENERIC_ACTIVITIES.bits | Self::QUERY_PROVIDERS.bits | Self::QUERY_BLOCKED.bits | - Self::INCR_CACHE_LOADS.bits; + Self::INCR_CACHE_LOADS.bits | + Self::INCR_RESULT_HASHING.bits; const ARGS = Self::QUERY_KEYS.bits | Self::FUNCTION_ARGS.bits; } } -// keep this in sync with the `-Z self-profile-events` help message in librustc_session/options.rs +// keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("none", EventFilter::empty()), ("all", EventFilter::all()), @@ -132,6 +135,7 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("function-args", EventFilter::FUNCTION_ARGS), ("args", EventFilter::ARGS), ("llvm", EventFilter::LLVM), + ("incr-result-hashing", EventFilter::INCR_RESULT_HASHING), ]; /// Something that uniquely identifies a query invocation. @@ -248,6 +252,15 @@ impl SelfProfilerRef { }) } + /// Start profiling with some event filter for a given event. Profiling continues until the + /// TimingGuard returned from this call is dropped. + #[inline(always)] + pub fn generic_activity_with_event_id(&self, event_id: EventId) -> TimingGuard<'_> { + self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| { + TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id) + }) + } + /// Start profiling a generic activity. Profiling continues until the /// TimingGuard returned from this call is dropped. #[inline(always)] @@ -337,6 +350,19 @@ impl SelfProfilerRef { }) } + /// Start profiling how long it takes to hash query results for incremental compilation. + /// Profiling continues until the TimingGuard returned from this call is dropped. + #[inline(always)] + pub fn incr_result_hashing(&self) -> TimingGuard<'_> { + self.exec(EventFilter::INCR_RESULT_HASHING, |profiler| { + TimingGuard::start( + profiler, + profiler.incremental_result_hashing_event_kind, + EventId::INVALID, + ) + }) + } + #[inline(always)] fn instant_query_event( &self, @@ -364,6 +390,14 @@ impl SelfProfilerRef { } } + /// Gets a `StringId` for the given string. This method makes sure that + /// any strings going through it will only be allocated once in the + /// profiling data. + /// Returns `None` if the self-profiling is not enabled. + pub fn get_or_alloc_cached_string(&self, s: &str) -> Option { + self.profiler.as_ref().map(|p| p.get_or_alloc_cached_string(s)) + } + #[inline] pub fn enabled(&self) -> bool { self.profiler.is_some() @@ -388,6 +422,7 @@ pub struct SelfProfiler { query_event_kind: StringId, generic_activity_event_kind: StringId, incremental_load_result_event_kind: StringId, + incremental_result_hashing_event_kind: StringId, query_blocked_event_kind: StringId, query_cache_hit_event_kind: StringId, } @@ -408,6 +443,8 @@ impl SelfProfiler { let query_event_kind = profiler.alloc_string("Query"); let generic_activity_event_kind = profiler.alloc_string("GenericActivity"); let incremental_load_result_event_kind = profiler.alloc_string("IncrementalLoadResult"); + let incremental_result_hashing_event_kind = + profiler.alloc_string("IncrementalResultHashing"); let query_blocked_event_kind = profiler.alloc_string("QueryBlocked"); let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit"); @@ -451,6 +488,7 @@ impl SelfProfiler { query_event_kind, generic_activity_event_kind, incremental_load_result_event_kind, + incremental_result_hashing_event_kind, query_blocked_event_kind, query_cache_hit_event_kind, }) diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index 01cd1cec92..e92db9ea12 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -1,6 +1,5 @@ //! A variant of `SortedMap` that preserves insertion order. -use std::borrow::Borrow; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; @@ -76,11 +75,7 @@ impl SortedIndexMultiMap { /// /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. - pub fn get_by_key(&'a self, key: &Q) -> impl 'a + Iterator - where - Q: Ord + ?Sized, - K: Borrow, - { + pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator { self.get_by_key_enumerated(key).map(|(_, v)| v) } @@ -89,77 +84,12 @@ impl SortedIndexMultiMap { /// /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. - pub fn get_by_key_enumerated(&self, key: &Q) -> impl '_ + Iterator - where - Q: Ord + ?Sized, - K: Borrow, - { - // FIXME: This should be in the standard library as `equal_range`. See rust-lang/rfcs#2184. - match self.binary_search_idx(key) { - Err(_) => self.idxs_to_items_enumerated(&[]), - - Ok(idx) => { - let start = self.find_lower_bound(key, idx); - let end = self.find_upper_bound(key, idx); - self.idxs_to_items_enumerated(&self.idx_sorted_by_item_key[start..end]) - } - } - } - - fn binary_search_idx(&self, key: &Q) -> Result - where - Q: Ord + ?Sized, - K: Borrow, - { - self.idx_sorted_by_item_key.binary_search_by(|&idx| self.items[idx].0.borrow().cmp(key)) - } - - /// Returns the index into the `idx_sorted_by_item_key` array of the first item equal to - /// `key`. - /// - /// `initial` must be an index into that same array for an item that is equal to `key`. - fn find_lower_bound(&self, key: &Q, initial: usize) -> usize - where - Q: Ord + ?Sized, - K: Borrow, - { - debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key); - - // FIXME: At present, this uses linear search, meaning lookup is only `O(log n)` if duplicate - // entries are rare. It would be better to start with a linear search for the common case but - // fall back to an exponential search if many duplicates are found. This applies to - // `upper_bound` as well. - let mut start = initial; - while start != 0 && self.items[self.idx_sorted_by_item_key[start - 1]].0.borrow() == key { - start -= 1; - } - - start - } - - /// Returns the index into the `idx_sorted_by_item_key` array of the first item greater than - /// `key`, or `self.len()` if no such item exists. - /// - /// `initial` must be an index into that same array for an item that is equal to `key`. - fn find_upper_bound(&self, key: &Q, initial: usize) -> usize - where - Q: Ord + ?Sized, - K: Borrow, - { - debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key); - - // See the FIXME for `find_lower_bound`. - let mut end = initial + 1; - let len = self.items.len(); - while end < len && self.items[self.idx_sorted_by_item_key[end]].0.borrow() == key { - end += 1; - } - - end - } - - fn idxs_to_items_enumerated(&'a self, idxs: &'a [I]) -> impl 'a + Iterator { - idxs.iter().map(move |&idx| (idx, &self.items[idx].1)) + pub fn get_by_key_enumerated(&'a self, key: K) -> impl '_ + Iterator { + let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key); + self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| { + let (k, v) = &self.items[i]; + (k == &key).then_some((i, v)) + }) } } diff --git a/compiler/rustc_data_structures/src/sorted_map/tests.rs b/compiler/rustc_data_structures/src/sorted_map/tests.rs index 7d91e1fdce..1e977d709f 100644 --- a/compiler/rustc_data_structures/src/sorted_map/tests.rs +++ b/compiler/rustc_data_structures/src/sorted_map/tests.rs @@ -14,11 +14,11 @@ fn test_sorted_index_multi_map() { } // `get_by_key` works. - assert_eq!(set.get_by_key(&3).copied().collect::>(), vec![0]); - assert!(set.get_by_key(&4).next().is_none()); + assert_eq!(set.get_by_key(3).copied().collect::>(), vec![0]); + assert!(set.get_by_key(4).next().is_none()); // `get_by_key` returns items in insertion order. - let twos: Vec<_> = set.get_by_key_enumerated(&2).collect(); + let twos: Vec<_> = set.get_by_key_enumerated(2).collect(); let idxs: Vec = twos.iter().map(|(i, _)| *i).collect(); let values: Vec = twos.iter().map(|(_, &v)| v).collect(); diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index 73b04d3329..cc7ec9432f 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -1,6 +1,7 @@ use std::borrow::Borrow; +use std::fmt::Debug; use std::iter::FromIterator; -use std::slice::{Iter, IterMut}; +use std::slice::Iter; use std::vec::IntoIter; use crate::stable_hasher::{HashStable, StableHasher}; @@ -12,7 +13,8 @@ pub struct VecMap(Vec<(K, V)>); impl VecMap where - K: PartialEq, + K: Debug + PartialEq, + V: Debug, { pub fn new() -> Self { VecMap(Default::default()) @@ -37,14 +39,31 @@ where self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1) } - /// Returns the value corresponding to the supplied predicate filter. + /// Returns the any value corresponding to the supplied predicate filter. /// /// The supplied predicate will be applied to each (key, value) pair and it will return a /// reference to the values where the predicate returns `true`. - pub fn get_by(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> { + pub fn any_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> { self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1) } + /// Returns the value corresponding to the supplied predicate filter. It crashes if there's + /// more than one matching element. + /// + /// The supplied predicate will be applied to each (key, value) pair and it will return a + /// reference to the value where the predicate returns `true`. + pub fn get_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> { + let mut filter = self.0.iter().filter(|kv| predicate(kv)); + let (_, value) = filter.next()?; + // This should return just one element, otherwise it's a bug + assert!( + filter.next().is_none(), + "Collection {:?} should have just one matching element", + self + ); + Some(value) + } + /// Returns `true` if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, @@ -67,9 +86,13 @@ where self.into_iter() } - pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> { + pub fn iter_mut(&mut self) -> impl Iterator { self.into_iter() } + + pub fn retain(&mut self, f: impl Fn(&(K, V)) -> bool) { + self.0.retain(f) + } } impl Default for VecMap { @@ -108,12 +131,12 @@ impl<'a, K, V> IntoIterator for &'a VecMap { } impl<'a, K, V> IntoIterator for &'a mut VecMap { - type Item = &'a mut (K, V); - type IntoIter = IterMut<'a, (K, V)>; + type Item = (&'a K, &'a mut V); + type IntoIter = impl Iterator; #[inline] fn into_iter(self) -> Self::IntoIter { - self.0.iter_mut() + self.0.iter_mut().map(|(k, v)| (&*k, v)) } } @@ -127,13 +150,15 @@ impl IntoIterator for VecMap { } } -impl Extend<(K, V)> for VecMap { +impl Extend<(K, V)> for VecMap { fn extend>(&mut self, iter: I) { - self.0.extend(iter); + for (k, v) in iter { + self.insert(k, v); + } } - fn extend_one(&mut self, item: (K, V)) { - self.0.extend_one(item); + fn extend_one(&mut self, (k, v): (K, V)) { + self.insert(k, v); } fn extend_reserve(&mut self, additional: usize) { diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index c521f2041d..93c6ec04e4 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -34,8 +34,6 @@ rustc_interface = { path = "../rustc_interface" } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -rustc_mir_build = { path = "../rustc_mir_build" } -rustc_typeck = { path = "../rustc_typeck" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index b943977e4c..326fefa59a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -29,7 +29,7 @@ use rustc_middle::middle::cstore::MetadataLoader; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_serialize::json::{self, ToJson}; -use rustc_session::config::nightly_options; +use rustc_session::config::{nightly_options, CG_OPTIONS, DB_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths}; use rustc_session::getopts; use rustc_session::lint::{Lint, LintId}; @@ -46,7 +46,6 @@ use std::ffi::OsString; use std::fs; use std::io::{self, Read, Write}; use std::lazy::SyncLazy; -use std::mem; use std::panic::{self, catch_unwind}; use std::path::PathBuf; use std::process::{self, Command, Stdio}; @@ -316,12 +315,12 @@ fn run_compiler( if let Some(ppm) = &sess.opts.pretty { if ppm.needs_ast_map() { + let expanded_crate = queries.expansion()?.peek().0.clone(); queries.global_ctxt()?.peek_mut().enter(|tcx| { - let expanded_crate = queries.expansion()?.take().0; pretty::print_after_hir_lowering( tcx, compiler.input(), - &expanded_crate, + &*expanded_crate, *ppm, compiler.output_file().as_ref().map(|p| &**p), ); @@ -377,12 +376,6 @@ fn run_compiler( queries.global_ctxt()?; - // Drop AST after creating GlobalCtxt to free memory - { - let _timer = sess.prof.generic_activity("drop_ast"); - mem::drop(queries.expansion()?.take()); - } - if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json { return early_exit(); } @@ -528,8 +521,12 @@ fn stderr_isatty() -> bool { } fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { - let normalised = - if code.starts_with('E') { code.to_string() } else { format!("E{0:0>4}", code) }; + let upper_cased_code = code.to_ascii_uppercase(); + let normalised = if upper_cased_code.starts_with('E') { + upper_cased_code + } else { + format!("E{0:0>4}", code) + }; match registry.try_find_description(&normalised) { Ok(Some(description)) => { let mut is_in_code_block = false; @@ -1013,9 +1010,18 @@ pub fn handle_options(args: &[String]) -> Option { for option in config::rustc_optgroups() { (option.apply)(&mut options); } - let matches = options - .parse(args) - .unwrap_or_else(|f| early_error(ErrorOutputType::default(), &f.to_string())); + let matches = options.parse(args).unwrap_or_else(|e| { + let msg = match e { + getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS + .iter() + .map(|&(name, ..)| ('C', name)) + .chain(DB_OPTIONS.iter().map(|&(name, ..)| ('Z', name))) + .find(|&(_, name)| *opt == name.replace("_", "-")) + .map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)), + _ => None, + }; + early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string())); + }); // For all options we just parsed, we check a few aspects: // @@ -1163,23 +1169,26 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { static DEFAULT_HOOK: SyncLazy) + Sync + Send + 'static>> = SyncLazy::new(|| { let hook = panic::take_hook(); - panic::set_hook(Box::new(|info| report_ice(info, BUG_REPORT_URL))); + panic::set_hook(Box::new(|info| { + // Invoke the default handler, which prints the actual panic message and optionally a backtrace + (*DEFAULT_HOOK)(info); + + // Separate the output with an empty line + eprintln!(); + + // Print the ICE message + report_ice(info, BUG_REPORT_URL); + })); hook }); -/// Prints the ICE message, including backtrace and query stack. +/// Prints the ICE message, including query stack, but without backtrace. /// /// The message will point the user at `bug_report_url` to report the ICE. /// /// When `install_ice_hook` is called, this function will be called as the panic /// hook. pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { - // Invoke the default handler, which prints the actual panic message and optionally a backtrace - (*DEFAULT_HOOK)(info); - - // Separate the output with an empty line - eprintln!(); - let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( rustc_errors::ColorConfig::Auto, None, @@ -1296,10 +1305,60 @@ pub fn init_env_logger(env: &str) { tracing::subscriber::set_global_default(subscriber).unwrap(); } +#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))] +mod signal_handler { + extern "C" { + fn backtrace_symbols_fd( + buffer: *const *mut libc::c_void, + size: libc::c_int, + fd: libc::c_int, + ); + } + + extern "C" fn print_stack_trace(_: libc::c_int) { + const MAX_FRAMES: usize = 256; + static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] = + [std::ptr::null_mut(); MAX_FRAMES]; + unsafe { + let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32); + if depth == 0 { + return; + } + backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2); + } + } + + // When an error signal (such as SIGABRT or SIGSEGV) is delivered to the + // process, print a stack trace and then exit. + pub(super) fn install() { + unsafe { + const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; + let mut alt_stack: libc::stack_t = std::mem::zeroed(); + alt_stack.ss_sp = + std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) + as *mut libc::c_void; + alt_stack.ss_size = ALT_STACK_SIZE; + libc::sigaltstack(&mut alt_stack, std::ptr::null_mut()); + + let mut sa: libc::sigaction = std::mem::zeroed(); + sa.sa_sigaction = print_stack_trace as libc::sighandler_t; + sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK; + libc::sigemptyset(&mut sa.sa_mask); + libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); + } + } +} + +#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))] +mod signal_handler { + pub(super) fn install() {} +} + pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); init_rustc_env_logger(); + signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); let exit_code = catch_with_exit_code(|| { diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index a2b4f3fcf7..bf131914b9 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -293,18 +293,6 @@ struct TypedAnnotation<'tcx> { maybe_typeck_results: Cell>>, } -impl<'tcx> TypedAnnotation<'tcx> { - /// Gets the type-checking results for the current body. - /// As this will ICE if called outside bodies, only call when working with - /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). - #[track_caller] - fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> { - self.maybe_typeck_results - .get() - .expect("`TypedAnnotation::typeck_results` called outside of body") - } -} - impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> { fn sess(&self) -> &Session { &self.tcx.sess @@ -336,10 +324,20 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { } fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) { if let pprust_hir::AnnNode::Expr(expr) = node { - s.s.space(); - s.s.word("as"); - s.s.space(); - s.s.word(self.typeck_results().expr_ty(expr).to_string()); + let typeck_results = self.maybe_typeck_results.get().or_else(|| { + self.tcx + .hir() + .maybe_body_owned_by(self.tcx.hir().local_def_id_to_hir_id(expr.hir_id.owner)) + .map(|body_id| self.tcx.typeck_body(body_id)) + }); + + if let Some(typeck_results) = typeck_results { + s.s.space(); + s.s.word("as"); + s.s.space(); + s.s.word(typeck_results.expr_ty(expr).to_string()); + } + s.pclose(); } } diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index f10efd8323..1aa5f99597 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -361,6 +361,7 @@ E0626: include_str!("./error_codes/E0626.md"), E0627: include_str!("./error_codes/E0627.md"), E0628: include_str!("./error_codes/E0628.md"), E0631: include_str!("./error_codes/E0631.md"), +E0632: include_str!("./error_codes/E0632.md"), E0633: include_str!("./error_codes/E0633.md"), E0634: include_str!("./error_codes/E0634.md"), E0635: include_str!("./error_codes/E0635.md"), @@ -417,6 +418,7 @@ E0716: include_str!("./error_codes/E0716.md"), E0718: include_str!("./error_codes/E0718.md"), E0719: include_str!("./error_codes/E0719.md"), E0720: include_str!("./error_codes/E0720.md"), +E0722: include_str!("./error_codes/E0722.md"), E0724: include_str!("./error_codes/E0724.md"), E0725: include_str!("./error_codes/E0725.md"), E0727: include_str!("./error_codes/E0727.md"), @@ -448,6 +450,7 @@ E0753: include_str!("./error_codes/E0753.md"), E0754: include_str!("./error_codes/E0754.md"), E0755: include_str!("./error_codes/E0755.md"), E0756: include_str!("./error_codes/E0756.md"), +E0757: include_str!("./error_codes/E0757.md"), E0758: include_str!("./error_codes/E0758.md"), E0759: include_str!("./error_codes/E0759.md"), E0760: include_str!("./error_codes/E0760.md"), @@ -609,7 +612,7 @@ E0783: include_str!("./error_codes/E0783.md"), // E0540, // multiple rustc_deprecated attributes E0544, // multiple stability levels // E0548, // replaced with a generic attribute input check - E0553, // multiple rustc_const_unstable attributes +// E0553, // multiple rustc_const_unstable attributes // E0555, // replaced with a generic attribute input check // E0558, // replaced with a generic attribute input check // E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 @@ -620,12 +623,9 @@ E0783: include_str!("./error_codes/E0783.md"), // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) E0625, // thread-local statics cannot be accessed at compile-time - E0629, // missing 'feature' (rustc_const_unstable) - // rustc_const_unstable attribute must be paired with stable/unstable - // attribute - E0630, - E0632, // cannot provide explicit generic arguments when `impl Trait` is - // used in argument position +// E0629, // missing 'feature' (rustc_const_unstable) +// E0630, // rustc_const_unstable attribute must be paired with stable/unstable + // attribute E0640, // infer outlives requirements // E0645, // trait aliases not finished E0667, // `impl Trait` in projections @@ -636,10 +636,8 @@ E0783: include_str!("./error_codes/E0783.md"), E0711, // a feature has been declared with conflicting stability attributes E0717, // rustc_promotable without stability attribute // E0721, // `await` keyword - E0722, // Malformed `#[optimize]` attribute // E0723, unstable feature in `const` context E0726, // non-explicit (not `'_`) elided lifetime in unsupported position // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. - E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]` E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`. } diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 42baa65bf9..ec86ec44ec 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -1,4 +1,4 @@ -An invalid number of type parameters was given to an intrinsic function. +An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: diff --git a/compiler/rustc_error_codes/src/error_codes/E0493.md b/compiler/rustc_error_codes/src/error_codes/E0493.md index 0dcc3b62b4..e891129efa 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0493.md +++ b/compiler/rustc_error_codes/src/error_codes/E0493.md @@ -21,7 +21,7 @@ static FOO: Foo = Foo { field1: (DropType::A, DropType::A).1 }; // error! The problem here is that if the given type or one of its fields implements the `Drop` trait, this `Drop` implementation cannot be called within a const context since it may run arbitrary, non-const-checked code. To prevent this -issue, ensure all values with custom a custom `Drop` implementation escape the +issue, ensure all values with a custom `Drop` implementation escape the initializer. ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0508.md b/compiler/rustc_error_codes/src/error_codes/E0508.md index 33572fca6a..91865907bf 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0508.md +++ b/compiler/rustc_error_codes/src/error_codes/E0508.md @@ -39,3 +39,16 @@ fn main() { let _value = array[0].clone(); } ``` + +If you really want to move the value out, you can use a destructuring array +pattern to move it: + +``` +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + // Destructuring the array + let [_value] = array; +} +``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0542.md b/compiler/rustc_error_codes/src/error_codes/E0542.md index 7cb58f9d0c..7fecfeaa57 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0542.md +++ b/compiler/rustc_error_codes/src/error_codes/E0542.md @@ -10,7 +10,7 @@ Erroneous code example: fn _stable_fn() {} #[rustc_const_stable(feature = "_stable_const_fn")] // invalid -fn _stable_const_fn() {} +const fn _stable_const_fn() {} #[stable(feature = "_deprecated_fn", since = "0.1.0")] #[rustc_deprecated( @@ -29,7 +29,7 @@ To fix this issue, you need to provide the `since` field. Example: fn _stable_fn() {} #[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] // ok! -fn _stable_const_fn() {} +const fn _stable_const_fn() {} #[stable(feature = "_deprecated_fn", since = "0.1.0")] #[rustc_deprecated( diff --git a/compiler/rustc_error_codes/src/error_codes/E0545.md b/compiler/rustc_error_codes/src/error_codes/E0545.md index 9fb935a3ab..7aba084f4d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0545.md +++ b/compiler/rustc_error_codes/src/error_codes/E0545.md @@ -10,7 +10,7 @@ Erroneous code example: fn _unstable_fn() {} #[rustc_const_unstable(feature = "_unstable_const_fn", issue = "0")] // invalid -fn _unstable_const_fn() {} +const fn _unstable_const_fn() {} ``` To fix this issue, you need to provide a correct value in the `issue` field. @@ -24,7 +24,7 @@ Example: fn _unstable_fn() {} #[rustc_const_unstable(feature = "_unstable_const_fn", issue = "1")] // ok! -fn _unstable_const_fn() {} +const fn _unstable_const_fn() {} ``` See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix diff --git a/compiler/rustc_error_codes/src/error_codes/E0547.md b/compiler/rustc_error_codes/src/error_codes/E0547.md index 1aa4b35424..4950325df6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0547.md +++ b/compiler/rustc_error_codes/src/error_codes/E0547.md @@ -10,7 +10,7 @@ Erroneous code example: fn _unstable_fn() {} #[rustc_const_unstable(feature = "_unstable_const_fn")] // invalid -fn _unstable_const_fn() {} +const fn _unstable_const_fn() {} ``` To fix this issue, you need to provide the `issue` field. Example: @@ -26,7 +26,7 @@ fn _unstable_fn() {} feature = "_unstable_const_fn", issue = "none" )] // ok! -fn _unstable_const_fn() {} +const fn _unstable_const_fn() {} ``` See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix diff --git a/compiler/rustc_error_codes/src/error_codes/E0632.md b/compiler/rustc_error_codes/src/error_codes/E0632.md new file mode 100644 index 0000000000..40840e894d --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0632.md @@ -0,0 +1,25 @@ +An explicit generic argument was provided when calling a function that +uses `impl Trait` in argument position. + +Erroneous code example: + +```compile_fail,E0632 +fn foo(a: T, b: impl Clone) {} + +foo::(0i32, "abc".to_string()); +``` + +Either all generic arguments should be inferred at the call site, or +the function definition should use an explicit generic type parameter +instead of `impl Trait`. Example: + +``` +fn foo(a: T, b: impl Clone) {} +fn bar(a: T, b: U) {} + +foo(0i32, "abc".to_string()); + +bar::(0i32, "abc".to_string()); +bar::<_, _>(0i32, "abc".to_string()); +bar(0i32, "abc".to_string()); +``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0690.md b/compiler/rustc_error_codes/src/error_codes/E0690.md index 1673456580..ba706ad2b0 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0690.md +++ b/compiler/rustc_error_codes/src/error_codes/E0690.md @@ -1,19 +1,19 @@ -A struct with the representation hint `repr(transparent)` had zero or more than -one fields that were not guaranteed to be zero-sized. +A struct with the representation hint `repr(transparent)` had two or more fields +that were not guaranteed to be zero-sized. Erroneous code example: ```compile_fail,E0690 #[repr(transparent)] -struct LengthWithUnit { // error: transparent struct needs exactly one +struct LengthWithUnit { // error: transparent struct needs at most one value: f32, // non-zero-sized field, but has 2 unit: U, } ``` Because transparent structs are represented exactly like one of their fields at -run time, said field must be uniquely determined. If there is no field, or if -there are multiple fields, it is not clear how the struct should be represented. +run time, said field must be uniquely determined. If there are multiple fields, +it is not clear how the struct should be represented. Note that fields of zero-sized types (e.g., `PhantomData`) can also exist alongside the field that contains the actual data, they do not count for this error. When generic types are involved (as in the above example), an error is diff --git a/compiler/rustc_error_codes/src/error_codes/E0716.md b/compiler/rustc_error_codes/src/error_codes/E0716.md index c6d0337ddd..c3546cd744 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0716.md +++ b/compiler/rustc_error_codes/src/error_codes/E0716.md @@ -14,14 +14,16 @@ Here, the expression `&foo()` is borrowing the expression `foo()`. As `foo()` is a call to a function, and not the name of a variable, this creates a **temporary** -- that temporary stores the return value from `foo()` so that it can be borrowed. You could imagine that `let p = bar(&foo());` is equivalent to -this: +the following, which uses an explicit temporary variable. + +Erroneous code example: ```compile_fail,E0597 # fn foo() -> i32 { 22 } # fn bar(x: &i32) -> &i32 { x } let p = { let tmp = foo(); // the temporary - bar(&tmp) + bar(&tmp) // error: `tmp` does not live long enough }; // <-- tmp is freed as we exit this block let q = p; ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0722.md b/compiler/rustc_error_codes/src/error_codes/E0722.md new file mode 100644 index 0000000000..570717a92b --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0722.md @@ -0,0 +1,31 @@ +The `optimize` attribute was malformed. + +Erroneous code example: + +```compile_fail,E0722 +#![feature(optimize_attribute)] + +#[optimize(something)] // error: invalid argument +pub fn something() {} +``` + +The `#[optimize]` attribute should be used as follows: + +- `#[optimize(size)]` -- instructs the optimization pipeline to generate code + that's smaller rather than faster + +- `#[optimize(speed)]` -- instructs the optimization pipeline to generate code + that's faster rather than smaller + +For example: + +``` +#![feature(optimize_attribute)] + +#[optimize(size)] +pub fn something() {} +``` + +See [RFC 2412] for more details. + +[RFC 2412]: https://rust-lang.github.io/rfcs/2412-optimize-attr.html diff --git a/compiler/rustc_error_codes/src/error_codes/E0757.md b/compiler/rustc_error_codes/src/error_codes/E0757.md new file mode 100644 index 0000000000..41b06b23c4 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0757.md @@ -0,0 +1,33 @@ +A function was given both the `ffi_const` and `ffi_pure` attributes. + +Erroneous code example: + +```compile_fail,E0757 +#![feature(ffi_const, ffi_pure)] + +extern "C" { + #[ffi_const] + #[ffi_pure] // error: `#[ffi_const]` function cannot be `#[ffi_pure]` + pub fn square(num: i32) -> i32; +} +``` + +As `ffi_const` provides stronger guarantees than `ffi_pure`, remove the +`ffi_pure` attribute: + +``` +#![feature(ffi_const)] + +extern "C" { + #[ffi_const] + pub fn square(num: i32) -> i32; +} +``` + +You can get more information about `const` and `pure` in the [GCC documentation +on Common Function Attributes]. The unstable Rust Book has more information +about [`ffi_const`] and [`ffi_pure`]. + +[GCC documentation on Common Function Attributes]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html +[`ffi_const`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/ffi-const.html +[`ffi_pure`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/ffi-pure.html diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 577baec21f..2253007ce3 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -145,8 +145,9 @@ impl AnnotateSnippetEmitterWriter { title: Some(Annotation { label: Some(&message), id: code.as_ref().map(|c| match c { - DiagnosticId::Error(val) - | DiagnosticId::Lint { name: val, has_future_breakage: _ } => val.as_str(), + DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => { + val.as_str() + } }), annotation_type: annotation_type_for_level(*level), }), diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 14ccced2c6..45661ac156 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -29,7 +29,7 @@ pub struct Diagnostic { #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DiagnosticId { Error(String), - Lint { name: String, has_future_breakage: bool }, + Lint { name: String, has_future_breakage: bool, is_force_warn: bool }, } /// A "sub"-diagnostic attached to a parent diagnostic. @@ -109,6 +109,13 @@ impl Diagnostic { } } + pub fn is_force_warn(&self) -> bool { + match self.code { + Some(DiagnosticId::Lint { is_force_warn, .. }) => is_force_warn, + _ => false, + } + } + /// Cancel the diagnostic (a structured diagnostic must either be emitted or /// canceled or it will panic when dropped). pub fn cancel(&mut self) { diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index d3f92bf304..87272b1605 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -9,7 +9,6 @@ use Destination::*; -use rustc_lint_defs::FutureBreakage; use rustc_span::source_map::SourceMap; use rustc_span::{MultiSpan, SourceFile, Span}; @@ -193,7 +192,7 @@ pub trait Emitter { /// other formats can, and will, simply ignore it. fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {} - fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {} + fn emit_future_breakage_report(&mut self, _diags: Vec) {} /// Emit list of unused externs fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {} @@ -309,9 +308,7 @@ pub trait Emitter { // are some which do actually involve macros. ExpnKind::Inlined | ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None, - ExpnKind::Macro { kind: macro_kind, name, proc_macro: _ } => { - Some((macro_kind, name)) - } + ExpnKind::Macro(macro_kind, name) => Some((macro_kind, name)), } }); @@ -368,23 +365,11 @@ pub trait Emitter { continue; } - if matches!(trace.kind, ExpnKind::Inlined) { - new_labels - .push((trace.call_site, "in the inlined copy of this code".to_string())); - } else if always_backtrace { - let proc_macro = if let ExpnKind::Macro { kind: _, name: _, proc_macro: true } = - trace.kind - { - "procedural macro " - } else { - "" - }; - + if always_backtrace && !matches!(trace.kind, ExpnKind::Inlined) { new_labels.push(( trace.def_site, format!( - "in this expansion of {}`{}`{}", - proc_macro, + "in this expansion of `{}`{}", trace.kind.descr(), if macro_backtrace.len() > 1 { // if macro_backtrace.len() == 1 it'll be @@ -410,17 +395,27 @@ pub trait Emitter { // and it needs an "in this macro invocation" label to match that. let redundant_span = trace.call_site.contains(sp); - if !redundant_span - && matches!( - trace.kind, - ExpnKind::Macro { kind: MacroKind::Bang, name: _, proc_macro: _ } - ) - || always_backtrace - { + if !redundant_span || always_backtrace { + let msg: Cow<'static, _> = match trace.kind { + ExpnKind::Macro(MacroKind::Attr, _) => { + "this procedural macro expansion".into() + } + ExpnKind::Macro(MacroKind::Derive, _) => { + "this derive macro expansion".into() + } + ExpnKind::Macro(MacroKind::Bang, _) => "this macro invocation".into(), + ExpnKind::Inlined => "the inlined copy of this code".into(), + ExpnKind::Root => "in the crate root".into(), + ExpnKind::AstPass(kind) => kind.descr().into(), + ExpnKind::Desugaring(kind) => { + format!("this {} desugaring", kind.descr()).into() + } + }; new_labels.push(( trace.call_site, format!( - "in this macro invocation{}", + "in {}{}", + msg, if macro_backtrace.len() > 1 && always_backtrace { // only specify order when the macro // backtrace is multiple levels deep diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 72395bd31e..1b6cd04cca 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -16,7 +16,7 @@ use crate::registry::Registry; use crate::DiagnosticId; use crate::ToolMetadata; use crate::{CodeSuggestion, SubDiagnostic}; -use rustc_lint_defs::{Applicability, FutureBreakage}; +use rustc_lint_defs::Applicability; use rustc_data_structures::sync::Lrc; use rustc_span::hygiene::ExpnData; @@ -134,17 +134,14 @@ impl Emitter for JsonEmitter { } } - fn emit_future_breakage_report(&mut self, diags: Vec<(FutureBreakage, crate::Diagnostic)>) { + fn emit_future_breakage_report(&mut self, diags: Vec) { let data: Vec = diags .into_iter() - .map(|(breakage, mut diag)| { + .map(|mut diag| { if diag.level == crate::Level::Allow { diag.level = crate::Level::Warning; } - FutureBreakageItem { - future_breakage_date: breakage.date, - diagnostic: Diagnostic::from_errors_diagnostic(&diag, self), - } + FutureBreakageItem { diagnostic: Diagnostic::from_errors_diagnostic(&diag, self) } }) .collect(); let report = FutureIncompatReport { future_incompat_report: data }; @@ -326,7 +323,6 @@ struct ArtifactNotification<'a> { #[derive(Encodable)] struct FutureBreakageItem { - future_breakage_date: Option<&'static str>, diagnostic: Diagnostic, } @@ -559,7 +555,7 @@ impl DiagnosticCode { s.map(|s| { let s = match s { DiagnosticId::Error(s) => s, - DiagnosticId::Lint { name, has_future_breakage: _ } => name, + DiagnosticId::Lint { name, .. } => name, }; let je_result = je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap(); diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index e69e868c8e..d055937ac3 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -39,16 +39,11 @@ impl Write for Shared { } } -fn with_default_session_globals(f: impl FnOnce()) { - let session_globals = rustc_span::SessionGlobals::new(rustc_span::edition::DEFAULT_EDITION); - rustc_span::SESSION_GLOBALS.set(&session_globals, f); -} - /// Test the span yields correct positions in JSON. fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { let expected_output = TestData { spans: vec![expected_output] }; - with_default_session_globals(|| { + rustc_span::create_default_session_globals_then(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned()); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 979f2d3b30..993a7c2c16 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,7 +5,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(backtrace)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(format_args_capture)] #![feature(iter_zip)] #![feature(nll)] @@ -24,7 +23,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{self, Lock, Lrc}; use rustc_data_structures::AtomicRef; -use rustc_lint_defs::FutureBreakage; pub use rustc_lint_defs::{pluralize, Applicability}; use rustc_serialize::json::Json; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -521,12 +519,28 @@ impl Handler { } /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + /// + /// The builder will be canceled if warnings cannot be emitted. pub fn struct_span_warn(&self, span: impl Into, msg: &str) -> DiagnosticBuilder<'_> { let mut result = self.struct_warn(msg); result.set_span(span); result } + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + /// + /// This will "force" the warning meaning it will not be canceled even + /// if warnings cannot be emitted. + pub fn struct_span_force_warn( + &self, + span: impl Into, + msg: &str, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_force_warn(msg); + result.set_span(span); + result + } + /// Construct a builder at the `Allow` level at the given `span` and with the `msg`. pub fn struct_span_allow( &self, @@ -552,6 +566,8 @@ impl Handler { } /// Construct a builder at the `Warning` level with the `msg`. + /// + /// The builder will be canceled if warnings cannot be emitted. pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); if !self.flags.can_emit_warnings { @@ -560,6 +576,14 @@ impl Handler { result } + /// Construct a builder at the `Warning` level with the `msg`. + /// + /// This will "force" a warning meaning it will not be canceled even + /// if warnings cannot be emitted. + pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Level::Warning, msg) + } + /// Construct a builder at the `Allow` level with the `msg`. pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Allow, msg) @@ -765,7 +789,7 @@ impl Handler { self.inner.borrow_mut().emit_artifact_notification(path, artifact_type) } - pub fn emit_future_breakage_report(&self, diags: Vec<(FutureBreakage, Diagnostic)>) { + pub fn emit_future_breakage_report(&self, diags: Vec) { self.inner.borrow_mut().emitter.emit_future_breakage_report(diags) } @@ -802,7 +826,10 @@ impl HandlerInner { self.future_breakage_diagnostics.push(diagnostic.clone()); } - if diagnostic.level == Warning && !self.flags.can_emit_warnings { + if diagnostic.level == Warning + && !self.flags.can_emit_warnings + && !diagnostic.is_force_warn() + { if diagnostic.has_future_breakage() { (*TRACK_DIAGNOSTICS)(diagnostic); } @@ -874,7 +901,7 @@ impl HandlerInner { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => self.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)), + (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)), (_, 0) => { let _ = self.fatal(&errors); } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index aab2741c85..8c6aef8063 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -16,7 +16,7 @@ use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind}; +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, MultiSpan, Span, DUMMY_SP}; @@ -29,6 +29,9 @@ use std::rc::Rc; crate use rustc_span::hygiene::MacroKind; +// When adding new variants, make sure to +// adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector` +// to use `assign_id!` #[derive(Debug, Clone)] pub enum Annotatable { Item(P), @@ -745,9 +748,17 @@ impl SyntaxExtension { } } - let builtin_name = sess + let (builtin_name, helper_attrs) = sess .find_by_name(attrs, sym::rustc_builtin_macro) - .map(|a| a.value_str().unwrap_or(name)); + .map(|attr| { + // Override `helper_attrs` passed above if it's a built-in macro, + // marking `proc_macro_derive` macros as built-in is not a realistic use case. + parse_macro_name_and_helper_attrs(sess.diagnostic(), attr, "built-in").map_or_else( + || (Some(name), Vec::new()), + |(name, helper_attrs)| (Some(name), helper_attrs), + ) + }) + .unwrap_or_else(|| (None, helper_attrs)); let (stability, const_stability) = attr::find_stability(&sess, attrs, span); if let Some((_, sp)) = const_stability { sess.parse_sess @@ -805,22 +816,15 @@ impl SyntaxExtension { pub fn expn_data( &self, - parent: ExpnId, + parent: LocalExpnId, call_site: Span, descr: Symbol, macro_def_id: Option, + parent_module: Option, ) -> ExpnData { - use SyntaxExtensionKind::*; - let proc_macro = match self.kind { - // User-defined proc macro - Bang(..) | Attr(..) | Derive(..) => true, - // Consider everthing else to be not a proc - // macro for diagnostic purposes - LegacyBang(..) | LegacyAttr(..) | NonMacroAttr { .. } | LegacyDerive(..) => false, - }; ExpnData::new( - ExpnKind::Macro { kind: self.macro_kind(), name: descr, proc_macro }, - parent, + ExpnKind::Macro(self.macro_kind(), descr), + parent.to_expn_id(), call_site, self.span, self.allow_internal_unstable.clone(), @@ -828,6 +832,7 @@ impl SyntaxExtension { self.local_inner_macros, self.edition, macro_def_id, + parent_module, ) } } @@ -835,13 +840,17 @@ impl SyntaxExtension { /// Error type that denotes indeterminacy. pub struct Indeterminate; -pub type DeriveResolutions = Vec<(ast::Path, Option>)>; +pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option>)>; pub trait ResolverExpand { fn next_node_id(&mut self) -> NodeId; fn resolve_dollar_crates(&mut self); - fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment); + fn visit_ast_fragment_with_placeholders( + &mut self, + expn_id: LocalExpnId, + fragment: &AstFragment, + ); fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind); fn expansion_for_ast_pass( @@ -850,37 +859,38 @@ pub trait ResolverExpand { pass: AstPass, features: &[Symbol], parent_module_id: Option, - ) -> ExpnId; + ) -> LocalExpnId; fn resolve_imports(&mut self); fn resolve_macro_invocation( &mut self, invoc: &Invocation, - eager_expansion_root: ExpnId, + eager_expansion_root: LocalExpnId, force: bool, ) -> Result, Indeterminate>; fn check_unused_macros(&mut self); - /// Some parent node that is close enough to the given macro call. - fn lint_node_id(&self, expn_id: ExpnId) -> NodeId; - // Resolver interfaces for specific built-in macros. /// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it? - fn has_derive_copy(&self, expn_id: ExpnId) -> bool; + fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool; /// Resolve paths inside the `#[derive(...)]` attribute with the given `ExpnId`. fn resolve_derives( &mut self, - expn_id: ExpnId, + expn_id: LocalExpnId, force: bool, derive_paths: &dyn Fn() -> DeriveResolutions, ) -> Result<(), Indeterminate>; /// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId` /// back from resolver. - fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option; + fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option; /// Path resolution logic for `#[cfg_accessible(path)]`. - fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result; + fn cfg_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + ) -> Result; /// Decodes the proc-macro quoted span in the specified crate, with the specified id. /// No caching is performed. @@ -911,11 +921,13 @@ impl ModuleData { #[derive(Clone)] pub struct ExpansionData { - pub id: ExpnId, + pub id: LocalExpnId, pub depth: usize, pub module: Rc, pub dir_ownership: DirOwnership, pub prior_type_ascription: Option<(Span, bool)>, + /// Some parent node that is close to this macro call + pub lint_node_id: NodeId, } type OnExternModLoaded<'a> = @@ -956,11 +968,12 @@ impl<'a> ExtCtxt<'a> { extern_mod_loaded, root_path: PathBuf::new(), current_expansion: ExpansionData { - id: ExpnId::root(), + id: LocalExpnId::ROOT, depth: 0, module: Default::default(), dir_ownership: DirOwnership::Owned { relative: None }, prior_type_ascription: None, + lint_node_id: ast::CRATE_NODE_ID, }, force_mode: false, expansions: FxHashMap::default(), @@ -993,19 +1006,19 @@ impl<'a> ExtCtxt<'a> { /// Equivalent of `Span::def_site` from the proc macro API, /// except that the location is taken from the span passed as an argument. pub fn with_def_site_ctxt(&self, span: Span) -> Span { - span.with_def_site_ctxt(self.current_expansion.id) + span.with_def_site_ctxt(self.current_expansion.id.to_expn_id()) } /// Equivalent of `Span::call_site` from the proc macro API, /// except that the location is taken from the span passed as an argument. pub fn with_call_site_ctxt(&self, span: Span) -> Span { - span.with_call_site_ctxt(self.current_expansion.id) + span.with_call_site_ctxt(self.current_expansion.id.to_expn_id()) } /// Equivalent of `Span::mixed_site` from the proc macro API, /// except that the location is taken from the span passed as an argument. pub fn with_mixed_site_ctxt(&self, span: Span) -> Span { - span.with_mixed_site_ctxt(self.current_expansion.id) + span.with_mixed_site_ctxt(self.current_expansion.id.to_expn_id()) } /// Returns span for the macro which originally caused the current expansion to happen. @@ -1219,6 +1232,88 @@ pub fn get_exprs_from_tts( Some(es) } +pub fn parse_macro_name_and_helper_attrs( + diag: &rustc_errors::Handler, + attr: &Attribute, + descr: &str, +) -> Option<(Symbol, Vec)> { + // Once we've located the `#[proc_macro_derive]` attribute, verify + // that it's of the form `#[proc_macro_derive(Foo)]` or + // `#[proc_macro_derive(Foo, attributes(A, ..))]` + let list = match attr.meta_item_list() { + Some(list) => list, + None => return None, + }; + if list.len() != 1 && list.len() != 2 { + diag.span_err(attr.span, "attribute must have either one or two arguments"); + return None; + } + let trait_attr = match list[0].meta_item() { + Some(meta_item) => meta_item, + _ => { + diag.span_err(list[0].span(), "not a meta item"); + return None; + } + }; + let trait_ident = match trait_attr.ident() { + Some(trait_ident) if trait_attr.is_word() => trait_ident, + _ => { + diag.span_err(trait_attr.span, "must only be one word"); + return None; + } + }; + + if !trait_ident.name.can_be_raw() { + diag.span_err( + trait_attr.span, + &format!("`{}` cannot be a name of {} macro", trait_ident, descr), + ); + } + + let attributes_attr = list.get(1); + let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { + if !attr.has_name(sym::attributes) { + diag.span_err(attr.span(), "second argument must be `attributes`") + } + attr.meta_item_list() + .unwrap_or_else(|| { + diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`"); + &[] + }) + .iter() + .filter_map(|attr| { + let attr = match attr.meta_item() { + Some(meta_item) => meta_item, + _ => { + diag.span_err(attr.span(), "not a meta item"); + return None; + } + }; + + let ident = match attr.ident() { + Some(ident) if attr.is_word() => ident, + _ => { + diag.span_err(attr.span, "must only be one word"); + return None; + } + }; + if !ident.name.can_be_raw() { + diag.span_err( + attr.span, + &format!("`{}` cannot be a name of derive helper attribute", ident), + ); + } + + Some(ident.name) + }) + .collect() + } else { + Vec::new() + }; + + Some((trait_ident.name, proc_attrs)) +} + /// This nonterminal looks like some specific enums from /// `proc-macro-hack` and `procedural-masquerade` crates. /// We need to maintain some special pretty-printing behavior for them due to incorrect diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index ef5b97a946..824df2757e 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -432,7 +432,7 @@ impl<'a> ExtCtxt<'a> { pub fn arm(&self, span: Span, pat: P, expr: P) -> ast::Arm { ast::Arm { - attrs: vec![], + attrs: AttrVec::new(), pat, guard: None, body: expr, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 39c0447bd0..dcd871c9d2 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -12,7 +12,7 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs}; +use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; @@ -22,14 +22,16 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; -use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser, RecoverComma}; +use rustc_parse::parser::{ + AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma, +}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; use rustc_session::Limit; use rustc_span::symbol::{sym, Ident}; -use rustc_span::{ExpnId, FileName, Span}; +use rustc_span::{FileName, LocalExpnId, Span}; use smallvec::{smallvec, SmallVec}; use std::ops::DerefMut; @@ -427,7 +429,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { let orig_expansion_data = self.cx.current_expansion.clone(); let orig_force_mode = self.cx.force_mode; - self.cx.current_expansion.depth = 0; // Collect all macro invocations and replace them with placeholders. let (mut fragment_with_placeholders, mut invocations) = @@ -488,6 +489,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data; + let depth = depth - orig_expansion_data.depth; self.cx.current_expansion = invoc.expansion_data.clone(); self.cx.force_mode = force; @@ -500,42 +502,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> { .resolver .take_derive_resolutions(expn_id) .map(|derives| { - enum AnnotatableRef<'a> { - Item(&'a P), - Stmt(&'a ast::Stmt), - } - let item = match &fragment { - AstFragment::Items(items) => match &items[..] { - [item] => AnnotatableRef::Item(item), - _ => unreachable!(), - }, - AstFragment::Stmts(stmts) => match &stmts[..] { - [stmt] => AnnotatableRef::Stmt(stmt), - _ => unreachable!(), - }, - _ => unreachable!(), - }; - derive_invocations.reserve(derives.len()); derives .into_iter() - .map(|(path, _exts)| { + .map(|(path, item, _exts)| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. - let expn_id = ExpnId::fresh(None); + let expn_id = LocalExpnId::fresh_empty(); derive_invocations.push(( Invocation { - kind: InvocationKind::Derive { - path, - item: match item { - AnnotatableRef::Item(item) => { - Annotatable::Item(item.clone()) - } - AnnotatableRef::Stmt(stmt) => { - Annotatable::Stmt(P(stmt.clone())) - } - }, - }, + kind: InvocationKind::Derive { path, item }, fragment_kind, expansion_data: ExpansionData { id: expn_id, @@ -956,9 +932,11 @@ pub fn parse_ast_fragment<'a>( } } AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?), - AstFragmentKind::Pat => { - AstFragment::Pat(this.parse_pat_allow_top_alt(None, RecoverComma::No)?) - } + AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::Yes, + )?), AstFragmentKind::Arms | AstFragmentKind::Fields | AstFragmentKind::FieldPats @@ -1015,7 +993,7 @@ struct InvocationCollector<'a, 'b> { impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment { - let expn_id = ExpnId::fresh(None); + let expn_id = LocalExpnId::fresh_empty(); let vis = kind.placeholder_visibility(); self.invocations.push(( Invocation { @@ -1120,6 +1098,43 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } } +/// Wraps a call to `noop_visit_*` / `noop_flat_map_*` +/// for an AST node that supports attributes +/// (see the `Annotatable` enum) +/// This method assigns a `NodeId`, and sets that `NodeId` +/// as our current 'lint node id'. If a macro call is found +/// inside this AST node, we will use this AST node's `NodeId` +/// to emit lints associated with that macro (allowing +/// `#[allow]` / `#[deny]` to be applied close to +/// the macro invocation). +/// +/// Do *not* call this for a macro AST node +/// (e.g. `ExprKind::MacCall`) - we cannot emit lints +/// at these AST nodes, since they are removed and +/// replaced with the result of macro expansion. +/// +/// All other `NodeId`s are assigned by `visit_id`. +/// * `self` is the 'self' parameter for the current method, +/// * `id` is a mutable reference to the `NodeId` field +/// of the current AST node. +/// * `closure` is a closure that executes the +/// `noop_visit_*` / `noop_flat_map_*` method +/// for the current AST node. +macro_rules! assign_id { + ($self:ident, $id:expr, $closure:expr) => {{ + let old_id = $self.cx.current_expansion.lint_node_id; + if $self.monotonic { + debug_assert_eq!(*$id, ast::DUMMY_NODE_ID); + let new_id = $self.cx.resolver.next_node_id(); + *$id = new_id; + $self.cx.current_expansion.lint_node_id = new_id; + } + let ret = ($closure)(); + $self.cx.current_expansion.lint_node_id = old_id; + ret + }}; +} + impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn visit_expr(&mut self, expr: &mut P) { self.cfg.configure_expr(expr); @@ -1140,12 +1155,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.check_attributes(&expr.attrs); self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner() } else { - ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self)); + assign_id!(self, &mut expr.id, || { + ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self)); + }); expr } }); } + // This is needed in order to set `lint_node_id` for `let` statements + fn visit_local(&mut self, local: &mut P) { + assign_id!(self, &mut local.id, || noop_visit_local(local, self)); + } + fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { let mut arm = configure!(self, arm); @@ -1155,7 +1177,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_arms(); } - noop_flat_map_arm(arm, self) + assign_id!(self, &mut arm.id, || noop_flat_map_arm(arm, self)) } fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> { @@ -1167,7 +1189,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_expr_fields(); } - noop_flat_map_expr_field(field, self) + assign_id!(self, &mut field.id, || noop_flat_map_expr_field(field, self)) } fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> { @@ -1179,7 +1201,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_pat_fields(); } - noop_flat_map_pat_field(fp, self) + assign_id!(self, &mut fp.id, || noop_flat_map_pat_field(fp, self)) } fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> { @@ -1191,7 +1213,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_params(); } - noop_flat_map_param(p, self) + assign_id!(self, &mut p.id, || noop_flat_map_param(p, self)) } fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> { @@ -1203,7 +1225,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_field_defs(); } - noop_flat_map_field_def(sf, self) + assign_id!(self, &mut sf.id, || noop_flat_map_field_def(sf, self)) } fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> { @@ -1215,7 +1237,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_variants(); } - noop_flat_map_variant(variant, self) + assign_id!(self, &mut variant.id, || noop_flat_map_variant(variant, self)) } fn filter_map_expr(&mut self, expr: P) -> Option> { @@ -1236,9 +1258,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_opt_expr() .map(|expr| expr.into_inner()) } else { - Some({ - noop_visit_expr(&mut expr, self); - expr + assign_id!(self, &mut expr.id, || { + Some({ + noop_visit_expr(&mut expr, self); + expr + }) }) } }) @@ -1288,6 +1312,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } // The placeholder expander gives ids to statements, so we avoid folding the id here. + // We don't use `assign_id!` - it will be called when we visit statement's contents + // (e.g. an expression, item, or local) let ast::Stmt { id, kind, span } = stmt; noop_flat_map_stmt_kind(kind, self) .into_iter() @@ -1399,7 +1425,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let orig_dir_ownership = mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership); - let result = noop_flat_map_item(item, self); + let result = assign_id!(self, &mut item.id, || noop_flat_map_item(item, self)); // Restore the module info. self.cx.current_expansion.dir_ownership = orig_dir_ownership; @@ -1409,7 +1435,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } _ => { item.attrs = attrs; - noop_flat_map_item(item, self) + // The crate root is special - don't assign an ID to it. + if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::invalid()) { + assign_id!(self, &mut item.id, || noop_flat_map_item(item, self)) + } else { + noop_flat_map_item(item, self) + } } } } @@ -1433,7 +1464,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - _ => noop_flat_map_assoc_item(item, self), + _ => { + assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self)) + } } } @@ -1456,7 +1489,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - _ => noop_flat_map_assoc_item(item, self), + _ => { + assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self)) + } } } @@ -1500,7 +1535,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - _ => noop_flat_map_foreign_item(foreign_item, self), + _ => { + assign_id!(self, &mut foreign_item.id, || noop_flat_map_foreign_item( + foreign_item, + self + )) + } } } @@ -1520,13 +1560,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_generic_params(); } - noop_flat_map_generic_param(param, self) + assign_id!(self, &mut param.id, || noop_flat_map_generic_param(param, self)) } fn visit_id(&mut self, id: &mut ast::NodeId) { - if self.monotonic { - debug_assert_eq!(*id, ast::DUMMY_NODE_ID); - *id = self.cx.resolver.next_node_id() + // We may have already assigned a `NodeId` + // by calling `assign_id` + if self.monotonic && *id == ast::DUMMY_NODE_ID { + *id = self.cx.resolver.next_node_id(); } } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index abad190b07..7f985af364 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -11,14 +11,16 @@ use crate::mbe::transcribe::transcribe; use rustc_ast as ast; use rustc_ast::token::{self, NonterminalKind, NtTT, Token, TokenKind::*}; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::NodeId; +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; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_feature::Features; -use rustc_lint_defs::builtin::{OR_PATTERNS_BACK_COMPAT, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS}; +use rustc_lint_defs::builtin::{ + RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, +}; use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::parser::Parser; use rustc_session::parse::ParseSess; @@ -287,7 +289,6 @@ fn generic_extension<'cx>( let mut p = Parser::new(sess, tts, false, None); p.last_type_ascription = cx.current_expansion.prior_type_ascription; - let lint_node_id = cx.resolver.lint_node_id(cx.current_expansion.id); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. @@ -299,7 +300,7 @@ fn generic_extension<'cx>( // macro leaves unparsed tokens. site_span: sp, macro_ident: name, - lint_node_id, + lint_node_id: cx.current_expansion.lint_node_id, arm_span, }); } @@ -471,7 +472,7 @@ pub fn compile_declarative_macro( ) .pop() .unwrap(); - valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def.attrs, &tt); + valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def, &tt); return tt; } } @@ -540,13 +541,13 @@ pub fn compile_declarative_macro( fn check_lhs_nt_follows( sess: &ParseSess, features: &Features, - attrs: &[ast::Attribute], + def: &ast::Item, lhs: &mbe::TokenTree, ) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. if let mbe::TokenTree::Delimited(_, ref tts) = *lhs { - check_matcher(sess, features, attrs, &tts.tts) + check_matcher(sess, features, def, &tts.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; sess.span_diagnostic.span_err(lhs.span(), msg); @@ -604,13 +605,13 @@ fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool { fn check_matcher( sess: &ParseSess, features: &Features, - attrs: &[ast::Attribute], + def: &ast::Item, matcher: &[mbe::TokenTree], ) -> bool { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); let err = sess.span_diagnostic.err_count(); - check_matcher_core(sess, features, attrs, &first_sets, matcher, &empty_suffix); + check_matcher_core(sess, features, def, &first_sets, matcher, &empty_suffix); err == sess.span_diagnostic.err_count() } @@ -857,7 +858,7 @@ impl TokenSet { fn check_matcher_core( sess: &ParseSess, features: &Features, - attrs: &[ast::Attribute], + def: &ast::Item, first_sets: &FirstSets, matcher: &[mbe::TokenTree], follow: &TokenSet, @@ -903,7 +904,7 @@ fn check_matcher_core( } TokenTree::Delimited(span, ref d) => { let my_suffix = TokenSet::singleton(d.close_tt(span)); - check_matcher_core(sess, features, attrs, first_sets, &d.tts, &my_suffix); + check_matcher_core(sess, features, def, first_sets, &d.tts, &my_suffix); // don't track non NT tokens last.replace_with_irrelevant(); @@ -936,7 +937,7 @@ fn check_matcher_core( // `my_suffix` is some TokenSet that we can use // for checking the interior of `seq_rep`. let next = - check_matcher_core(sess, features, attrs, first_sets, &seq_rep.tts, my_suffix); + check_matcher_core(sess, features, def, first_sets, &seq_rep.tts, my_suffix); if next.maybe_empty { last.add_all(&next); } else { @@ -956,29 +957,31 @@ fn check_matcher_core( for token in &last.tokens { if let TokenTree::MetaVarDecl(span, name, Some(kind)) = *token { for next_token in &suffix_first.tokens { - // Check if the old pat is used and the next token is `|`. - if let NonterminalKind::PatParam { inferred: true } = kind { - if let TokenTree::Token(token) = next_token { - if let BinOp(token) = token.kind { - if let token::BinOpToken::Or = token { - // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param. - let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( - span, - name, - Some(NonterminalKind::PatParam { inferred: false }), - )); - sess.buffer_lint_with_diagnostic( - &OR_PATTERNS_BACK_COMPAT, - span, - ast::CRATE_NODE_ID, - &*format!("the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro",), - BuiltinLintDiagnostics::OrPatternsBackCompat( - span, suggestion, - ), - ); - } - } - } + // Check if the old pat is used and the next token is `|` + // to warn about incompatibility with Rust 2021. + // We only emit this lint if we're parsing the original + // definition of this macro_rules, not while (re)parsing + // the macro when compiling another crate that is using the + // macro. (See #86567.) + // Macros defined in the current crate have a real node id, + // whereas macros from an external crate have a dummy id. + if def.id != DUMMY_NODE_ID + && matches!(kind, NonterminalKind::PatParam { inferred: true }) + && matches!(next_token, TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or)) + { + // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param. + let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( + span, + name, + Some(NonterminalKind::PatParam { inferred: false }), + )); + sess.buffer_lint_with_diagnostic( + &RUST_2021_INCOMPATIBLE_OR_PATTERNS, + span, + ast::CRATE_NODE_ID, + "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro", + BuiltinLintDiagnostics::OrPatternsBackCompat(span, suggestion), + ); } match is_in_follow(next_token, kind) { IsInFollow::Yes => {} diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index f9e7c4254b..9ed5c8b8ff 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -8,7 +8,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{pluralize, PResult}; -use rustc_span::hygiene::{ExpnId, Transparency}; +use rustc_span::hygiene::{LocalExpnId, Transparency}; use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; @@ -16,7 +16,7 @@ use smallvec::{smallvec, SmallVec}; use std::mem; // A Marker adds the given mark to the syntax context. -struct Marker(ExpnId, Transparency); +struct Marker(LocalExpnId, Transparency); impl MutVisitor for Marker { fn token_visiting_enabled(&self) -> bool { @@ -24,7 +24,7 @@ impl MutVisitor for Marker { } fn visit_span(&mut self, span: &mut Span) { - *span = span.apply_mark(self.0, self.1) + *span = span.apply_mark(self.0.to_expn_id(), self.1) } } diff --git a/compiler/rustc_expand/src/mut_visit/tests.rs b/compiler/rustc_expand/src/mut_visit/tests.rs index 7e7155ad27..0068539fb3 100644 --- a/compiler/rustc_expand/src/mut_visit/tests.rs +++ b/compiler/rustc_expand/src/mut_visit/tests.rs @@ -3,8 +3,8 @@ use crate::tests::{matches_codepattern, string_to_crate}; use rustc_ast as ast; use rustc_ast::mut_visit::MutVisitor; use rustc_ast_pretty::pprust; +use rustc_span::create_default_session_globals_then; use rustc_span::symbol::Ident; -use rustc_span::with_default_session_globals; // This version doesn't care about getting comments or doc-strings in. fn print_crate_items(krate: &ast::Crate) -> String { @@ -38,7 +38,7 @@ macro_rules! assert_pred { // Make sure idents get transformed everywhere. #[test] fn ident_transformation() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mut zz_visitor = ToZzIdentMutVisitor; let mut krate = string_to_crate("#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string()); @@ -55,7 +55,7 @@ fn ident_transformation() { // Make sure idents get transformed even inside macro defs. #[test] fn ident_transformation_in_defs() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mut zz_visitor = ToZzIdentMutVisitor; let mut krate = string_to_crate( "macro_rules! a {(b $c:expr $(d $e:token)f+ => \ diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs index 56f25ffdb0..6402a81e7c 100644 --- a/compiler/rustc_expand/src/parse/tests.rs +++ b/compiler/rustc_expand/src/parse/tests.rs @@ -10,9 +10,9 @@ use rustc_errors::PResult; use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; +use rustc_span::create_default_session_globals_then; use rustc_span::source_map::FilePathMapping; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::with_default_session_globals; use rustc_span::{BytePos, FileName, Pos, Span}; use std::path::PathBuf; @@ -51,7 +51,7 @@ fn string_to_item(source_str: String) -> Option> { #[should_panic] #[test] fn bad_path_expr_1() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { string_to_expr("::abc::def::return".to_string()); }) } @@ -59,7 +59,7 @@ fn bad_path_expr_1() { // Checks the token-tree-ization of macros. #[test] fn string_to_tts_macro() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let tts: Vec<_> = string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect(); let tts: &[TokenTree] = &tts[..]; @@ -96,7 +96,7 @@ fn string_to_tts_macro() { #[test] fn string_to_tts_1() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); let expected = TokenStream::new(vec![ @@ -131,7 +131,7 @@ fn string_to_tts_1() { #[test] fn parse_use() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let use_s = "use foo::bar::baz;"; let vitem = string_to_item(use_s.to_string()).unwrap(); let vitem_s = item_to_string(&vitem); @@ -146,7 +146,7 @@ fn parse_use() { #[test] fn parse_extern_crate() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let ex_s = "extern crate foo;"; let vitem = string_to_item(ex_s.to_string()).unwrap(); let vitem_s = item_to_string(&vitem); @@ -184,7 +184,7 @@ fn get_spans_of_pat_idents(src: &str) -> Vec { #[test] fn span_of_self_arg_pat_idents_are_correct() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let srcs = [ "impl z { fn a (&self, &myarg: i32) {} }", "impl z { fn a (&mut self, &myarg: i32) {} }", @@ -193,7 +193,7 @@ fn span_of_self_arg_pat_idents_are_correct() { "impl z { fn a (self: Foo, &myarg: i32) {} }", ]; - for &src in &srcs { + for src in srcs { let spans = get_spans_of_pat_idents(src); let (lo, hi) = (spans[0].lo(), spans[0].hi()); assert!( @@ -208,7 +208,7 @@ fn span_of_self_arg_pat_idents_are_correct() { #[test] fn parse_exprs() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { // just make sure that they parse.... string_to_expr("3 + 4".to_string()); string_to_expr("a::z.froob(b,&(987+3))".to_string()); @@ -217,7 +217,7 @@ fn parse_exprs() { #[test] fn attrs_fix_bug() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { string_to_item( "pub fn mk_file_writer(path: &Path, flags: &[FileFlag]) -> Result, String> { @@ -238,7 +238,7 @@ let mut fflags: c_int = wb(); #[test] fn crlf_doc_comments() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let sess = sess(); let name_1 = FileName::Custom("crlf_source_1".to_string()); @@ -272,7 +272,7 @@ fn ttdelim_span() { new_parser_from_source_str(sess, name, source).parse_expr() } - with_default_session_globals(|| { + create_default_session_globals_then(|| { let sess = sess(); let expr = parse_expr_from_source_str( PathBuf::from("foo").into(), @@ -300,7 +300,7 @@ fn ttdelim_span() { // See `recurse_into_file_modules` in the parser. #[test] fn out_of_line_mod() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let item = parse_item_from_source_str( PathBuf::from("foo").into(), "mod foo { struct S; mod this_does_not_exist; }".to_owned(), diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 494b3fb61e..3f84979ac0 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -9,14 +9,12 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_parse::nt_to_tokenstream; use rustc_parse::parser::ForceCollect; -use rustc_span::def_id::CrateNum; use rustc_span::{Span, DUMMY_SP}; const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread; pub struct BangProcMacro { pub client: pm::bridge::client::Client pm::TokenStream>, - pub krate: CrateNum, } impl base::ProcMacro for BangProcMacro { @@ -26,7 +24,7 @@ impl base::ProcMacro for BangProcMacro { span: Span, input: TokenStream, ) -> Result { - let server = proc_macro_server::Rustc::new(ecx, self.krate); + let server = proc_macro_server::Rustc::new(ecx); self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| { let mut err = ecx.struct_span_err(span, "proc macro panicked"); if let Some(s) = e.as_str() { @@ -40,7 +38,6 @@ impl base::ProcMacro for BangProcMacro { pub struct AttrProcMacro { pub client: pm::bridge::client::Client pm::TokenStream>, - pub krate: CrateNum, } impl base::AttrProcMacro for AttrProcMacro { @@ -51,7 +48,7 @@ impl base::AttrProcMacro for AttrProcMacro { annotation: TokenStream, annotated: TokenStream, ) -> Result { - let server = proc_macro_server::Rustc::new(ecx, self.krate); + let server = proc_macro_server::Rustc::new(ecx); self.client .run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace) .map_err(|e| { @@ -67,7 +64,6 @@ impl base::AttrProcMacro for AttrProcMacro { pub struct ProcMacroDerive { pub client: pm::bridge::client::Client pm::TokenStream>, - pub krate: CrateNum, } impl MultiItemModifier for ProcMacroDerive { @@ -101,7 +97,7 @@ impl MultiItemModifier for ProcMacroDerive { nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No) }; - let server = proc_macro_server::Rustc::new(ecx, self.krate); + let server = proc_macro_server::Rustc::new(ecx); let stream = match self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace) { Ok(stream) => stream, diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 92315c4d4f..ff135f60a8 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -14,7 +14,6 @@ use rustc_parse::lexer::nfc_normalize; use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str}; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; -use rustc_span::hygiene::ExpnId; use rustc_span::hygiene::ExpnKind; use rustc_span::symbol::{self, kw, sym, Symbol}; use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span}; @@ -363,26 +362,20 @@ pub(crate) struct Rustc<'a> { mixed_site: Span, span_debug: bool, krate: CrateNum, - expn_id: ExpnId, rebased_spans: FxHashMap, } impl<'a> Rustc<'a> { - pub fn new(cx: &'a ExtCtxt<'_>, krate: CrateNum) -> Self { + pub fn new(cx: &'a ExtCtxt<'_>) -> Self { let expn_data = cx.current_expansion.id.expn_data(); - let def_site = cx.with_def_site_ctxt(expn_data.def_site); - let call_site = cx.with_call_site_ctxt(expn_data.call_site); - let mixed_site = cx.with_mixed_site_ctxt(expn_data.call_site); - let sess = cx.parse_sess(); Rustc { resolver: cx.resolver, - sess, - def_site, - call_site, - mixed_site, + sess: cx.parse_sess(), + def_site: cx.with_def_site_ctxt(expn_data.def_site), + call_site: cx.with_call_site_ctxt(expn_data.call_site), + mixed_site: cx.with_mixed_site_ctxt(expn_data.call_site), span_debug: cx.ecfg.span_debug, - krate, - expn_id: cx.current_expansion.id, + krate: expn_data.macro_def_id.unwrap().krate, rebased_spans: FxHashMap::default(), } } @@ -411,6 +404,10 @@ impl server::FreeFunctions for Rustc<'_> { fn track_env_var(&mut self, var: &str, value: Option<&str>) { self.sess.env_depinfo.borrow_mut().insert((Symbol::intern(var), value.map(Symbol::intern))); } + + fn track_path(&mut self, path: &str) { + self.sess.file_depinfo.borrow_mut().insert(Symbol::intern(path)); + } } impl server::TokenStream for Rustc<'_> { @@ -778,25 +775,15 @@ impl server::Span for Rustc<'_> { /// span from the metadata of `my_proc_macro` (which we have access to, /// since we've loaded `my_proc_macro` from disk in order to execute it). /// In this way, we have obtained a span pointing into `my_proc_macro` - fn save_span(&mut self, mut span: Self::Span) -> usize { - // Throw away the `SyntaxContext`, since we currently - // skip serializing `SyntaxContext`s for proc-macro crates - span = span.with_ctxt(rustc_span::SyntaxContext::root()); + fn save_span(&mut self, span: Self::Span) -> usize { self.sess.save_proc_macro_span(span) } fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span { - let resolver = self.resolver; - let krate = self.krate; - let expn_id = self.expn_id; + let (resolver, krate, def_site) = (self.resolver, self.krate, self.def_site); *self.rebased_spans.entry(id).or_insert_with(|| { - let raw_span = resolver.get_proc_macro_quoted_span(krate, id); - // Ignore the deserialized `SyntaxContext` entirely. - // FIXME: Preserve the macro backtrace from the serialized span - // For example, if a proc-macro crate has code like - // `macro_one!() -> macro_two!() -> quote!()`, we might - // want to 'concatenate' this backtrace with the backtrace from - // our current call site. - raw_span.with_def_site_ctxt(expn_id) + // FIXME: `SyntaxContext` for spans from proc macro crates is lost during encoding, + // replace it with a def-site context until we are encoding it properly. + resolver.get_proc_macro_quoted_span(krate, id).with_ctxt(def_site.ctxt()) }) } } @@ -808,7 +795,7 @@ fn ident_name_compatibility_hack( rustc: &mut Rustc<'_>, ) -> Option<(rustc_span::symbol::Ident, bool)> { if let NtIdent(ident, is_raw) = nt { - if let ExpnKind::Macro { name: macro_name, .. } = orig_span.ctxt().outer_expn_data().kind { + if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind { let source_map = rustc.sess.source_map(); let filename = source_map.span_to_filename(orig_span); if let FileName::Real(RealFileName::LocalPath(path)) = filename { diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index f2345ff270..ed3aa1eaca 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -2,8 +2,8 @@ use rustc_ast as ast; use rustc_ast::tokenstream::TokenStream; use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream}; use rustc_session::parse::ParseSess; +use rustc_span::create_default_session_if_not_set_then; use rustc_span::source_map::{FilePathMapping, SourceMap}; -use rustc_span::with_default_session_globals; use rustc_span::{BytePos, MultiSpan, Span}; use rustc_data_structures::sync::Lrc; @@ -124,7 +124,7 @@ impl Write for Shared { } fn test_harness(file_text: &str, span_labels: Vec, expected_output: &str) { - with_default_session_globals(|| { + create_default_session_if_not_set_then(|_| { let output = Arc::new(Mutex::new(Vec::new())); let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); diff --git a/compiler/rustc_expand/src/tokenstream/tests.rs b/compiler/rustc_expand/src/tokenstream/tests.rs index 8b546e7e4a..31052bfb54 100644 --- a/compiler/rustc_expand/src/tokenstream/tests.rs +++ b/compiler/rustc_expand/src/tokenstream/tests.rs @@ -2,7 +2,7 @@ use crate::tests::string_to_stream; use rustc_ast::token; use rustc_ast::tokenstream::{Spacing, TokenStream, TokenStreamBuilder, TokenTree}; -use rustc_span::with_default_session_globals; +use rustc_span::create_default_session_globals_then; use rustc_span::{BytePos, Span, Symbol}; use smallvec::smallvec; @@ -20,7 +20,7 @@ fn joint(tree: TokenTree) -> TokenStream { #[test] fn test_concat() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test_res = string_to_ts("foo::bar::baz"); let test_fst = string_to_ts("foo::bar"); let test_snd = string_to_ts("::baz"); @@ -33,7 +33,7 @@ fn test_concat() { #[test] fn test_to_from_bijection() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test_start = string_to_ts("foo::bar(baz)"); let test_end = test_start.trees().collect(); assert_eq!(test_start, test_end) @@ -42,7 +42,7 @@ fn test_to_from_bijection() { #[test] fn test_eq_0() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test_res = string_to_ts("foo"); let test_eqs = string_to_ts("foo"); assert_eq!(test_res, test_eqs) @@ -51,7 +51,7 @@ fn test_eq_0() { #[test] fn test_eq_1() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test_res = string_to_ts("::bar::baz"); let test_eqs = string_to_ts("::bar::baz"); assert_eq!(test_res, test_eqs) @@ -60,7 +60,7 @@ fn test_eq_1() { #[test] fn test_eq_3() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test_res = string_to_ts(""); let test_eqs = string_to_ts(""); assert_eq!(test_res, test_eqs) @@ -69,7 +69,7 @@ fn test_eq_3() { #[test] fn test_diseq_0() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test_res = string_to_ts("::bar::baz"); let test_eqs = string_to_ts("bar::baz"); assert_eq!(test_res == test_eqs, false) @@ -78,7 +78,7 @@ fn test_diseq_0() { #[test] fn test_diseq_1() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test_res = string_to_ts("(bar,baz)"); let test_eqs = string_to_ts("bar,baz"); assert_eq!(test_res == test_eqs, false) @@ -87,7 +87,7 @@ fn test_diseq_1() { #[test] fn test_is_empty() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let test0: TokenStream = Vec::::new().into_iter().collect(); let test1: TokenStream = TokenTree::token(token::Ident(Symbol::intern("a"), false), sp(0, 1)).into(); @@ -101,7 +101,7 @@ fn test_is_empty() { #[test] fn test_dotdotdot() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mut builder = TokenStreamBuilder::new(); builder.push(joint(TokenTree::token(token::Dot, sp(0, 1)))); builder.push(joint(TokenTree::token(token::Dot, sp(1, 2)))); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 16f67783c1..a3e40daf6b 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -16,8 +16,14 @@ macro_rules! set { } macro_rules! declare_features { + (__status_to_bool active) => { + false + }; + (__status_to_bool incomplete) => { + true + }; ($( - $(#[doc = $doc:tt])* (active, $feature:ident, $ver:expr, $issue:expr, $edition:expr), + $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr, $edition:expr), )+) => { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. @@ -67,6 +73,21 @@ macro_rules! declare_features { pub fn unordered_const_ty_params(&self) -> bool { self.const_generics || self.const_generics_defaults } + + /// Some features are known to be incomplete and using them is likely to have + /// unanticipated results, such as compiler crashes. We warn the user about these + /// to alert them. + pub fn incomplete(&self, feature: Symbol) -> bool { + match feature { + $( + sym::$feature => declare_features!(__status_to_bool $status), + )* + // accepted and removed features aren't in this file but are never incomplete + _ if self.declared_lang_features.iter().any(|f| f.0 == feature) => false, + _ if self.declared_lib_features.iter().any(|f| f.0 == feature) => false, + _ => panic!("`{}` was not listed in `declare_features`", feature), + } + } } }; } @@ -305,7 +326,7 @@ declare_features! ( (active, cfg_target_thread_local, "1.7.0", Some(29594), None), /// Allows specialization of implementations (RFC 1210). - (active, specialization, "1.7.0", Some(31844), None), + (incomplete, specialization, "1.7.0", Some(31844), None), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization @@ -342,7 +363,7 @@ declare_features! ( (active, abi_ptx, "1.15.0", Some(38788), None), /// Allows the `#[repr(i128)]` attribute for enums. - (active, repr128, "1.16.0", Some(56071), None), + (incomplete, repr128, "1.16.0", Some(56071), None), /// Allows `#[link(kind="static-nobundle"...)]`. (active, static_nobundle, "1.16.0", Some(37403), None), @@ -395,9 +416,6 @@ declare_features! ( /// Allows accessing fields of unions inside `const` functions. (active, const_fn_union, "1.27.0", Some(51909), None), - /// Allows casting raw pointers to `usize` during const eval. - (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None), - /// Allows dereferencing raw pointers during const eval. (active, const_raw_ptr_deref, "1.27.0", Some(51911), None), @@ -429,7 +447,7 @@ declare_features! ( (active, proc_macro_hygiene, "1.30.0", Some(54727), None), /// Allows unsized rvalues at arguments and parameters. - (active, unsized_locals, "1.30.0", Some(48055), None), + (incomplete, unsized_locals, "1.30.0", Some(48055), None), /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. (active, custom_test_frameworks, "1.30.0", Some(50297), None), @@ -437,9 +455,6 @@ declare_features! ( /// Allows non-builtin attributes in inner attribute position. (active, custom_inner_attributes, "1.30.0", Some(54726), None), - /// Allows `impl Trait` in bindings (`let`, `const`, `static`). - (active, impl_trait_in_bindings, "1.30.0", Some(63065), None), - /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (active, lint_reasons, "1.31.0", Some(54503), None), @@ -450,7 +465,7 @@ declare_features! ( (active, ffi_returns_twice, "1.34.0", Some(58314), None), /// Allows const generic types (e.g. `struct Foo(...);`). - (active, const_generics, "1.34.0", Some(44580), None), + (incomplete, const_generics, "1.34.0", Some(44580), None), /// Allows using `#[optimize(X)]`. (active, optimize_attribute, "1.34.0", Some(54882), None), @@ -462,7 +477,7 @@ declare_features! ( (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows `if/while p && let q = r && ...` chains. - (active, let_chains, "1.37.0", Some(53667), None), + (incomplete, let_chains, "1.37.0", Some(53667), None), /// Allows #[repr(transparent)] on unions (RFC 2645). (active, transparent_unions, "1.37.0", Some(60405), None), @@ -474,13 +489,13 @@ declare_features! ( (active, async_closure, "1.37.0", Some(62290), None), /// Allows `impl Trait` to be used inside type aliases (RFC 2515). - (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + (incomplete, type_alias_impl_trait, "1.38.0", Some(63063), None), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (active, const_extern_fn, "1.40.0", Some(64926), None), /// Allows the use of raw-dylibs (RFC 2627). - (active, raw_dylib, "1.40.0", Some(58713), None), + (incomplete, raw_dylib, "1.40.0", Some(58713), None), /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and @@ -519,7 +534,7 @@ declare_features! ( (active, const_trait_impl, "1.42.0", Some(67792), None), /// Allows `T: ?const Trait` syntax in bounds. - (active, const_trait_bound_opt_out, "1.42.0", Some(67794), None), + (incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None), /// Allows the use of `no_sanitize` attribute. (active, no_sanitize, "1.42.0", Some(39699), None), @@ -552,16 +567,16 @@ declare_features! ( (active, format_args_capture, "1.46.0", Some(67984), None), /// Lazily evaluate constants. This allows constants to depend on type parameters. - (active, lazy_normalization_consts, "1.46.0", Some(72219), None), + (incomplete, lazy_normalization_consts, "1.46.0", Some(72219), None), /// Allows calling `transmute` in const fn (active, const_fn_transmute, "1.46.0", Some(53605), None), /// Allows `if let` guard in match arms. - (active, if_let_guard, "1.47.0", Some(51114), None), + (incomplete, if_let_guard, "1.47.0", Some(51114), None), /// Allows non-trivial generic constants which have to be manually propagated upwards. - (active, const_evaluatable_checked, "1.48.0", Some(76560), None), + (incomplete, const_evaluatable_checked, "1.48.0", Some(76560), None), /// Allows basic arithmetic on floating point types in a `const fn`. (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), @@ -582,7 +597,7 @@ declare_features! ( (active, isa_attribute, "1.48.0", Some(74727), None), /// Allow anonymous constants from an inline `const` block - (active, inline_const, "1.49.0", Some(76001), None), + (incomplete, inline_const, "1.49.0", Some(76001), None), /// Allows unsized fn parameters. (active, unsized_fn_params, "1.49.0", Some(48055), None), @@ -594,7 +609,7 @@ declare_features! ( (active, cfg_panic, "1.49.0", Some(77443), None), /// Allows capturing disjoint fields in a closure/generator (RFC 2229). - (active, capture_disjoint_fields, "1.49.0", Some(53488), None), + (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), /// Allows const generics to have default values (e.g. `struct Foo(...);`). (active, const_generics_defaults, "1.51.0", Some(44580), None), @@ -618,7 +633,7 @@ declare_features! ( (active, min_type_alias_impl_trait, "1.52.0", Some(63063), None), /// Allows associated types in inherent impls. - (active, inherent_associated_types, "1.52.0", Some(8995), None), + (incomplete, inherent_associated_types, "1.52.0", Some(8995), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), @@ -626,6 +641,9 @@ declare_features! ( /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. (active, c_unwind, "1.52.0", Some(74990), None), + /// Allows using `#[repr(align(...))]` on function items + (active, fn_align, "1.53.0", Some(82232), None), + /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), @@ -658,41 +676,19 @@ declare_features! ( (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), /// Allows unnamed fields of struct and union type - (active, unnamed_fields, "1.53.0", Some(49804), None), + (incomplete, unnamed_fields, "1.53.0", Some(49804), None), /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. - (active, more_qualified_paths, "1.54.0", Some(80080), None), + (active, more_qualified_paths, "1.54.0", Some(86935), None), + + /// Allows `cfg(target_abi = "...")`. + (active, cfg_target_abi, "1.55.0", Some(80970), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- ); -/// Some features are known to be incomplete and using them is likely to have -/// unanticipated results, such as compiler crashes. We warn the user about these -/// to alert them. -pub const INCOMPLETE_FEATURES: &[Symbol] = &[ - sym::if_let_guard, - sym::impl_trait_in_bindings, - sym::generic_associated_types, - sym::const_generics, - sym::let_chains, - sym::raw_dylib, - sym::const_evaluatable_checked, - sym::const_trait_impl, - sym::const_trait_bound_opt_out, - sym::lazy_normalization_consts, - sym::specialization, - sym::inline_const, - sym::repr128, - sym::unsized_locals, - sym::capture_disjoint_fields, - sym::inherent_associated_types, - sym::type_alias_impl_trait, - sym::rustc_insignificant_dtor, - sym::unnamed_fields, -]; - /// Some features are not allowed to be used together at the same time, if /// the two are present, produce an error. /// diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 259a6328a2..b1c725ecd8 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -23,6 +23,7 @@ pub type GatedCfg = (Symbol, Symbol, GateFn); /// `cfg(...)`'s that are feature gated. const GATED_CFGS: &[GatedCfg] = &[ // (name in cfg, feature, function to check if the feature is enabled) + (sym::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)), (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), @@ -349,6 +350,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!(cmse_nonsecure_entry, AssumedUsed, template!(Word), experimental!(cmse_nonsecure_entry)), + // RFC 2632 + gated!( + default_method_body_is_const, AssumedUsed, template!(Word), const_trait_impl, + "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \ + as `const`, which may be removed or renamed in the future." + ), // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: @@ -441,7 +448,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Macro related: // ========================================================================== - rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL), + rustc_attr!( + rustc_builtin_macro, AssumedUsed, + template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), + IMPL_DETAIL, + ), rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), rustc_attr!( rustc_macro_transparency, AssumedUsed, diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 654d240858..cf102aa16e 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -146,7 +146,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option { LabelStr(Cow<'a, str>), /// This kind of label uses the graphviz label escString type: - /// + /// /// /// Occurrences of backslashes (`\`) are not escaped; instead they /// are interpreted as initiating an escString escape sequence. @@ -307,12 +307,12 @@ pub enum LabelText<'a> { /// printed exactly as given, but between `<` and `>`. **No /// escaping is performed.** /// - /// [html]: http://www.graphviz.org/content/node-shapes#html + /// [html]: https://www.graphviz.org/content/node-shapes#html HtmlStr(Cow<'a, str>), } /// The style for a node or edge. -/// See for descriptions. +/// See for descriptions. /// Note that some of these are not valid for edges. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Style { @@ -439,7 +439,7 @@ pub trait Labeller<'a> { /// Maps `n` to one of the [graphviz `shape` names][1]. If `None` /// is returned, no `shape` attribute is specified. /// - /// [1]: http://www.graphviz.org/content/node-shapes + /// [1]: https://www.graphviz.org/content/node-shapes fn node_shape(&'a self, _node: &Self::Node) -> Option> { None } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 753b8c8567..30a367052c 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -5,16 +5,13 @@ //! expressions) that are mostly just leftovers. pub use crate::def_id::DefPathHash; -use crate::def_id::{ - CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE, -}; +use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::hir; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::unhash::UnhashMap; use rustc_index::vec::IndexVec; -use rustc_span::crate_disambiguator::CrateDisambiguator; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym, Symbol}; @@ -26,7 +23,7 @@ use tracing::debug; /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` /// stores the `DefIndex` of its parent. /// There is one `DefPathTable` for each crate. -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub struct DefPathTable { index_to_key: IndexVec, def_path_hashes: IndexVec, @@ -99,7 +96,7 @@ impl DefPathTable { /// The definition table containing node definitions. /// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s. /// It also stores mappings to convert `LocalDefId`s to/from `HirId`s. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Definitions { table: DefPathTable, @@ -108,9 +105,6 @@ pub struct Definitions { /// The reverse mapping of `def_id_to_hir_id`. pub(super) hir_id_to_def_id: FxHashMap, - /// If `ExpnId` is an ID of some macro expansion, - /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined. - parent_modules_of_macro_defs: FxHashMap, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expansions_that_defined: FxHashMap, } @@ -330,7 +324,7 @@ impl Definitions { } /// Adds a root definition (no parent) and a few other reserved definitions. - pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definitions { + pub fn new(stable_crate_id: StableCrateId) -> Definitions { let key = DefKey { parent: None, disambiguated_data: DisambiguatedDefPathData { @@ -339,7 +333,6 @@ impl Definitions { }, }; - let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator); let parent_hash = DefPathHash::new(stable_crate_id, 0); let def_path_hash = key.compute_stable_hash(parent_hash); @@ -353,7 +346,6 @@ impl Definitions { def_id_to_hir_id: Default::default(), hir_id_to_def_id: Default::default(), expansions_that_defined: Default::default(), - parent_modules_of_macro_defs: Default::default(), } } @@ -420,14 +412,6 @@ impl Definitions { self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root) } - pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId { - self.parent_modules_of_macro_defs[&expn_id] - } - - pub fn add_parent_module_of_macro_def(&mut self, expn_id: ExpnId, module: DefId) { - self.parent_modules_of_macro_defs.insert(expn_id, module); - } - pub fn iter_local_def_id(&self) -> impl Iterator + '_ { self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 577d43b1c8..6aff2fdbd1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -808,13 +808,13 @@ impl<'hir> Pat<'hir> { } use PatKind::*; - match &self.kind { + match self.kind { Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), Slice(before, slice, after) => { - before.iter().chain(slice.iter()).chain(after.iter()).all(|p| p.walk_short_(it)) + before.iter().chain(slice).chain(after.iter()).all(|p| p.walk_short_(it)) } } } @@ -836,13 +836,13 @@ impl<'hir> Pat<'hir> { } use PatKind::*; - match &self.kind { + match self.kind { Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {} Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), Slice(before, slice, after) => { - before.iter().chain(slice.iter()).chain(after.iter()).for_each(|p| p.walk_(it)) + before.iter().chain(slice).chain(after.iter()).for_each(|p| p.walk_(it)) } } } @@ -940,11 +940,11 @@ pub enum PatKind<'hir> { /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `Option` denotes its position. /// `0 <= position <= subpats.len()` - TupleStruct(QPath<'hir>, &'hir [&'hir Pat<'hir>], Option), + TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], Option), /// An or-pattern `A | B | C`. /// Invariant: `pats.len() >= 2`. - Or(&'hir [&'hir Pat<'hir>]), + Or(&'hir [Pat<'hir>]), /// A path pattern for an unit struct/variant or a (maybe-associated) constant. Path(QPath<'hir>), @@ -952,7 +952,7 @@ pub enum PatKind<'hir> { /// A tuple pattern (e.g., `(a, b)`). /// If the `..` pattern fragment is present, then `Option` denotes its position. /// `0 <= position <= subpats.len()` - Tuple(&'hir [&'hir Pat<'hir>], Option), + Tuple(&'hir [Pat<'hir>], Option), /// A `box` pattern. Box(&'hir Pat<'hir>), @@ -975,7 +975,7 @@ pub enum PatKind<'hir> { /// ``` /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)]) /// ``` - Slice(&'hir [&'hir Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [&'hir Pat<'hir>]), + Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]), } #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] @@ -1205,8 +1205,6 @@ pub struct ExprField<'hir> { pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), - PushUnsafeBlock(UnsafeSource), - PopUnsafeBlock(UnsafeSource), } #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] @@ -2266,18 +2264,14 @@ pub struct OpaqueTy<'hir> { } /// From whence the opaque type came. -#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OpaqueTyOrigin { /// `-> impl Trait` FnReturn, /// `async fn` AsyncFn, - /// `let _: impl Trait = ...` - Binding, /// type aliases: `type Foo = impl Trait;` TyAlias, - /// Impl trait consts, statics, bounds. - Misc, } /// The various kinds of types recognized by the compiler. @@ -2817,6 +2811,27 @@ impl ItemKind<'_> { _ => return None, }) } + + pub fn descr(&self) -> &'static str { + match self { + ItemKind::ExternCrate(..) => "extern crate", + ItemKind::Use(..) => "`use` import", + ItemKind::Static(..) => "static item", + ItemKind::Const(..) => "constant item", + ItemKind::Fn(..) => "function", + ItemKind::Mod(..) => "module", + ItemKind::ForeignMod { .. } => "extern block", + ItemKind::GlobalAsm(..) => "global asm item", + ItemKind::TyAlias(..) => "type alias", + ItemKind::OpaqueTy(..) => "opaque type", + ItemKind::Enum(..) => "enum", + ItemKind::Struct(..) => "struct", + ItemKind::Union(..) => "union", + ItemKind::Trait(..) => "trait", + ItemKind::TraitAlias(..) => "trait alias", + ItemKind::Impl(..) => "implementation", + } + } } /// A reference from an trait to one of its associated items. This @@ -3045,6 +3060,27 @@ impl<'hir> Node<'hir> { Node::Crate(_) | Node::Visibility(_) => None, } } + + /// Returns `Constness::Const` when this node is a const fn/impl. + pub fn constness(&self) -> Constness { + match self { + Node::Item(Item { + kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), + .. + }) + | Node::TraitItem(TraitItem { + kind: TraitItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), + .. + }) + | Node::ImplItem(ImplItem { + kind: ImplItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), + .. + }) + | Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness, + + _ => Constness::NotConst, + } + } } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 0b8535f8ca..28ae08030e 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -310,6 +310,8 @@ language_item_table! { Try, sym::Try, try_trait, Target::Trait; + SliceLen, sym::slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent); + // Language items from AST lowering TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }); TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }); @@ -346,7 +348,4 @@ language_item_table! { Range, sym::Range, range_struct, Target::Struct; RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct; RangeTo, sym::RangeTo, range_to_struct, Target::Struct; - Send, sym::send, send_trait, Target::Trait; - UnwindSafe, sym::unwind_safe, unwind_safe_trait, Target::Trait; - RefUnwindSafe, sym::ref_unwind_safe, ref_unwind_safe_trait, Target::Trait; } diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index ad2ecae923..4257527383 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -3,7 +3,6 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 0232654aaa..5606075283 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -5,7 +5,7 @@ use crate::hir::{ TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; -use rustc_span::def_id::{DefPathHash, LocalDefId}; +use rustc_span::def_id::DefPathHash; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro @@ -21,7 +21,6 @@ pub trait HashStableContext: fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); fn hash_hir_item_like(&mut self, f: F); - fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash; } impl ToStableHashKey for HirId { @@ -29,7 +28,7 @@ impl ToStableHashKey for HirId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { - let def_path_hash = hcx.local_def_path_hash(self.owner); + let def_path_hash = self.owner.to_stable_hash_key(hcx); (def_path_hash, self.local_id) } } @@ -39,7 +38,7 @@ impl ToStableHashKey for ItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - hcx.local_def_path_hash(self.def_id) + self.def_id.to_stable_hash_key(hcx) } } @@ -48,7 +47,7 @@ impl ToStableHashKey for TraitItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - hcx.local_def_path_hash(self.def_id) + self.def_id.to_stable_hash_key(hcx) } } @@ -57,7 +56,7 @@ impl ToStableHashKey for ImplItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - hcx.local_def_path_hash(self.def_id) + self.def_id.to_stable_hash_key(hcx) } } @@ -66,7 +65,7 @@ impl ToStableHashKey for ForeignItemId #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - hcx.local_def_path_hash(self.def_id) + self.def_id.to_stable_hash_key(hcx) } } diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 2aafc6afa2..4636d51524 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -1,6 +1,4 @@ use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData}; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_span::crate_disambiguator::CrateDisambiguator; use rustc_span::def_id::{DefPathHash, StableCrateId}; #[test] @@ -13,17 +11,16 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - let d0 = CrateDisambiguator::from(Fingerprint::new(12, 34)); - let d1 = CrateDisambiguator::from(Fingerprint::new(56, 78)); + let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]); + let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]); - let h0 = mk_test_hash("foo", d0); - let h1 = mk_test_hash("foo", d1); + let h0 = mk_test_hash(id0); + let h1 = mk_test_hash(id1); assert_ne!(h0.stable_crate_id(), h1.stable_crate_id()); assert_ne!(h0.local_hash(), h1.local_hash()); - fn mk_test_hash(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> DefPathHash { - let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator); + fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash { let parent_hash = DefPathHash::new(stable_crate_id, 0); let key = DefKey { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 2b932b7c95..5c1739b1ab 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1070,8 +1070,6 @@ impl<'a> State<'a> { ) { match blk.rules { hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"), - hir::BlockCheckMode::PushUnsafeBlock(..) => self.word_space("push_unsafe"), - hir::BlockCheckMode::PopUnsafeBlock(..) => self.word_space("pop_unsafe"), hir::BlockCheckMode::DefaultBlock => (), } self.maybe_print_comment(blk.span.lo()); @@ -1446,6 +1444,9 @@ impl<'a> State<'a> { if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) { options.push("att_syntax"); } + if opts.contains(ast::InlineAsmOptions::RAW) { + options.push("raw"); + } s.commasep(Inconsistent, &options, |s, &opt| { s.word(opt); }); @@ -1538,7 +1539,6 @@ impl<'a> State<'a> { self.word_space(":"); } self.head("loop"); - self.s.space(); self.print_block(&blk); } hir::ExprKind::Match(ref expr, arms, _) => { diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 83e80b55da..2ed0539841 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -108,7 +108,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorReported; use rustc_fs_util::{link_or_copy, LinkOrCopy}; -use rustc_session::{CrateDisambiguator, Session}; +use rustc_session::{Session, StableCrateId}; use std::fs as std_fs; use std::io; @@ -189,7 +189,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu pub fn prepare_session_directory( sess: &Session, crate_name: &str, - crate_disambiguator: CrateDisambiguator, + stable_crate_id: StableCrateId, ) -> Result<(), ErrorReported> { if sess.opts.incremental.is_none() { return Ok(()); @@ -200,7 +200,7 @@ pub fn prepare_session_directory( debug!("prepare_session_directory"); // {incr-comp-dir}/{crate-name-and-disambiguator} - let crate_dir = crate_path(sess, crate_name, crate_disambiguator); + let crate_dir = crate_path(sess, crate_name, stable_crate_id); debug!("crate-dir: {}", crate_dir.display()); create_dir(sess, &crate_dir, "crate")?; @@ -648,19 +648,12 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path( - sess: &Session, - crate_name: &str, - crate_disambiguator: CrateDisambiguator, -) -> PathBuf { +fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf { let incr_dir = sess.opts.incremental.as_ref().unwrap().clone(); - // The full crate disambiguator is really long. 64 bits of it should be - // sufficient. - let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash(); - let crate_disambiguator = base_n::encode(crate_disambiguator as u128, INT_ENCODE_BASE); + let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE); - let crate_name = format!("{}-{}", crate_name, crate_disambiguator); + let crate_name = format!("{}-{}", crate_name, stable_crate_id); incr_dir.join(crate_name) } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 8539cc6937..437d559644 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; -use rustc_middle::ty::query::OnDiskCache; +use rustc_middle::ty::OnDiskCache; use rustc_serialize::opaque::Decoder; use rustc_serialize::Decodable; use rustc_session::Session; @@ -21,8 +21,8 @@ pub enum LoadResult { Error { message: String }, } -impl LoadResult<(SerializedDepGraph, WorkProductMap)> { - pub fn open(self, sess: &Session) -> (SerializedDepGraph, WorkProductMap) { +impl LoadResult { + pub fn open(self, sess: &Session) -> T { match self { LoadResult::Error { message } => { sess.warn(&message); @@ -74,11 +74,14 @@ pub enum MaybeAsync { Sync(T), Async(std::thread::JoinHandle), } -impl MaybeAsync { - pub fn open(self) -> std::thread::Result { + +impl MaybeAsync> { + pub fn open(self) -> LoadResult { match self { - MaybeAsync::Sync(result) => Ok(result), - MaybeAsync::Async(handle) => handle.join(), + MaybeAsync::Sync(result) => result, + MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error { + message: format!("could not decode incremental cache: {:?}", e), + }), } } } @@ -195,7 +198,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { /// If we are not in incremental compilation mode, returns `None`. /// Otherwise, tries to load the query result cache from disk, /// creating an empty cache if it could not be loaded. -pub fn load_query_result_cache<'a>(sess: &'a Session) -> Option> { +pub fn load_query_result_cache<'a, C: OnDiskCache<'a>>(sess: &'a Session) -> Option { if sess.opts.incremental.is_none() { return None; } @@ -207,9 +210,7 @@ pub fn load_query_result_cache<'a>(sess: &'a Session) -> Option> &query_cache_path(sess), sess.is_nightly_build(), ) { - LoadResult::Ok { data: (bytes, start_pos) } => { - Some(OnDiskCache::new(sess, bytes, start_pos)) - } - _ => Some(OnDiskCache::new_empty(sess.source_map())), + LoadResult::Ok { data: (bytes, start_pos) } => Some(C::new(sess, bytes, start_pos)), + _ => Some(C::new_empty(sess.source_map())), } } diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index a75ad7b31a..933373150c 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -8,7 +8,6 @@ edition = "2018" doctest = false [dependencies] -rustc_graphviz = { path = "../rustc_graphviz" } tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -21,4 +20,3 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } -rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index c68705da41..448dd66234 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -46,13 +46,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { { self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( - value, - Some(self), - self.tcx, - &CanonicalizeAllFreeRegions, - query_state, - ) + Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state) } /// Canonicalizes a query *response* `V`. When we canonicalize a @@ -87,7 +81,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let mut query_state = OriginalQueryValues::default(); Canonicalizer::canonicalize( value, - Some(self), + self, self.tcx, &CanonicalizeQueryResponse, &mut query_state, @@ -101,27 +95,18 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let mut query_state = OriginalQueryValues::default(); Canonicalizer::canonicalize( value, - Some(self), + self, self.tcx, &CanonicalizeUserTypeAnnotation, &mut query_state, ) } - /// A hacky variant of `canonicalize_query` that does not - /// canonicalize `'static`. Unfortunately, the existing leak - /// check treats `'static` differently in some cases (see also - /// #33684), so if we are performing an operation that may need to - /// prove "leak-check" related things, we leave `'static` - /// alone. - /// - /// `'static` is also special cased when winnowing candidates when - /// selecting implementation candidates, so we also have to leave `'static` - /// alone for queries that do selection. - // - // FIXME(#48536): once the above issues are resolved, we can remove this - // and just use `canonicalize_query`. - pub fn canonicalize_hr_query_hack( + /// A variant of `canonicalize_query` that does not + /// canonicalize `'static`. This is useful when + /// the query implementation can perform more efficient + /// handling of `'static` regions (e.g. trait evaluation). + pub fn canonicalize_query_keep_static( &self, value: V, query_state: &mut OriginalQueryValues<'tcx>, @@ -133,7 +118,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { Canonicalizer::canonicalize( value, - Some(self), + self, self.tcx, &CanonicalizeFreeRegionsOtherThanStatic, query_state, @@ -275,7 +260,7 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic { } struct Canonicalizer<'cx, 'tcx> { - infcx: Option<&'cx InferCtxt<'cx, 'tcx>>, + infcx: &'cx InferCtxt<'cx, 'tcx>, tcx: TyCtxt<'tcx>, variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>, query_state: &'cx mut OriginalQueryValues<'tcx>, @@ -316,7 +301,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { ty::ReVar(vid) => { let resolved_vid = self .infcx - .unwrap() .inner .borrow_mut() .unwrap_region_constraints() @@ -343,7 +327,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { match *t.kind() { ty::Infer(ty::TyVar(vid)) => { debug!("canonical: type var found with vid {:?}", vid); - match self.infcx.unwrap().probe_ty_var(vid) { + match self.infcx.probe_ty_var(vid) { // `t` could be a float / int variable; canonicalize that instead. Ok(t) => { debug!("(resolved to {:?})", t); @@ -429,7 +413,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { match ct.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { debug!("canonical: const var found with vid {:?}", vid); - match self.infcx.unwrap().probe_const_var(vid) { + match self.infcx.probe_const_var(vid) { Ok(c) => { debug!("(resolved to {:?})", c); return self.fold_const(c); @@ -476,7 +460,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { /// `canonicalize_query` and `canonicalize_response`. fn canonicalize( value: V, - infcx: Option<&InferCtxt<'_, 'tcx>>, + infcx: &InferCtxt<'_, 'tcx>, tcx: TyCtxt<'tcx>, canonicalize_region_mode: &dyn CanonicalizeRegionMode, query_state: &mut OriginalQueryValues<'tcx>, @@ -610,7 +594,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { /// Returns the universe in which `vid` is defined. fn region_var_universe(&self, vid: ty::RegionVid) -> ty::UniverseIndex { - self.infcx.unwrap().inner.borrow_mut().unwrap_region_constraints().var_universe(vid) + self.infcx.inner.borrow_mut().unwrap_region_constraints().var_universe(vid) } /// Creates a canonical variable (with the given `info`) @@ -631,7 +615,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { /// *that*. Otherwise, create a new canonical variable for /// `ty_var`. fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>) -> Ty<'tcx> { - let infcx = self.infcx.expect("encountered ty-var without infcx"); + let infcx = self.infcx; let bound_to = infcx.shallow_resolve(ty_var); if bound_to != ty_var { self.fold_ty(bound_to) @@ -650,7 +634,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { info: CanonicalVarInfo<'tcx>, const_var: &'tcx ty::Const<'tcx>, ) -> &'tcx ty::Const<'tcx> { - let infcx = self.infcx.expect("encountered const-var without infcx"); + let infcx = self.infcx; let bound_to = infcx.shallow_resolve(const_var); if bound_to != const_var { self.fold_const(bound_to) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e3a79fe265..f885c0a4b8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -995,7 +995,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let get_lifetimes = |sig| { use rustc_hir::def::Namespace; let mut s = String::new(); - let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS) + let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS) .name_all_regions(sig) .unwrap(); let lts: Vec = reg.into_iter().map(|(_, kind)| kind.to_string()).collect(); @@ -1590,17 +1590,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } }; if let Some((expected, found)) = expected_found { - let expected_label = match exp_found { - Mismatch::Variable(ef) => ef.expected.prefix_string(self.tcx), - Mismatch::Fixed(s) => s.into(), - }; - let found_label = match exp_found { - Mismatch::Variable(ef) => ef.found.prefix_string(self.tcx), - Mismatch::Fixed(s) => s.into(), - }; - let exp_found = match exp_found { - Mismatch::Variable(exp_found) => Some(exp_found), - Mismatch::Fixed(_) => None, + let (expected_label, found_label, exp_found) = match exp_found { + Mismatch::Variable(ef) => ( + ef.expected.prefix_string(self.tcx), + ef.found.prefix_string(self.tcx), + Some(ef), + ), + Mismatch::Fixed(s) => (s.into(), s.into(), None), }; match (&terr, expected == found) { (TypeError::Sorts(values), extra) => { @@ -2134,7 +2130,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let new_lt = generics .as_ref() .and_then(|(parent_g, g)| { - let possible: Vec<_> = (b'a'..=b'z').map(|c| format!("'{}", c as char)).collect(); + let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char)); let mut lts_names = g .params .iter() @@ -2150,7 +2146,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::>(); - possible.into_iter().find(|candidate| !lts.contains(&candidate.as_str())) + possible.find(|candidate| !lts.contains(&candidate.as_str())) }) .unwrap_or("'lt".to_string()); let add_lt_sugg = generics 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 d9a1193aac..9a718102cf 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 @@ -491,11 +491,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span }; - let is_named_and_not_impl_trait = |ty: Ty<'_>| { - &ty.to_string() != "_" && - // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527 - (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings) - }; + let is_named_and_not_impl_trait = + |ty: Ty<'_>| &ty.to_string() != "_" && !ty.is_impl_trait(); let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) { (_, Some(_)) => String::new(), 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 new file mode 100644 index 0000000000..cca1954172 --- /dev/null +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -0,0 +1,103 @@ +//! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate +//! to hold. + +use crate::infer::error_reporting::nice_region_error::NiceRegionError; +use crate::infer::error_reporting::note_and_explain_region; +use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::{SubregionOrigin, TypeTrace}; +use crate::traits::ObligationCauseCode; +use rustc_data_structures::stable_set::FxHashSet; +use rustc_errors::{Applicability, ErrorReported}; +use rustc_hir as hir; +use rustc_hir::intravisit::Visitor; +use rustc_middle::ty::{self, TypeVisitor}; +use rustc_span::MultiSpan; + +impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { + pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option { + let error = self.error.as_ref()?; + debug!("try_report_mismatched_static_lifetime {:?}", error); + + let (origin, sub, sup) = match error.clone() { + RegionResolutionError::ConcreteFailure(origin, sub, sup) => (origin, sub, sup), + _ => return None, + }; + if *sub != ty::RegionKind::ReStatic { + return None; + } + let cause = match origin { + SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause, + _ => return None, + }; + let (parent, impl_def_id) = match &cause.code { + ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id), + _ => return None, + }; + let binding_span = match **parent { + ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span, + _ => return None, + }; + let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type"); + // FIXME: we should point at the lifetime + let mut multi_span: MultiSpan = vec![binding_span].into(); + multi_span + .push_span_label(binding_span, "introduces a `'static` lifetime requirement".into()); + err.span_note(multi_span, "because this has an unmet lifetime requirement"); + note_and_explain_region(self.tcx(), &mut err, "", sup, "..."); + 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. + + // First, let's get the hir self type of the impl + let impl_self_ty = match impl_node { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + }) => self_ty, + _ => bug!("Node not an impl."), + }; + + // Next, let's figure out the set of trait objects with implict static bounds + let ty = self.tcx().type_of(*impl_def_id); + let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default()); + v.visit_ty(ty); + let mut traits = vec![]; + for matching_def_id in v.0 { + let mut hir_v = + super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id); + hir_v.visit_ty(&impl_self_ty); + } + + if traits.is_empty() { + // If there are no trait object traits to point at, either because + // there aren't trait objects or because none are implicit, then just + // write a single note on the impl itself. + + let impl_span = self.tcx().def_span(*impl_def_id); + err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`"); + } else { + // Otherwise, point at all implicit static lifetimes + + err.note("...does not necessarily outlive the static lifetime introduced by the compatible `impl`"); + for span in &traits { + err.span_note(*span, "this has an implicit `'static` lifetime requirement"); + // It would be nice to put this immediately under the above note, but they get + // pushed to the end. + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider relaxing the implicit `'static` requirement", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + } + } + } else { + // Otherwise just point out the impl. + + let impl_span = self.tcx().def_span(*impl_def_id); + err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`"); + } + err.emit(); + Some(ErrorReported) + } +} 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 e20436690b..3f27bf67b5 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 @@ -7,6 +7,7 @@ use rustc_span::source_map::Span; mod different_lifetimes; pub mod find_anon_type; +mod mismatched_static_lifetime; mod named_anon_conflict; mod placeholder_error; mod static_impl_trait; @@ -58,6 +59,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { .or_else(|| self.try_report_impl_not_conforming_to_trait()) .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_static_impl_trait()) + .or_else(|| self.try_report_mismatched_static_lifetime()) } pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { 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 1e92698926..fde4ec05ff 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 @@ -4,6 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; +use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; @@ -185,17 +186,20 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { - if let ObligationCauseCode::ItemObligation(item_def_id) = cause.code { + let code = match &cause.code { + ObligationCauseCode::MatchImpl(parent, ..) => &**parent, + _ => &cause.code, + }; + if let ObligationCauseCode::ItemObligation(item_def_id) = *code { // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` // lifetime as above, but called using a fully-qualified path to the method: // `Foo::qux(bar)`. - let mut v = TraitObjectVisitor(vec![]); + let mut v = TraitObjectVisitor(FxHashSet::default()); v.visit_ty(param.param_ty); if let Some((ident, self_ty)) = - self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0[..]) + self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0) { - if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0[..], ident, self_ty) - { + if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) { override_error_code = Some(ident); } } @@ -336,7 +340,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn get_impl_ident_and_self_ty_from_trait( &self, def_id: DefId, - trait_objects: &[DefId], + trait_objects: &FxHashSet, ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { let tcx = self.tcx(); match tcx.hir().get_if_local(def_id) { @@ -373,9 +377,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // multiple `impl`s for the same trait like // `impl Foo for Box` and `impl Foo for dyn Bar`. // In that case, only the first one will get suggestions. - let mut hir_v = HirTraitObjectVisitor(vec![], *did); + let mut traits = vec![]; + let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); hir_v.visit_ty(self_ty); - !hir_v.0.is_empty() + !traits.is_empty() }) => { Some(self_ty) @@ -417,33 +422,34 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { _ => return false, }; - let mut v = TraitObjectVisitor(vec![]); + let mut v = TraitObjectVisitor(FxHashSet::default()); v.visit_ty(ty); // Get the `Ident` of the method being called and the corresponding `impl` (to point at // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). let (ident, self_ty) = - match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0[..]) { + match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0) { Some((ident, self_ty)) => (ident, self_ty), None => return false, }; // Find the trait object types in the argument, so we point at *only* the trait object. - self.suggest_constrain_dyn_trait_in_impl(err, &v.0[..], ident, self_ty) + self.suggest_constrain_dyn_trait_in_impl(err, &v.0, ident, self_ty) } fn suggest_constrain_dyn_trait_in_impl( &self, err: &mut DiagnosticBuilder<'_>, - found_dids: &[DefId], + found_dids: &FxHashSet, ident: Ident, self_ty: &hir::Ty<'_>, ) -> bool { let mut suggested = false; for found_did in found_dids { - let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); + let mut traits = vec![]; + let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); hir_v.visit_ty(&self_ty); - for span in &hir_v.0 { + for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); multi_span.push_span_label( *span, @@ -468,14 +474,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime. -struct TraitObjectVisitor(Vec); +pub(super) struct TraitObjectVisitor(pub(super) FxHashSet); impl TypeVisitor<'_> for TraitObjectVisitor { fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow { match t.kind() { ty::Dynamic(preds, RegionKind::ReStatic) => { if let Some(def_id) = preds.principal_def_id() { - self.0.push(def_id); + self.0.insert(def_id); } ControlFlow::CONTINUE } @@ -485,9 +491,9 @@ impl TypeVisitor<'_> for TraitObjectVisitor { } /// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime. -struct HirTraitObjectVisitor(Vec, DefId); +pub(super) struct HirTraitObjectVisitor<'a>(pub(super) &'a mut Vec, pub(super) DefId); -impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor { +impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> { type Map = ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { 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 17a56046a5..8dcdd4b149 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 @@ -56,33 +56,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); let poly_fn_sig = self.tcx().fn_sig(id); let fn_sig = self.tcx().liberate_late_bound_regions(id, poly_fn_sig); - body.params.iter().enumerate().find_map(|(index, param)| { - // May return None; sometimes the tables are not yet populated. - let ty = fn_sig.inputs()[index]; - let mut found_anon_region = false; - let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| { - if *r == *anon_region { - found_anon_region = true; - replace_region + body.params + .iter() + .take(if fn_sig.c_variadic { + fn_sig.inputs().len() + } else { + assert_eq!(fn_sig.inputs().len(), body.params.len()); + body.params.len() + }) + .enumerate() + .find_map(|(index, param)| { + // May return None; sometimes the tables are not yet populated. + let ty = fn_sig.inputs()[index]; + let mut found_anon_region = false; + let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| { + if *r == *anon_region { + found_anon_region = true; + replace_region + } else { + r + } + }); + if found_anon_region { + let ty_hir_id = fn_decl.inputs[index].hir_id; + let param_ty_span = hir.span(ty_hir_id); + let is_first = index == 0; + Some(AnonymousParamInfo { + param, + param_ty: new_param_ty, + param_ty_span, + bound_region, + is_first, + }) } else { - r + None } - }); - if found_anon_region { - let ty_hir_id = fn_decl.inputs[index].hir_id; - let param_ty_span = hir.span(ty_hir_id); - let is_first = index == 0; - Some(AnonymousParamInfo { - param, - param_ty: new_param_ty, - param_ty_span, - bound_region, - is_first, - }) - } else { - None - } - }) + }) } pub(super) fn future_return_type( diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index b3d7876c6e..4af1bdf97a 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -47,16 +47,18 @@ pub struct TypeFreshener<'a, 'tcx> { const_freshen_count: u32, ty_freshen_map: FxHashMap>, const_freshen_map: FxHashMap, &'tcx ty::Const<'tcx>>, + keep_static: bool, } impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> TypeFreshener<'a, 'tcx> { + pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, keep_static: bool) -> TypeFreshener<'a, 'tcx> { TypeFreshener { infcx, ty_freshen_count: 0, const_freshen_count: 0, ty_freshen_map: Default::default(), const_freshen_map: Default::default(), + keep_static, } } @@ -124,8 +126,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { r } - ty::ReStatic - | ty::ReEarlyBound(..) + ty::ReEarlyBound(..) | ty::ReFree(_) | ty::ReVar(_) | ty::RePlaceholder(..) @@ -134,6 +135,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { // replace all free regions with 'erased self.tcx().lifetimes.re_erased } + ty::ReStatic => { + if self.keep_static { + r + } else { + self.tcx().lifetimes.re_erased + } + } } } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index ab34cda8cc..869fd225d5 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -638,6 +638,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let sub = var_data.normalize(self.tcx(), verify.region); let verify_kind_ty = verify.kind.to_ty(self.tcx()); + let verify_kind_ty = var_data.normalize(self.tcx(), verify_kind_ty); if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) { continue; } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f39431f249..d3bfb2b2e4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -646,7 +646,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> { - freshen::TypeFreshener::new(self) + freshen::TypeFreshener::new(self, false) + } + + /// Like `freshener`, but does not replace `'static` regions. + pub fn freshener_keep_static<'b>(&'b self) -> TypeFreshener<'b, 'tcx> { + freshen::TypeFreshener::new(self, true) } pub fn type_is_unconstrained_numeric(&'a self, ty: Ty<'_>) -> UnconstrainedNumeric { diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 4935913016..7f4c33c579 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -674,7 +674,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { self.combine_map(t).insert(vars, c); self.undo_log.push(AddCombination(t, vars)); let new_r = tcx.mk_region(ReVar(c)); - for &old_r in &[a, b] { + for old_r in [a, b] { match t { Glb => self.make_subregion(origin.clone(), new_r, old_r), Lub => self.make_subregion(origin.clone(), old_r, new_r), diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 683c1df783..13b78b26af 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -400,6 +400,7 @@ impl<'tcx> From for TyVidEqKey<'tcx> { impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> { type Value = TypeVariableValue<'tcx>; + #[inline(always)] fn index(&self) -> u32 { self.vid.index } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index a33234a91f..d5c17ede21 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -70,6 +70,10 @@ pub struct FulfillmentError<'tcx> { /// obligation error caused by a call argument. When this is the case, we also signal that in /// this field to ensure accuracy of suggestions. pub points_at_arg_span: bool, + /// Diagnostics only: the 'root' obligation which resulted in + /// the failure to process `obligation`. This is the obligation + /// that was initially passed to `register_predicate_obligation` + pub root_obligation: PredicateObligation<'tcx>, } #[derive(Clone)] @@ -122,8 +126,9 @@ impl<'tcx> FulfillmentError<'tcx> { pub fn new( obligation: PredicateObligation<'tcx>, code: FulfillmentErrorCode<'tcx>, + root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { - FulfillmentError { obligation, code, points_at_arg_span: false } + FulfillmentError { obligation, code, points_at_arg_span: false, root_obligation } } } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 194464dd0b..85493978d9 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -31,7 +31,6 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } rustc_metadata = { path = "../rustc_metadata" } rustc_mir = { path = "../rustc_mir" } rustc_mir_build = { path = "../rustc_mir_build" } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index a1090ee316..8393826aa1 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -12,6 +12,7 @@ use rustc_errors::{ErrorReported, Handler}; use rustc_lint::LintStore; use rustc_middle::ty; use rustc_parse::new_parser_from_source_str; +use rustc_query_impl::QueryCtxt; use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; use rustc_session::early_error; use rustc_session::lint; @@ -76,7 +77,7 @@ impl Compiler { /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option)> { - rustc_span::with_default_session_globals(move || { + rustc_span::create_default_session_if_not_set_then(move |_| { let cfg = cfgspecs .into_iter() .map(|s| { @@ -233,7 +234,7 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option) { // state if it was responsible for triggering the panic. let i = ty::tls::with_context_opt(|icx| { if let Some(icx) = icx { - icx.tcx.queries.try_print_query_stack(icx.tcx, icx.query, handler, num_frames) + QueryCtxt::from_tcx(icx.tcx).try_print_query_stack(icx.query, handler, num_frames) } else { 0 } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 9e3e96df3a..5db027fb5b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -7,19 +7,18 @@ use rustc_ast::{self as ast, visit}; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; -use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::Crate; use rustc_lint::LintStore; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::middle; -use rustc_middle::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; +use rustc_middle::middle::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc_mir as mir; @@ -27,20 +26,20 @@ use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str}; use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; -use rustc_query_impl::Queries as TcxQueries; +use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; +use rustc_serialize::json; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode}; use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::Session; use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::FileName; use rustc_trait_selection::traits; use rustc_typeck as typeck; -use tracing::{info, warn}; - -use rustc_serialize::json; use tempfile::Builder as TempFileBuilder; +use tracing::{info, warn}; use std::any::Any; use std::cell::RefCell; @@ -101,7 +100,7 @@ mod boxed_resolver { } // Note: Drop order is important to prevent dangling references. Resolver must be dropped first, - // then resolver_arenas and finally session. + // then resolver_arenas and session. impl Drop for BoxedResolverInner { fn drop(&mut self) { self.resolver.take(); @@ -110,13 +109,10 @@ mod boxed_resolver { } impl BoxedResolver { - pub(super) fn new(session: Lrc, make_resolver: F) -> Result<(ast::Crate, Self)> - where - F: for<'a> FnOnce( - &'a Session, - &'a ResolverArenas<'a>, - ) -> Result<(ast::Crate, Resolver<'a>)>, - { + pub(super) fn new( + session: Lrc, + make_resolver: impl for<'a> FnOnce(&'a Session, &'a ResolverArenas<'a>) -> Resolver<'a>, + ) -> BoxedResolver { let mut boxed_resolver = Box::new(BoxedResolverInner { session, resolver_arenas: Some(Resolver::arenas()), @@ -127,14 +123,14 @@ mod boxed_resolver { // returns a resolver with the same lifetime as the arena. We ensure that the arena // outlives the resolver in the drop impl and elsewhere so these transmutes are sound. unsafe { - let (crate_, resolver) = make_resolver( + let resolver = make_resolver( std::mem::transmute::<&Session, &Session>(&boxed_resolver.session), std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>( boxed_resolver.resolver_arenas.as_ref().unwrap(), ), - )?; + ); boxed_resolver.resolver = Some(resolver); - Ok((crate_, BoxedResolver(Pin::new_unchecked(boxed_resolver)))) + BoxedResolver(Pin::new_unchecked(boxed_resolver)) } } @@ -165,35 +161,15 @@ mod boxed_resolver { } } -/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, -/// syntax expansion, secondary `cfg` expansion, synthesis of a test -/// harness if one is to be provided, injection of a dependency on the -/// standard library and prelude, and name resolution. -/// -/// Returns [`None`] if we're aborting after handling -W help. -pub fn configure_and_expand( +pub fn create_resolver( sess: Lrc, - lint_store: Lrc, metadata_loader: Box, - krate: ast::Crate, + krate: &ast::Crate, crate_name: &str, -) -> Result<(ast::Crate, BoxedResolver)> { - tracing::trace!("configure_and_expand"); - // Currently, we ignore the name resolution data structures for the purposes of dependency - // tracking. Instead we will run name resolution and include its output in the hash of each - // item, much like we do for macro expansion. In other words, the hash reflects not just - // its contents but the results of name resolution on those contents. Hopefully we'll push - // this back at some point. - let crate_name = crate_name.to_string(); +) -> BoxedResolver { + tracing::trace!("create_resolver"); BoxedResolver::new(sess, move |sess, resolver_arenas| { - configure_and_expand_inner( - sess, - &lint_store, - krate, - &crate_name, - &resolver_arenas, - metadata_loader, - ) + Resolver::new(sess, &krate, &crate_name, metadata_loader, &resolver_arenas) }) } @@ -219,9 +195,13 @@ pub fn register_plugins<'a>( let crate_types = util::collect_crate_types(sess, &krate.attrs); sess.init_crate_types(crate_types); - let disambiguator = util::compute_crate_disambiguator(sess); - sess.crate_disambiguator.set(disambiguator).expect("not yet initialized"); - rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?; + let stable_crate_id = StableCrateId::new( + crate_name, + sess.crate_types().contains(&CrateType::Executable), + sess.opts.cg.metadata.clone(), + ); + sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized"); + rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?; if sess.opts.incremental.is_some() { sess.time("incr_comp_garbage_collect_session_directories", || { @@ -235,10 +215,6 @@ pub fn register_plugins<'a>( }); } - sess.time("recursion_limit", || { - middle::limits::update_limits(sess, &krate); - }); - let mut lint_store = rustc_lint::new_lint_store( sess.opts.debugging_opts.no_interleave_lints, sess.unstable_options(), @@ -278,28 +254,24 @@ fn pre_expansion_lint( }); } -fn configure_and_expand_inner<'a>( - sess: &'a Session, +/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, +/// syntax expansion, secondary `cfg` expansion, synthesis of a test +/// harness if one is to be provided, injection of a dependency on the +/// standard library and prelude, and name resolution. +pub fn configure_and_expand( + sess: &Session, lint_store: &LintStore, mut krate: ast::Crate, crate_name: &str, - resolver_arenas: &'a ResolverArenas<'a>, - metadata_loader: Box, -) -> Result<(ast::Crate, Resolver<'a>)> { - tracing::trace!("configure_and_expand_inner"); + resolver: &mut Resolver<'_>, +) -> Result { + tracing::trace!("configure_and_expand"); pre_expansion_lint(sess, lint_store, &krate, crate_name); - - let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas); - rustc_builtin_macros::register_builtin_macros(&mut resolver); + rustc_builtin_macros::register_builtin_macros(resolver); krate = sess.time("crate_injection", || { let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s)); - rustc_builtin_macros::standard_library_imports::inject( - krate, - &mut resolver, - &sess, - alt_std_name, - ) + rustc_builtin_macros::standard_library_imports::inject(krate, resolver, &sess, alt_std_name) }); util::check_attr_crate_type(&sess, &krate.attrs, &mut resolver.lint_buffer()); @@ -339,9 +311,11 @@ fn configure_and_expand_inner<'a>( // Create the config for macro expansion let features = sess.features_untracked(); + let recursion_limit = + rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess); let cfg = rustc_expand::expand::ExpansionConfig { features: Some(&features), - recursion_limit: sess.recursion_limit(), + recursion_limit, trace_mac: sess.opts.debugging_opts.trace_macros, should_test: sess.opts.test, span_debug: sess.opts.debugging_opts.span_debug, @@ -354,7 +328,7 @@ fn configure_and_expand_inner<'a>( pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str()); (krate.attrs, krate.items) }; - let mut ecx = ExtCtxt::new(&sess, cfg, &mut resolver, Some(&extern_mod_loaded)); + let mut ecx = ExtCtxt::new(&sess, cfg, resolver, Some(&extern_mod_loaded)); // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); @@ -396,16 +370,16 @@ fn configure_and_expand_inner<'a>( })?; sess.time("maybe_building_test_harness", || { - rustc_builtin_macros::test_harness::inject(&sess, &mut resolver, &mut krate) + rustc_builtin_macros::test_harness::inject(&sess, resolver, &mut krate) }); if let Some(PpMode::Source(PpSourceMode::EveryBodyLoops)) = sess.opts.pretty { tracing::debug!("replacing bodies with loop {{}}"); - util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate); + util::ReplaceBodyWithLoop::new(resolver).visit_crate(&mut krate); } let has_proc_macro_decls = sess.time("AST_validation", || { - rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer()) + rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer()) }); let crate_types = sess.crate_types(); @@ -431,7 +405,7 @@ fn configure_and_expand_inner<'a>( let is_test_crate = sess.opts.test; rustc_builtin_macros::proc_macro_harness::inject( &sess, - &mut resolver, + resolver, krate, is_proc_macro_crate, has_proc_macro_decls, @@ -471,26 +445,20 @@ fn configure_and_expand_inner<'a>( } }); - Ok((krate, resolver)) + Ok(krate) } pub fn lower_to_hir<'res, 'tcx>( sess: &'tcx Session, lint_store: &LintStore, resolver: &'res mut Resolver<'_>, - dep_graph: &'res DepGraph, - krate: &'res ast::Crate, + krate: Rc, arena: &'tcx rustc_ast_lowering::Arena<'tcx>, -) -> Crate<'tcx> { - // We're constructing the HIR here; we don't care what we will - // read, since we haven't even constructed the *input* to - // incr. comp. yet. - dep_graph.assert_ignored(); - +) -> &'tcx Crate<'tcx> { // Lower AST to HIR. let hir_crate = rustc_ast_lowering::lower_crate( sess, - &krate, + &*krate, resolver, rustc_parse::nt_to_tokenstream, arena, @@ -511,6 +479,9 @@ pub fn lower_to_hir<'res, 'tcx>( ) }); + // Drop AST to free memory + sess.time("drop_ast", || std::mem::drop(krate)); + // Discard hygiene data, which isn't required after lowering to HIR. if !sess.opts.debugging_opts.keep_hygiene_data { rustc_span::hygiene::clear_syntax_context_map(); @@ -581,7 +552,7 @@ fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option { fn escape_dep_filename(filename: &String) -> String { // Apparently clang and gcc *only* escape spaces: - // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 + // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 filename.replace(" ", "\\ ") } @@ -603,7 +574,7 @@ fn escape_dep_env(symbol: Symbol) -> String { fn write_out_deps( sess: &Session, - boxed_resolver: &Steal>>, + boxed_resolver: &RefCell, outputs: &OutputFilenames, out_filenames: &[PathBuf], ) { @@ -625,12 +596,22 @@ fn write_out_deps( .map(|fmap| escape_dep_filename(&fmap.name.prefer_local().to_string())) .collect(); + // Account for explicitly marked-to-track files + // (e.g. accessed in proc macros). + let file_depinfo = sess.parse_sess.file_depinfo.borrow(); + let extra_tracked_files = file_depinfo.iter().map(|path_sym| { + let path = PathBuf::from(&*path_sym.as_str()); + let file = FileName::from(path); + escape_dep_filename(&file.prefer_local().to_string()) + }); + files.extend(extra_tracked_files); + if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend { files.push(backend.to_string()); } if sess.binary_dep_depinfo() { - boxed_resolver.borrow().borrow_mut().access(|resolver| { + boxed_resolver.borrow_mut().access(|resolver| { for cnum in resolver.cstore().crates_untracked() { let source = resolver.cstore().crate_source_untracked(cnum); if let Some((path, _)) = source.dylib { @@ -699,7 +680,7 @@ pub fn prepare_outputs( sess: &Session, compiler: &Compiler, krate: &ast::Crate, - boxed_resolver: &Steal>>, + boxed_resolver: &RefCell, crate_name: &str, ) -> Result { let _timer = sess.timer("prepare_outputs"); @@ -803,16 +784,26 @@ impl<'tcx> QueryContext<'tcx> { pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, lint_store: Lrc, - krate: &'tcx Crate<'tcx>, + krate: Rc, dep_graph: DepGraph, - resolver_outputs: ResolverOutputs, + resolver: Rc>, outputs: OutputFilenames, crate_name: &str, queries: &'tcx OnceCell>, global_ctxt: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, + hir_arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { + // We're constructing the HIR here; we don't care what we will + // read, since we haven't even constructed the *input* to + // incr. comp. yet. + dep_graph.assert_ignored(); + let sess = &compiler.session(); + let krate = resolver + .borrow_mut() + .access(|resolver| lower_to_hir(sess, &lint_store, resolver, krate, hir_arena)); + let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -828,10 +819,12 @@ pub fn create_global_ctxt<'tcx>( callback(sess, &mut local_providers, &mut extern_providers); } - let queries = queries.get_or_init(|| TcxQueries::new(local_providers, extern_providers)); + let queries = queries.get_or_init(|| { + TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache) + }); let gcx = sess.time("setup_global_ctxt", || { - global_ctxt.get_or_init(|| { + global_ctxt.get_or_init(move || { TyCtxt::create_global_ctxt( sess, lint_store, @@ -839,7 +832,7 @@ pub fn create_global_ctxt<'tcx>( resolver_outputs, krate, dep_graph, - query_result_on_disk_cache, + queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), queries.as_dyn(), &crate_name, outputs, @@ -869,11 +862,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { tcx.ensure().proc_macro_decls_static(()) }); - let cstore = tcx - .cstore_as_any() - .downcast_ref::() - .expect("`tcx.cstore` is not a `CStore`"); - cstore.report_unused_deps(tcx); + CStore::from_tcx(tcx).report_unused_deps(tcx); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { @@ -883,6 +872,13 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { tcx.ensure().check_mod_unstable_api_usage(module); tcx.ensure().check_mod_const_bodies(module); }); + }, + { + // We force these querie to run, + // since they might not otherwise get called. + // This marks the corresponding crate-level attributes + // as used, and ensures that their values are valid. + tcx.ensure().limits(()); } ); }); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2320f0b47d..8a0964e6b9 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -3,17 +3,15 @@ use crate::passes::{self, BoxedResolver, QueryContext}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::ErrorReported; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::Crate; use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; -use rustc_middle::ty::{GlobalCtxt, ResolverOutputs, TyCtxt}; +use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_query_impl::Queries as TcxQueries; use rustc_serialize::json; use rustc_session::config::{self, OutputFilenames, OutputType}; @@ -81,9 +79,8 @@ pub struct Queries<'tcx> { parse: Query, crate_name: Query, register_plugins: Query<(ast::Crate, Lrc)>, - expansion: Query<(ast::Crate, Steal>>, Lrc)>, + expansion: Query<(Rc, Rc>, Lrc)>, dep_graph: Query, - lower_to_hir: Query<(&'tcx Crate<'tcx>, Steal)>, prepare_outputs: Query, global_ctxt: Query>, ongoing_codegen: Query>, @@ -103,7 +100,6 @@ impl<'tcx> Queries<'tcx> { register_plugins: Default::default(), expansion: Default::default(), dep_graph: Default::default(), - lower_to_hir: Default::default(), prepare_outputs: Default::default(), global_ctxt: Default::default(), ongoing_codegen: Default::default(), @@ -117,13 +113,10 @@ impl<'tcx> Queries<'tcx> { &self.compiler.codegen_backend() } - pub fn dep_graph_future(&self) -> Result<&Query>> { + fn dep_graph_future(&self) -> Result<&Query>> { self.dep_graph_future.compute(|| { - Ok(self - .session() - .opts - .build_dep_graph() - .then(|| rustc_incremental::load_dep_graph(self.session()))) + let sess = self.session(); + Ok(sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess))) }) } @@ -174,83 +167,51 @@ impl<'tcx> Queries<'tcx> { pub fn expansion( &self, - ) -> Result<&Query<(ast::Crate, Steal>>, Lrc)>> { + ) -> Result<&Query<(Rc, Rc>, Lrc)>> { tracing::trace!("expansion"); self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let (krate, lint_store) = self.register_plugins()?.take(); let _timer = self.session().timer("configure_and_expand"); - passes::configure_and_expand( - self.session().clone(), - lint_store.clone(), + let sess = self.session(); + let mut resolver = passes::create_resolver( + sess.clone(), self.codegen_backend().metadata_loader(), - krate, + &krate, &crate_name, - ) - .map(|(krate, resolver)| { - (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store) - }) + ); + let krate = resolver.access(|resolver| { + passes::configure_and_expand(&sess, &lint_store, krate, &crate_name, resolver) + })?; + Ok((Rc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) } - pub fn dep_graph(&self) -> Result<&Query> { + fn dep_graph(&self) -> Result<&Query> { self.dep_graph.compute(|| { - Ok(match self.dep_graph_future()?.take() { - None => DepGraph::new_disabled(), - Some(future) => { + let sess = self.session(); + let future_opt = self.dep_graph_future()?.take(); + let dep_graph = future_opt + .and_then(|future| { let (prev_graph, prev_work_products) = - self.session().time("blocked_on_dep_graph_loading", || { - future - .open() - .unwrap_or_else(|e| rustc_incremental::LoadResult::Error { - message: format!("could not decode incremental cache: {:?}", e), - }) - .open(self.session()) - }); - - rustc_incremental::build_dep_graph( - self.session(), - prev_graph, - prev_work_products, - ) - .unwrap_or_else(DepGraph::new_disabled) - } - }) - }) - } + sess.time("blocked_on_dep_graph_loading", || future.open().open(sess)); - pub fn lower_to_hir(&'tcx self) -> Result<&Query<(&'tcx Crate<'tcx>, Steal)>> { - self.lower_to_hir.compute(|| { - let expansion_result = self.expansion()?; - let peeked = expansion_result.peek(); - let krate = &peeked.0; - let resolver = peeked.1.steal(); - let lint_store = &peeked.2; - let hir = resolver.borrow_mut().access(|resolver| { - Ok(passes::lower_to_hir( - self.session(), - lint_store, - resolver, - &*self.dep_graph()?.peek(), - &krate, - &self.hir_arena, - )) - })?; - let hir = self.hir_arena.alloc(hir); - Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) + rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products) + }) + .unwrap_or_else(DepGraph::new_disabled); + Ok(dep_graph) }) } pub fn prepare_outputs(&self) -> Result<&Query> { self.prepare_outputs.compute(|| { - let expansion_result = self.expansion()?; - let (krate, boxed_resolver, _) = &*expansion_result.peek(); + let (krate, boxed_resolver, _) = &*self.expansion()?.peek(); let crate_name = self.crate_name()?.peek(); passes::prepare_outputs( self.session(), self.compiler, - &krate, - &boxed_resolver, + krate, + &*boxed_resolver, &crate_name, ) }) @@ -260,22 +221,20 @@ impl<'tcx> Queries<'tcx> { self.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); - let lint_store = self.expansion()?.peek().2.clone(); - let hir = self.lower_to_hir()?.peek(); let dep_graph = self.dep_graph()?.peek().clone(); - let (ref krate, ref resolver_outputs) = &*hir; - let _timer = self.session().timer("create_global_ctxt"); + let (krate, resolver, lint_store) = self.expansion()?.take(); Ok(passes::create_global_ctxt( self.compiler, lint_store, krate, dep_graph, - resolver_outputs.steal(), + resolver, outputs, &crate_name, &self.queries, &self.gcx, &self.arena, + &self.hir_arena, )) }) } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 5d8a6084f2..b1e4e3ba39 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -96,10 +96,18 @@ fn assert_different_hash(x: &Options, y: &Options) { assert_same_clone(y); } +fn assert_non_crate_hash_different(x: &Options, y: &Options) { + assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true)); + assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false)); + // Check clone + assert_same_clone(x); + assert_same_clone(y); +} + // When the user supplies --test we should implicitly supply --cfg test #[test] fn test_switch_implies_cfg_test() { - rustc_span::with_default_session_globals(|| { + rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string()]).unwrap(); let (sess, cfg) = mk_session(matches); let cfg = build_configuration(&sess, to_crate_config(cfg)); @@ -110,7 +118,7 @@ fn test_switch_implies_cfg_test() { // When the user supplies --test and --cfg test, don't implicitly add another --cfg test #[test] fn test_switch_implies_cfg_test_unless_cfg_test() { - rustc_span::with_default_session_globals(|| { + rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap(); let (sess, cfg) = mk_session(matches); let cfg = build_configuration(&sess, to_crate_config(cfg)); @@ -122,20 +130,20 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { #[test] fn test_can_print_warnings() { - rustc_span::with_default_session_globals(|| { + rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); let (sess, _) = mk_session(matches); assert!(!sess.diagnostic().can_emit_warnings()); }); - rustc_span::with_default_session_globals(|| { + rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap(); let (sess, _) = mk_session(matches); assert!(sess.diagnostic().can_emit_warnings()); }); - rustc_span::with_default_session_globals(|| { + rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); let (sess, _) = mk_session(matches); assert!(sess.diagnostic().can_emit_warnings()); @@ -152,9 +160,9 @@ fn test_output_types_tracking_hash_different_paths() { v2.output_types = OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]); v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); - assert_different_hash(&v1, &v2); - assert_different_hash(&v1, &v3); - assert_different_hash(&v2, &v3); + assert_non_crate_hash_different(&v1, &v2); + assert_non_crate_hash_different(&v1, &v3); + assert_non_crate_hash_different(&v2, &v3); } #[test] @@ -228,9 +236,9 @@ fn test_lints_tracking_hash_different_values() { (String::from("d"), Level::Deny), ]; - assert_different_hash(&v1, &v2); - assert_different_hash(&v1, &v3); - assert_different_hash(&v2, &v3); + assert_non_crate_hash_different(&v1, &v2); + assert_non_crate_hash_different(&v1, &v3); + assert_non_crate_hash_different(&v2, &v3); } #[test] @@ -253,7 +261,21 @@ fn test_lints_tracking_hash_different_construction_order() { ]; // The hash should be order-dependent - assert_different_hash(&v1, &v2); + assert_non_crate_hash_different(&v1, &v2); +} + +#[test] +fn test_lint_cap_hash_different() { + let mut v1 = Options::default(); + let mut v2 = Options::default(); + let v3 = Options::default(); + + v1.lint_cap = Some(Level::Forbid); + v2.lint_cap = Some(Level::Allow); + + assert_non_crate_hash_different(&v1, &v2); + assert_non_crate_hash_different(&v1, &v3); + assert_non_crate_hash_different(&v2, &v3); } #[test] @@ -625,6 +647,7 @@ fn test_debugging_options_tracking_hash() { untracked!(dump_mir_graphviz, true); untracked!(emit_future_incompat_report, true); untracked!(emit_stack_sizes, true); + untracked!(future_incompat_test, true); untracked!(hir_stats, true); untracked!(identify_regions, true); untracked!(incremental_ignore_spans, true); @@ -646,6 +669,7 @@ fn test_debugging_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_link_args, true); untracked!(print_llvm_passes, true); untracked!(print_mono_items, Some(String::from("abc"))); @@ -707,15 +731,14 @@ fn test_debugging_options_tracking_hash() { tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(link_only, true); + tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_opt_level, Some(4)); tracked!(mutable_noalias, Some(true)); tracked!(new_llvm_pass_manager, Some(true)); - tracked!(no_codegen, true); tracked!(no_generate_arange_section, true); tracked!(no_link, true); - tracked!(no_profiler_runtime, true); tracked!(osx_rpath_install_name, true); tracked!(panic_abort_tests, true); tracked!(plt, Some(true)); @@ -724,6 +747,7 @@ fn test_debugging_options_tracking_hash() { tracked!(print_fuel, Some("abc".to_string())); tracked!(profile, true); tracked!(profile_emit, Some(PathBuf::from("abc"))); + tracked!(profiler_runtime, None); tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); @@ -747,6 +771,16 @@ fn test_debugging_options_tracking_hash() { tracked!(use_ctors_section, Some(true)); tracked!(verify_llvm_ir, true); tracked!(wasi_exec_model, Some(WasiExecModel::Reactor)); + + macro_rules! tracked_no_crate_hash { + ($name: ident, $non_default_value: expr) => { + opts = reference.clone(); + assert_ne!(opts.debugging_opts.$name, $non_default_value); + opts.debugging_opts.$name = $non_default_value; + assert_non_crate_hash_different(&reference, &opts); + }; + } + tracked_no_crate_hash!(no_codegen, true); } #[test] diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 6485fbebd6..8b41a0ff17 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -2,23 +2,22 @@ use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode}; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[cfg(parallel_compiler)] use rustc_data_structures::jobserver; -use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; use rustc_metadata::dynamic_lib::DynamicLibrary; #[cfg(parallel_compiler)] use rustc_middle::ty::tls; +#[cfg(parallel_compiler)] +use rustc_query_impl::QueryCtxt; use rustc_resolve::{self, Resolver}; use rustc_session as session; 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::CrateDisambiguator; use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session}; use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; @@ -153,7 +152,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals R + Se crate::callbacks::setup_callbacks(); let main_handler = move || { - rustc_span::with_session_globals(edition, || { + rustc_span::create_session_globals_then(edition, || { io::set_output_capture(stderr.clone()); f() }) @@ -174,12 +173,13 @@ unsafe fn handle_deadlock() { rustc_data_structures::sync::assert_sync::>(); let icx: &tls::ImplicitCtxt<'_, '_> = &*(context as *const tls::ImplicitCtxt<'_, '_>); - let session_globals = rustc_span::SESSION_GLOBALS.with(|sg| sg as *const _); + let session_globals = rustc_span::with_session_globals(|sg| sg as *const _); let session_globals = &*session_globals; thread::spawn(move || { tls::enter_context(icx, |_| { - rustc_span::SESSION_GLOBALS - .set(session_globals, || tls::with(|tcx| tcx.queries.deadlock(tcx, ®istry))) + rustc_span::set_session_globals_then(session_globals, || { + tls::with(|tcx| QueryCtxt::from_tcx(tcx).deadlock(®istry)) + }) }); }); } @@ -206,13 +206,13 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals R + Se let with_pool = move |pool: &rayon::ThreadPool| pool.install(f); - rustc_span::with_session_globals(edition, || { - rustc_span::SESSION_GLOBALS.with(|session_globals| { + 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::SESSION_GLOBALS.set(session_globals, || { + rustc_span::set_session_globals_then(session_globals, || { io::set_output_capture(stderr.clone()); thread.run() }) @@ -487,39 +487,6 @@ pub fn get_codegen_sysroot( } } -pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator { - use std::hash::Hasher; - - // The crate_disambiguator is a 128 bit hash. The disambiguator is fed - // into various other hashes quite a bit (symbol hashes, incr. comp. hashes, - // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits - // should still be safe enough to avoid collisions in practice. - let mut hasher = StableHasher::new(); - - let mut metadata = session.opts.cg.metadata.clone(); - // We don't want the crate_disambiguator to dependent on the order - // -C metadata arguments, so sort them: - metadata.sort(); - // Every distinct -C metadata value is only incorporated once: - metadata.dedup(); - - hasher.write(b"metadata"); - for s in &metadata { - // Also incorporate the length of a metadata string, so that we generate - // different values for `-Cmetadata=ab -Cmetadata=c` and - // `-Cmetadata=a -Cmetadata=bc` - hasher.write_usize(s.len()); - hasher.write(s.as_bytes()); - } - - // Also incorporate crate type, so that we don't get symbol conflicts when - // linking against a library of the same name, if this is an executable. - let is_exe = session.crate_types().contains(&CrateType::Executable); - hasher.write(if is_exe { b"exe" } else { b"lib" }); - - CrateDisambiguator::from(hasher.finish::()) -} - pub(crate) fn check_attr_crate_type( sess: &Session, attrs: &[ast::Attribute], diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b9781581ff..4cb2a6ca50 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -66,6 +66,13 @@ pub enum TokenKind { Ident, /// "r#ident" RawIdent, + /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the + /// prefix (`foo`) is included in the token, not the separator (which is + /// lexed as its own distinct token). In Rust 2021 and later, reserved + /// prefixes are reported as errors; in earlier editions, they result in a + /// (allowed by default) lint, and are treated as regular identifier + /// tokens. + UnknownPrefix, /// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details. Literal { kind: LiteralKind, suffix_start: usize }, /// "'a" @@ -323,7 +330,7 @@ impl Cursor<'_> { let kind = RawStr { n_hashes, err }; Literal { kind, suffix_start } } - _ => self.ident(), + _ => self.ident_or_unknown_prefix(), }, // Byte literal, byte string literal, raw byte string literal or identifier. @@ -358,12 +365,12 @@ impl Cursor<'_> { let kind = RawByteStr { n_hashes, err }; Literal { kind, suffix_start } } - _ => self.ident(), + _ => self.ident_or_unknown_prefix(), }, // Identifier (this should be checked after other variant that can // start as identifier). - c if is_id_start(c) => self.ident(), + c if is_id_start(c) => self.ident_or_unknown_prefix(), // Numeric literal. c @ '0'..='9' => { @@ -487,11 +494,16 @@ impl Cursor<'_> { RawIdent } - fn ident(&mut self) -> TokenKind { + fn ident_or_unknown_prefix(&mut self) -> TokenKind { debug_assert!(is_id_start(self.prev())); // Start is already eaten, eat the rest of identifier. self.eat_while(is_id_continue); - Ident + // Known prefixes must have been handled earlier. So if + // we see a prefix here, it is definitely a unknown prefix. + match self.first() { + '#' | '"' | '\'' => UnknownPrefix, + _ => Ident, + } } fn number(&mut self, first_digit: char) -> LiteralKind { diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 0b5bd39f7f..77741c7240 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -3,8 +3,10 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_middle::ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; -use rustc_session::lint::FutureBreakage; +use rustc_session::lint::FutureIncompatibilityReason; +use rustc_span::edition::Edition; use rustc_span::symbol::sym; +use rustc_span::Span; declare_lint! { /// The `array_into_iter` lint detects calling `into_iter` on arrays. @@ -20,37 +22,44 @@ declare_lint! { /// /// ### Explanation /// - /// In the future, it is planned to add an `IntoIter` implementation for - /// arrays such that it will iterate over *values* of the array instead of - /// references. Due to how method resolution works, this will change - /// existing code that uses `into_iter` on arrays. The solution to avoid - /// this warning is to use `iter()` instead of `into_iter()`. - /// - /// This is a [future-incompatible] lint to transition this to a hard error - /// in the future. See [issue #66145] for more details and a more thorough - /// description of the lint. - /// - /// [issue #66145]: https://github.com/rust-lang/rust/issues/66145 - /// [future-incompatible]: ../index.md#future-incompatible-lints + /// Since Rust 1.53, arrays implement `IntoIterator`. However, to avoid + /// breakage, `array.into_iter()` in Rust 2015 and 2018 code will still + /// behave as `(&array).into_iter()`, returning an iterator over + /// references, just like in Rust 1.52 and earlier. + /// This only applies to the method call syntax `array.into_iter()`, not to + /// any other syntax such as `for _ in array` or `IntoIterator::into_iter(array)`. pub ARRAY_INTO_ITER, Warn, - "detects calling `into_iter` on arrays", + "detects calling `into_iter` on arrays in Rust 2015 and 2018", @future_incompatible = FutureIncompatibleInfo { reference: "issue #66145 ", - edition: None, - future_breakage: Some(FutureBreakage { - date: None - }) + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021), }; } -declare_lint_pass!( - /// Checks for instances of calling `into_iter` on arrays. - ArrayIntoIter => [ARRAY_INTO_ITER] -); +#[derive(Copy, Clone, Default)] +pub struct ArrayIntoIter { + for_expr_span: Span, +} + +impl_lint_pass!(ArrayIntoIter => [ARRAY_INTO_ITER]); impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + // Save the span of expressions in `for _ in expr` syntax, + // so we can give a better suggestion for those later. + if let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) = &expr.kind { + if let hir::ExprKind::Call(path, [arg]) = &arg.kind { + if let hir::ExprKind::Path(hir::QPath::LangItem( + hir::LangItem::IntoIterIntoIter, + _, + )) = &path.kind + { + self.for_expr_span = arg.span; + } + } + } + // We only care about method call expressions. if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind { if call.ident.name != sym::into_iter { @@ -106,19 +115,37 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { _ => bug!("array type coerced to something other than array or slice"), }; cx.struct_span_lint(ARRAY_INTO_ITER, *span, |lint| { - lint.build(&format!( - "this method call currently resolves to `<&{} as IntoIterator>::into_iter` (due \ - to autoref coercions), but that might change in the future when \ - `IntoIterator` impls for arrays are added.", - target, - )) - .span_suggestion( + let mut diag = lint.build(&format!( + "this method call resolves to `<&{} as IntoIterator>::into_iter` \ + (due to backwards compatibility), \ + but will resolve to <{} as IntoIterator>::into_iter in Rust 2021.", + target, target, + )); + diag.span_suggestion( call.ident.span, "use `.iter()` instead of `.into_iter()` to avoid ambiguity", "iter".into(), Applicability::MachineApplicable, - ) - .emit(); + ); + if self.for_expr_span == expr.span { + let expr_span = expr.span.ctxt().outer_expn_data().call_site; + diag.span_suggestion( + receiver_arg.span.shrink_to_hi().to(expr_span.shrink_to_hi()), + "or remove `.into_iter()` to iterate by value", + String::new(), + Applicability::MaybeIncorrect, + ); + } else { + diag.multipart_suggestion( + "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", + 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(); }) } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index f6a84966f7..ccdbccae15 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -47,6 +47,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt}; +use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; @@ -570,6 +571,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.inner, "the", "crate"); for macro_def in krate.exported_macros { + // Non exported macros should be skipped, since `missing_docs` only + // applies to externally visible items. + if !cx.access_levels.is_exported(macro_def.hir_id()) { + continue; + } + let attrs = cx.tcx.hir().attrs(macro_def.hir_id()); let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a)); if !has_doc { @@ -874,7 +881,7 @@ declare_lint! { "detects anonymous parameters", @future_incompatible = FutureIncompatibleInfo { reference: "issue #41686 ", - edition: Some(Edition::Edition2018), + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), }; } @@ -983,13 +990,16 @@ impl EarlyLintPass for DeprecatedAttr { } fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) { + use rustc_ast::token::CommentKind; + let mut attrs = attrs.iter().peekable(); // Accumulate a single span for sugared doc comments. let mut sugared_span: Option = None; while let Some(attr) = attrs.next() { - if attr.is_doc_comment() { + let is_doc_comment = attr.is_doc_comment(); + if is_doc_comment { sugared_span = Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi()))); } @@ -1000,13 +1010,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & let span = sugared_span.take().unwrap_or(attr.span); - if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) { + if is_doc_comment || cx.sess().check_name(attr, sym::doc) { cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { let mut err = lint.build("unused doc comment"); err.span_label( node_span, format!("rustdoc does not generate documentation for {}", node_kind), ); + match attr.kind { + AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => { + err.help("use `//` for a plain comment"); + } + AttrKind::DocComment(CommentKind::Block, _) => { + err.help("use `/* */` for a plain comment"); + } + } err.emit(); }); } @@ -1083,7 +1101,7 @@ declare_lint! { /// /// ### Explanation /// - /// An function with generics must have its symbol mangled to accommodate + /// A function with generics must have its symbol mangled to accommodate /// the generic parameter. The [`no_mangle` attribute] has no effect in /// this situation, and should be removed. /// @@ -1663,7 +1681,7 @@ declare_lint! { "`...` range patterns are deprecated", @future_incompatible = FutureIncompatibleInfo { reference: "issue #80165 ", - edition: Some(Edition::Edition2021), + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), }; } @@ -1891,7 +1909,7 @@ declare_lint! { "detects edition keywords being used as an identifier", @future_incompatible = FutureIncompatibleInfo { reference: "issue #49716 ", - edition: Some(Edition::Edition2018), + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), }; } @@ -2297,7 +2315,7 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(generic_associated_types)] + /// #![feature(const_generics)] /// ``` /// /// {{produces}} @@ -2326,7 +2344,7 @@ impl EarlyLintPass for IncompleteFeatures { .iter() .map(|(name, span, _)| (name, span)) .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span))) - .filter(|(name, _)| rustc_feature::INCOMPLETE_FEATURES.iter().any(|f| name == &f)) + .filter(|(&name, _)| features.incomplete(name)) .for_each(|(&name, &span)| { cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| { let mut builder = lint.build(&format!( diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index a8df1b0952..f448acd24f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -16,7 +16,7 @@ use self::TargetLint::*; -use crate::levels::LintLevelsBuilder; +use crate::levels::{is_known_lint_tool, LintLevelsBuilder}; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; @@ -129,6 +129,8 @@ pub enum CheckLintNameResult<'a> { Ok(&'a [LintId]), /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name. NoLint(Option), + /// The lint refers to a tool that has not been registered. + NoTool, /// The lint is either renamed or removed. This is the warning /// message, and an optional new name (`None` if removed). Warning(String, Option), @@ -209,8 +211,8 @@ impl LintStore { bug!("duplicate specification of lint {}", lint.name_lower()) } - if let Some(FutureIncompatibleInfo { edition, .. }) = lint.future_incompatible { - if let Some(edition) = edition { + if let Some(FutureIncompatibleInfo { reason, .. }) = lint.future_incompatible { + if let Some(edition) = reason.edition() { self.lint_groups .entry(edition.lint_name()) .or_insert(LintGroup { @@ -220,17 +222,20 @@ impl LintStore { }) .lint_ids .push(id); + } else { + // Lints belonging to the `future_incompatible` lint group are lints where a + // future version of rustc will cause existing code to stop compiling. + // Lints tied to an edition don't count because they are opt-in. + self.lint_groups + .entry("future_incompatible") + .or_insert(LintGroup { + lint_ids: vec![], + from_plugin: lint.is_plugin, + depr: None, + }) + .lint_ids + .push(id); } - - self.lint_groups - .entry("future_incompatible") - .or_insert(LintGroup { - lint_ids: vec![], - from_plugin: lint.is_plugin, - depr: None, - }) - .lint_ids - .push(id); } } } @@ -273,22 +278,6 @@ impl LintStore { } } - /// This lint should be available with either the old or the new name. - /// - /// Using the old name will not give a warning. - /// You must register a lint with the new name before calling this function. - #[track_caller] - pub fn register_alias(&mut self, old_name: &str, new_name: &str) { - let target = match self.by_name.get(new_name) { - Some(&Id(lint_id)) => lint_id, - _ => bug!("cannot add alias {} for lint {} that does not exist", old_name, new_name), - }; - match self.by_name.insert(old_name.to_string(), Id(target)) { - None | Some(Ignored) => {} - Some(x) => bug!("duplicate specification of lint {} (was {:?})", old_name, x), - } - } - /// This lint should give no warning and have no effect. /// /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers them as tool lints. @@ -334,15 +323,17 @@ impl LintStore { } } - /// Checks the validity of lint names derived from the command line. Returns - /// true if the lint is valid, false otherwise. + /// Checks the validity of lint names derived from the command line. pub fn check_lint_name_cmdline( &self, sess: &Session, lint_name: &str, - level: Option, - ) -> bool { - let db = match self.check_lint_name(lint_name, None) { + level: Level, + crate_attrs: &[ast::Attribute], + ) { + let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name); + + let db = match self.check_lint_name(sess, lint_name_only, tool_name, crate_attrs) { CheckLintNameResult::Ok(_) => None, CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)), CheckLintNameResult::NoLint(suggestion) => { @@ -364,26 +355,29 @@ impl LintStore { ))), _ => None, }, + CheckLintNameResult::NoTool => Some(struct_span_err!( + sess, + DUMMY_SP, + E0602, + "unknown lint tool: `{}`", + tool_name.unwrap() + )), }; if let Some(mut db) = db { - if let Some(level) = level { - let msg = format!( - "requested on the command line with `{} {}`", - match level { - Level::Allow => "-A", - Level::Warn => "-W", - Level::Deny => "-D", - Level::Forbid => "-F", - }, - lint_name - ); - db.note(&msg); - } + let msg = format!( + "requested on the command line with `{} {}`", + match level { + Level::Allow => "-A", + Level::Warn => "-W", + Level::ForceWarn => "--force-warn", + Level::Deny => "-D", + Level::Forbid => "-F", + }, + lint_name + ); + db.note(&msg); db.emit(); - false - } else { - true } } @@ -410,9 +404,17 @@ impl LintStore { /// printing duplicate warnings. pub fn check_lint_name( &self, + sess: &Session, lint_name: &str, tool_name: Option, + crate_attrs: &[ast::Attribute], ) -> CheckLintNameResult<'_> { + if let Some(tool_name) = tool_name { + if !is_known_lint_tool(tool_name, sess, crate_attrs) { + return CheckLintNameResult::NoTool; + } + } + let complete_name = if let Some(tool_name) = tool_name { format!("{}::{}", tool_name, lint_name) } else { @@ -479,17 +481,17 @@ impl LintStore { fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> { let name_lower = lint_name.to_lowercase(); - let symbols = - self.get_lints().iter().map(|l| Symbol::intern(&l.name_lower())).collect::>(); if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() { // First check if the lint name is (partly) in upper case instead of lower case... - CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower))) - } else { - // ...if not, search for lints with a similar name - let suggestion = find_best_match_for_name(&symbols, Symbol::intern(&name_lower), None); - CheckLintNameResult::NoLint(suggestion) + return CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower))); } + // ...if not, search for lints with a similar name + let groups = self.lint_groups.keys().copied().map(Symbol::intern); + let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower())); + let names: Vec = groups.chain(lints).collect(); + let suggestion = find_best_match_for_name(&names, Symbol::intern(&name_lower), None); + CheckLintNameResult::NoLint(suggestion) } fn check_tool_name_for_backwards_compat( @@ -723,6 +725,15 @@ pub trait LintContext: Sized { BuiltinLintDiagnostics::OrPatternsBackCompat(span,suggestion) => { db.span_suggestion(span, "use pat_param to preserve semantics", suggestion, Applicability::MachineApplicable); } + BuiltinLintDiagnostics::ReservedPrefix(span) => { + db.span_label(span, "unknown prefix"); + db.span_suggestion_verbose( + span.shrink_to_hi(), + "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", + " ".into(), + Applicability::MachineApplicable, + ); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); @@ -1019,3 +1030,14 @@ impl<'tcx> LayoutOf for LateContext<'tcx> { self.tcx.layout_of(self.param_env.and(ty)) } } + +pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option, &str) { + match lint_name.split_once("::") { + Some((tool_name, lint_name)) => { + let tool_name = Symbol::intern(tool_name); + + (Some(tool_name), lint_name) + } + None => (None, lint_name), + } +} diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index eb2e495f73..7a8b731da5 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -120,6 +120,12 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> }) } + fn visit_expr_field(&mut self, f: &'a ast::ExprField) { + self.with_lint_attrs(f.id, &f.attrs, |cx| { + ast_visit::walk_expr_field(cx, f); + }) + } + fn visit_stmt(&mut self, s: &'a ast::Stmt) { // Add the statement's lint attributes to our // current state when checking the statement itself. @@ -204,8 +210,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_arm(&mut self, a: &'a ast::Arm) { - run_early_pass!(self, check_arm, a); - ast_visit::walk_arm(self, a); + self.with_lint_attrs(a.id, &a.attrs, |cx| { + run_early_pass!(cx, check_arm, a); + ast_visit::walk_arm(cx, a); + }) } fn visit_expr_post(&mut self, e: &'a ast::Expr) { @@ -389,9 +397,15 @@ pub fn check_ast_crate( // All of the buffered lints should have been emitted at this point. // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. - for (_id, lints) in buffered.map { + for (id, lints) in buffered.map { for early_lint in lints { - sess.delay_span_bug(early_lint.span, "failed to process buffered lint here"); + sess.delay_span_bug( + early_lint.span, + &format!( + "failed to process buffered lint here (dummy = {})", + id == ast::DUMMY_NODE_ID + ), + ); } } } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 0398d4a996..8a4a708943 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -2,15 +2,17 @@ //! Clippy. use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; -use rustc_ast::{ImplKind, Item, ItemKind}; -use rustc_data_structures::fx::FxHashMap; +use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind}; +use rustc_hir::{ + GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty, + TyKind, +}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; declare_tool_lint! { pub rustc::DEFAULT_HASH_TYPES, @@ -19,43 +21,35 @@ declare_tool_lint! { report_in_external_macro: true } -pub struct DefaultHashTypes { - map: FxHashMap, -} - -impl DefaultHashTypes { - // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself - #[allow(rustc::default_hash_types)] - pub fn new() -> Self { - let mut map = FxHashMap::default(); - map.insert(sym::HashMap, sym::FxHashMap); - map.insert(sym::HashSet, sym::FxHashSet); - Self { map } - } -} +declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); -impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); - -impl EarlyLintPass for DefaultHashTypes { - fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { - if let Some(replace) = self.map.get(&ident.name) { - cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, |lint| { - // FIXME: We can avoid a copy here. Would require us to take String instead of &str. - let msg = format!("Prefer {} over {}, it has better performance", replace, ident); - lint.build(&msg) - .span_suggestion( - ident.span, - "use", - replace.to_string(), - Applicability::MaybeIncorrect, // FxHashMap, ... needs another import - ) - .note(&format!( - "a `use rustc_data_structures::fx::{}` may be necessary", - replace - )) - .emit(); - }); +impl LateLintPass<'_> for DefaultHashTypes { + fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { + let def_id = match path.res { + Res::Def(rustc_hir::def::DefKind::Struct, id) => id, + _ => return, + }; + if matches!(cx.tcx.hir().get(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) { + // don't lint imports, only actual usages + return; } + let replace = if cx.tcx.is_diagnostic_item(sym::hashmap_type, def_id) { + "FxHashMap" + } else if cx.tcx.is_diagnostic_item(sym::hashset_type, def_id) { + "FxHashSet" + } else { + return; + }; + cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| { + let msg = format!( + "prefer `{}` over `{}`, it has better performance", + replace, + cx.tcx.item_name(def_id) + ); + lint.build(&msg) + .note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace)) + .emit(); + }); } } @@ -242,27 +236,17 @@ declare_tool_lint! { declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]); impl EarlyLintPass for LintPassImpl { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Impl(box ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { + if let ast::ItemKind::Impl(box ast::ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind + { if let Some(last) = lint_pass.path.segments.last() { if last.ident.name == sym::LintPass { let expn_data = lint_pass.path.span.ctxt().outer_expn_data(); let call_site = expn_data.call_site; - if !matches!( - expn_data.kind, - ExpnKind::Macro { - kind: MacroKind::Bang, - name: sym::impl_lint_pass, - proc_macro: _ - } - ) && !matches!( - call_site.ctxt().outer_expn_data().kind, - ExpnKind::Macro { - kind: MacroKind::Bang, - name: sym::declare_lint_pass, - proc_macro: _ - } - ) { + if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass) + && call_site.ctxt().outer_expn_data().kind + != ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass) + { cx.struct_span_lint( LINT_PASS_IMPL_WITHOUT_MACRO, lint_pass.path.span, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 0ee434f5fb..069fa41fa8 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -11,7 +11,8 @@ use rustc_middle::hir::map::Map; use rustc_middle::lint::LevelAndSource; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::lint::{ - struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, + struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, LintStackIndex, + COMMAND_LINE, }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -25,8 +26,6 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{source_map::MultiSpan, Span, DUMMY_SP}; use tracing::debug; -use std::cmp; - fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { let store = unerased_lint_store(tcx); let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); @@ -50,15 +49,15 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { pub struct LintLevelsBuilder<'s> { sess: &'s Session, sets: LintLevelSets, - id_to_set: FxHashMap, - cur: u32, + id_to_set: FxHashMap, + cur: LintStackIndex, warn_about_weird_lints: bool, store: &'s LintStore, crate_attrs: &'s [ast::Attribute], } pub struct BuilderPush { - prev: u32, + prev: LintStackIndex, pub changed: bool, } @@ -72,7 +71,7 @@ impl<'s> LintLevelsBuilder<'s> { let mut builder = LintLevelsBuilder { sess, sets: LintLevelSets::new(), - cur: 0, + cur: COMMAND_LINE, id_to_set: Default::default(), warn_about_weird_lints, store, @@ -88,14 +87,8 @@ impl<'s> LintLevelsBuilder<'s> { self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid); for &(ref lint_name, level) in &sess.opts.lint_opts { - store.check_lint_name_cmdline(sess, &lint_name, Some(level)); + store.check_lint_name_cmdline(sess, &lint_name, level, self.crate_attrs); let orig_level = level; - - // If the cap is less than this specified level, e.g., if we've got - // `--cap-lints allow` but we've also got `-D foo` then we ignore - // this specification as the lint cap will set it to allow anyway. - let level = cmp::min(level, self.sets.lint_cap); - let lint_flag_val = Symbol::intern(lint_name); let ids = match store.find_lints(&lint_name) { @@ -103,23 +96,18 @@ impl<'s> LintLevelsBuilder<'s> { Err(_) => continue, // errors handled in check_lint_name_cmdline above }; for id in ids { + // ForceWarn and Forbid cannot be overriden + if let Some((Level::ForceWarn | Level::Forbid, _)) = specs.get(&id) { + continue; + } + self.check_gated_lint(id, DUMMY_SP); let src = LintLevelSource::CommandLine(lint_flag_val, orig_level); specs.insert(id, (level, src)); } } - for lint_name in &sess.opts.force_warns { - let valid = store.check_lint_name_cmdline(sess, lint_name, None); - if valid { - let lints = store - .find_lints(lint_name) - .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids")); - self.sets.force_warns.extend(&lints); - } - } - - self.sets.list.push(LintSet::CommandLine { specs }); + self.cur = self.sets.list.push(LintSet { specs, parent: COMMAND_LINE }); } /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful @@ -131,6 +119,8 @@ impl<'s> LintLevelsBuilder<'s> { id: LintId, (level, src): LevelAndSource, ) { + let (old_level, old_src) = + self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess); // 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 overriden by `--cap-lints`. @@ -138,9 +128,7 @@ impl<'s> LintLevelsBuilder<'s> { // This means that this only errors if we're truly lowering the lint // level from forbid. if level != Level::Forbid { - if let (Level::Forbid, old_src) = - self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess) - { + if let Level::Forbid = old_level { // Backwards compatibility check: // // We used to not consider `forbid(lint_group)` @@ -152,9 +140,6 @@ impl<'s> LintLevelsBuilder<'s> { LintLevelSource::Default => false, LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol), LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol), - LintLevelSource::ForceWarn(_symbol) => { - bug!("forced warn lint returned a forbid lint level") - } }; debug!( "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}", @@ -179,7 +164,6 @@ impl<'s> LintLevelsBuilder<'s> { LintLevelSource::CommandLine(_, _) => { diag_builder.note("`forbid` lint level was set on command line"); } - _ => bug!("forced warn lint returned a forbid lint level"), } diag_builder.emit(); }; @@ -216,7 +200,11 @@ impl<'s> LintLevelsBuilder<'s> { } } } - specs.insert(id, (level, src)); + if let Level::ForceWarn = old_level { + specs.insert(id, (old_level, old_src)); + } else { + specs.insert(id, (level, src)); + } } /// Pushes a list of AST lint attributes onto this context. @@ -320,33 +308,14 @@ impl<'s> LintLevelsBuilder<'s> { continue; } }; - let tool_name = if meta_item.path.segments.len() > 1 { - let tool_ident = meta_item.path.segments[0].ident; - if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) { - let mut err = struct_span_err!( - sess, - tool_ident.span, - E0710, - "unknown tool name `{}` found in scoped lint: `{}`", - tool_ident.name, - pprust::path_to_string(&meta_item.path), - ); - if sess.is_nightly_build() { - err.help(&format!( - "add `#![register_tool({})]` to the crate root", - tool_ident.name - )); - } - err.emit(); - continue; - } - - Some(meta_item.path.segments.remove(0).ident.name) + let tool_ident = if meta_item.path.segments.len() > 1 { + Some(meta_item.path.segments.remove(0).ident) } else { None }; + let tool_name = tool_ident.map(|ident| ident.name); let name = pprust::path_to_string(&meta_item.path); - let lint_result = store.check_lint_name(&name, tool_name); + let lint_result = store.check_lint_name(sess, &name, tool_name, self.crate_attrs); match &lint_result { CheckLintNameResult::Ok(ids) => { let src = LintLevelSource::Node( @@ -363,7 +332,8 @@ impl<'s> LintLevelsBuilder<'s> { CheckLintNameResult::Tool(result) => { match *result { Ok(ids) => { - let complete_name = &format!("{}::{}", tool_name.unwrap(), name); + let complete_name = + &format!("{}::{}", tool_ident.unwrap().name, name); let src = LintLevelSource::Node( Symbol::intern(complete_name), sp, @@ -418,6 +388,26 @@ impl<'s> LintLevelsBuilder<'s> { } } + &CheckLintNameResult::NoTool => { + let mut err = struct_span_err!( + sess, + tool_ident.map_or(DUMMY_SP, |ident| ident.span), + E0710, + "unknown tool name `{}` found in scoped lint: `{}::{}`", + tool_name.unwrap(), + tool_name.unwrap(), + pprust::path_to_string(&meta_item.path), + ); + if sess.is_nightly_build() { + err.help(&format!( + "add `#![register_tool({})]` to the crate root", + tool_name.unwrap() + )); + } + err.emit(); + continue; + } + _ if !self.warn_about_weird_lints => {} CheckLintNameResult::Warning(msg, renamed) => { @@ -449,8 +439,8 @@ impl<'s> LintLevelsBuilder<'s> { let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess); struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| { - let name = if let Some(tool_name) = tool_name { - format!("{}::{}", tool_name, name) + let name = if let Some(tool_ident) = tool_ident { + format!("{}::{}", tool_ident.name, name) } else { name.to_string() }; @@ -473,7 +463,9 @@ impl<'s> LintLevelsBuilder<'s> { if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result { // Ignore any errors or warnings that happen because the new name is inaccurate // NOTE: `new_name` already includes the tool name, so we don't have to add it again. - if let CheckLintNameResult::Ok(ids) = store.check_lint_name(&new_name, None) { + if let CheckLintNameResult::Ok(ids) = + store.check_lint_name(sess, &new_name, None, self.crate_attrs) + { let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason); for &id in ids { self.check_gated_lint(id, attr.span); @@ -522,8 +514,7 @@ impl<'s> LintLevelsBuilder<'s> { let prev = self.cur; if !specs.is_empty() { - self.cur = self.sets.list.len() as u32; - self.sets.list.push(LintSet::Node { specs, parent: prev }); + self.cur = self.sets.list.push(LintSet { specs, parent: prev }); } BuilderPush { prev, changed: prev != self.cur } @@ -577,7 +568,7 @@ impl<'s> LintLevelsBuilder<'s> { } } -fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool { +pub fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool { if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) { return true; } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4f59460aa8..c947801614 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -163,7 +163,7 @@ macro_rules! late_lint_passes { // FIXME: Turn the computation of types which implement Debug into a query // and change this to a module lint pass MissingDebugImplementations: MissingDebugImplementations::default(), - ArrayIntoIter: ArrayIntoIter, + ArrayIntoIter: ArrayIntoIter::default(), ClashingExternDeclarations: ClashingExternDeclarations::new(), DropTraitConstraints: DropTraitConstraints, TemporaryCStringAsPtr: TemporaryCStringAsPtr, @@ -325,6 +325,9 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { store.register_renamed("redundant_semicolon", "redundant_semicolons"); store.register_renamed("overlapping_patterns", "overlapping_range_endpoints"); store.register_renamed("safe_packed_borrows", "unaligned_references"); + store.register_renamed("disjoint_capture_migration", "rust_2021_incompatible_closure_captures"); + store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns"); + store.register_renamed("non_fmt_panic", "non_fmt_panics"); // These were moved to tool lints, but rustc still sees them when compiling normally, before // tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use @@ -472,10 +475,10 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { } fn register_internals(store: &mut LintStore) { - store.register_lints(&DefaultHashTypes::get_lints()); - store.register_early_pass(|| box DefaultHashTypes::new()); store.register_lints(&LintPassImpl::get_lints()); store.register_early_pass(|| box LintPassImpl); + store.register_lints(&DefaultHashTypes::get_lints()); + store.register_late_pass(|| box DefaultHashTypes); store.register_lints(&ExistingDocKeyword::get_lints()); store.register_late_pass(|| box ExistingDocKeyword); store.register_lints(&TyTyKind::get_lints()); @@ -494,3 +497,6 @@ fn register_internals(store: &mut LintStore) { ], ); } + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index c91dc37b37..a32caf1bc4 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -4,10 +4,12 @@ use rustc_errors::{pluralize, Applicability}; use rustc_hir as hir; use rustc_middle::ty; use rustc_parse_format::{ParseMode, Parser, Piece}; +use rustc_session::lint::FutureIncompatibilityReason; +use rustc_span::edition::Edition; use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol}; declare_lint! { - /// The `non_fmt_panic` lint detects `panic!(..)` invocations where the first + /// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first /// argument is not a formatting string. /// /// ### Example @@ -27,13 +29,17 @@ declare_lint! { /// an `i32` as message. /// /// Rust 2021 always interprets the first argument as format string. - NON_FMT_PANIC, + NON_FMT_PANICS, Warn, "detect single-argument panic!() invocations in which the argument is not a format string", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021), + explain_reason: false, + }; report_in_external_macro } -declare_lint_pass!(NonPanicFmt => [NON_FMT_PANIC]); +declare_lint_pass!(NonPanicFmt => [NON_FMT_PANICS]); impl<'tcx> LateLintPass<'tcx> for NonPanicFmt { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { @@ -85,9 +91,10 @@ 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_PANIC, arg_span, |lint| { + cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| { let mut l = lint.build("panic message is not a string literal"); - l.note("this is no longer accepted in Rust 2021"); + l.note("this usage of panic!() is deprecated; it will be a hard error in Rust 2021"); + l.note("for more information, see "); if !span.contains(arg_span) { // No clue where this argument is coming from. l.emit(); @@ -167,7 +174,7 @@ fn check_panic_str<'tcx>( [] => vec![fmt_span], v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(), }; - cx.struct_span_lint(NON_FMT_PANIC, arg_spans, |lint| { + cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| { let mut l = lint.build(match n_arguments { 1 => "panic message contains an unused formatting placeholder", _ => "panic message contains unused formatting placeholders", @@ -201,7 +208,7 @@ fn check_panic_str<'tcx>( Some(v) if v.len() == 1 => "panic message contains a brace", _ => "panic message contains braces", }; - cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or_else(|| vec![span]), |lint| { + cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| { let mut l = lint.build(msg); l.note("this message is not used as a format string, but will be in Rust 2021"); if span.contains(arg.span) { @@ -249,10 +256,6 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, } let macro_symbol = - if let hygiene::ExpnKind::Macro { kind: _, name: symbol, proc_macro: _ } = expn.kind { - symbol - } else { - Symbol::intern("panic") - }; + if let hygiene::ExpnKind::Macro(_, symbol) = expn.kind { symbol } else { sym::panic }; (expn.call_site, panic_macro, macro_symbol.as_str()) } diff --git a/compiler/rustc_lint/src/tests.rs b/compiler/rustc_lint/src/tests.rs new file mode 100644 index 0000000000..fc9d6f636b --- /dev/null +++ b/compiler/rustc_lint/src/tests.rs @@ -0,0 +1,26 @@ +use crate::context::parse_lint_and_tool_name; +use rustc_span::{create_default_session_globals_then, Symbol}; + +#[test] +fn parse_lint_no_tool() { + create_default_session_globals_then(|| { + assert_eq!(parse_lint_and_tool_name("foo"), (None, "foo")) + }); +} + +#[test] +fn parse_lint_with_tool() { + create_default_session_globals_then(|| { + assert_eq!(parse_lint_and_tool_name("clippy::foo"), (Some(Symbol::intern("clippy")), "foo")) + }); +} + +#[test] +fn parse_lint_multiple_path() { + create_default_session_globals_then(|| { + assert_eq!( + parse_lint_and_tool_name("clippy::foo::bar"), + (Some(Symbol::intern("clippy")), "foo::bar") + ) + }); +} diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index e632f29e67..e713ce7c71 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -37,10 +37,47 @@ declare_lint! { "bounds of the form `T: Drop` are useless" } +declare_lint! { + /// The `dyn_drop` lint checks for trait objects with `std::ops::Drop`. + /// + /// ### Example + /// + /// ```rust + /// fn foo(_x: Box) {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// A trait object bound of the form `dyn Drop` is most likely misleading + /// and not what the programmer intended. + /// + /// `Drop` bounds do not actually indicate whether a type can be trivially + /// dropped or not, because a composite type containing `Drop` types does + /// not necessarily implement `Drop` itself. Naïvely, one might be tempted + /// to write a deferred drop system, to pull cleaning up memory out of a + /// latency-sensitive code path, using `dyn Drop` trait objects. However, + /// this breaks down e.g. when `T` is `String`, which does not implement + /// `Drop`, but should probably be accepted. + /// + /// To write a trait object bound that accepts anything, use a placeholder + /// trait with a blanket implementation. + /// + /// ```rust + /// trait Placeholder {} + /// impl Placeholder for T {} + /// fn foo(_x: Box) {} + /// ``` + pub DYN_DROP, + Warn, + "trait objects of the form `dyn Drop` are useless" +} + declare_lint_pass!( /// Lint for bounds of the form `T: Drop`, which usually /// indicate an attempt to emulate `std::mem::needs_drop`. - DropTraitConstraints => [DROP_BOUNDS] + DropTraitConstraints => [DROP_BOUNDS, DYN_DROP] ); impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { @@ -75,4 +112,28 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { } } } + + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { + let bounds = match &ty.kind { + hir::TyKind::TraitObject(bounds, _lifetime, _syntax) => bounds, + _ => return, + }; + 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 needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) { + Some(needs_drop) => needs_drop, + None => return, + }; + let msg = format!( + "types that do not implement `Drop` can still have drop glue, consider \ + instead using `{}` to detect whether a type is trivially dropped", + cx.tcx.def_path_str(needs_drop) + ); + lint.build(&msg).emit() + }); + } + } + } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 44c2a550c3..c431c048ca 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -154,6 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { | hir::BinOpKind::Shl | hir::BinOpKind::Shr => Some("bitwise operation"), }, + hir::ExprKind::AddrOf(..) => Some("borrow"), hir::ExprKind::Unary(..) => Some("unary operation"), _ => None, }; diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml index f909f15978..292833843e 100644 --- a/compiler/rustc_lint_defs/Cargo.toml +++ b/compiler/rustc_lint_defs/Cargo.toml @@ -5,7 +5,6 @@ version = "0.0.0" edition = "2018" [dependencies] -log = { package = "tracing", version = "0.1" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 352146d646..1b416f37bd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -6,7 +6,7 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use crate::{declare_lint, declare_lint_pass, FutureBreakage}; +use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason}; use rustc_span::edition::Edition; declare_lint! { @@ -41,7 +41,6 @@ declare_lint! { "applying forbid to lint-groups", @future_incompatible = FutureIncompatibleInfo { reference: "issue #81670 ", - edition: None, }; } @@ -77,7 +76,6 @@ declare_lint! { "ill-formed attribute inputs that were previously accepted and used in practice", @future_incompatible = FutureIncompatibleInfo { reference: "issue #57571 ", - edition: None, }; crate_level_only } @@ -114,7 +112,6 @@ declare_lint! { "conflicts between `#[repr(..)]` hints that were previously accepted and used in practice", @future_incompatible = FutureIncompatibleInfo { reference: "issue #68585 ", - edition: None, }; } @@ -293,7 +290,6 @@ declare_lint! { "constant evaluation encountered erroneous expression", @future_incompatible = FutureIncompatibleInfo { reference: "issue #71800 ", - edition: None, }; report_in_external_macro } @@ -900,7 +896,6 @@ declare_lint! { "detect private items in public interfaces not caught by the old implementation", @future_incompatible = FutureIncompatibleInfo { reference: "issue #34537 ", - edition: None, }; } @@ -980,7 +975,6 @@ declare_lint! { "detect public re-exports of private extern crates", @future_incompatible = FutureIncompatibleInfo { reference: "issue #34537 ", - edition: None, }; } @@ -1010,7 +1004,6 @@ declare_lint! { "type parameter default erroneously allowed in invalid location", @future_incompatible = FutureIncompatibleInfo { reference: "issue #36887 ", - edition: None, }; } @@ -1078,7 +1071,6 @@ declare_lint! { "detects unaligned references to fields of packed structs", @future_incompatible = FutureIncompatibleInfo { reference: "issue #82523 ", - edition: None, }; report_in_external_macro } @@ -1200,7 +1192,6 @@ declare_lint! { "patterns in functions without body were erroneously allowed", @future_incompatible = FutureIncompatibleInfo { reference: "issue #35203 ", - edition: None, }; } @@ -1244,7 +1235,6 @@ declare_lint! { "detects missing fragment specifiers in unused `macro_rules!` patterns", @future_incompatible = FutureIncompatibleInfo { reference: "issue #40107 ", - edition: None, }; } @@ -1286,7 +1276,6 @@ declare_lint! { "detects generic lifetime arguments in path segments with late bound lifetime parameters", @future_incompatible = FutureIncompatibleInfo { reference: "issue #42868 ", - edition: None, }; } @@ -1322,7 +1311,6 @@ declare_lint! { "trait-object types were treated as different depending on marker-trait order", @future_incompatible = FutureIncompatibleInfo { reference: "issue #56484 ", - edition: None, }; } @@ -1362,7 +1350,6 @@ declare_lint! { "distinct impls distinguished only by the leak-check code", @future_incompatible = FutureIncompatibleInfo { reference: "issue #56105 ", - edition: None, }; } @@ -1554,7 +1541,7 @@ declare_lint! { "raw pointer to an inference variable", @future_incompatible = FutureIncompatibleInfo { reference: "issue #46906 ", - edition: Some(Edition::Edition2018), + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), }; } @@ -1621,7 +1608,7 @@ declare_lint! { "suggest using `dyn Trait` for trait objects", @future_incompatible = FutureIncompatibleInfo { reference: "issue #80165 ", - edition: Some(Edition::Edition2021), + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), }; } @@ -1676,7 +1663,7 @@ declare_lint! { instead of `crate`, `self`, or an extern crate name", @future_incompatible = FutureIncompatibleInfo { reference: "issue #53130 ", - edition: Some(Edition::Edition2018), + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), }; } @@ -1725,7 +1712,6 @@ declare_lint! { "floating-point literals cannot be used in patterns", @future_incompatible = FutureIncompatibleInfo { reference: "issue #41620 ", - edition: None, }; } @@ -1769,7 +1755,6 @@ declare_lint! { "detects name collision with an existing but unstable method", @future_incompatible = FutureIncompatibleInfo { reference: "issue #48919 ", - edition: None, // Note: this item represents future incompatibility of all unstable functions in the // standard library, and thus should never be removed or changed to an error. }; @@ -1873,7 +1858,6 @@ declare_lint! { "checks the object safety of where clauses", @future_incompatible = FutureIncompatibleInfo { reference: "issue #51443 ", - edition: None, }; } @@ -1940,7 +1924,6 @@ declare_lint! { "detects proc macro derives using inaccessible names from parent modules", @future_incompatible = FutureIncompatibleInfo { reference: "issue #83583 ", - edition: None, }; } @@ -2043,7 +2026,6 @@ declare_lint! { cannot be referred to by absolute paths", @future_incompatible = FutureIncompatibleInfo { reference: "issue #52234 ", - edition: None, }; crate_level_only } @@ -2134,7 +2116,6 @@ declare_lint! { "constant used in pattern contains value of non-structural-match type in a field or a variant", @future_incompatible = FutureIncompatibleInfo { reference: "issue #62411 ", - edition: None, }; } @@ -2190,7 +2171,6 @@ declare_lint! { "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { reference: "issue #62411 ", - edition: None, }; } @@ -2229,7 +2209,6 @@ declare_lint! { expression contains values of non-structural-match types", @future_incompatible = FutureIncompatibleInfo { reference: "issue #73448 ", - edition: None, }; } @@ -2287,7 +2266,6 @@ declare_lint! { "ambiguous associated items", @future_incompatible = FutureIncompatibleInfo { reference: "issue #57644 ", - edition: None, }; } @@ -2318,7 +2296,6 @@ declare_lint! { "reservation of a two-phased borrow conflicts with other shared borrows", @future_incompatible = FutureIncompatibleInfo { reference: "issue #59159 ", - edition: None, }; } @@ -2360,7 +2337,6 @@ declare_lint! { "a feature gate that doesn't break dependent crates", @future_incompatible = FutureIncompatibleInfo { reference: "issue #64266 ", - edition: None, }; } @@ -2589,7 +2565,6 @@ declare_lint! { "a C-like enum implementing Drop is cast", @future_incompatible = FutureIncompatibleInfo { reference: "issue #73333 ", - edition: None, }; } @@ -2629,7 +2604,6 @@ declare_lint! { "detects a generic constant is used in a type without a emitting a warning", @future_incompatible = FutureIncompatibleInfo { reference: "issue #76200 ", - edition: None, }; } @@ -2688,7 +2662,6 @@ declare_lint! { "uninhabited static", @future_incompatible = FutureIncompatibleInfo { reference: "issue #74840 ", - edition: None, }; } @@ -2758,7 +2731,6 @@ declare_lint! { "unsupported naked function definitions", @future_incompatible = FutureIncompatibleInfo { reference: "issue #32408 ", - edition: None, }; } @@ -2831,7 +2803,6 @@ declare_lint! { "trailing semicolon in macro body used as expression", @future_incompatible = FutureIncompatibleInfo { reference: "issue #79813 ", - edition: None, }; } @@ -2996,11 +2967,14 @@ declare_lint_pass! { MISSING_ABI, INVALID_DOC_ATTRIBUTES, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, - DISJOINT_CAPTURE_MIGRATION, + RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, LEGACY_DERIVE_HELPERS, PROC_MACRO_BACK_COMPAT, - OR_PATTERNS_BACK_COMPAT, + RUST_2021_INCOMPATIBLE_OR_PATTERNS, LARGE_ASSIGNMENTS, + RUST_2021_PRELUDE_COLLISIONS, + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + UNSUPPORTED_CALLING_CONVENTIONS, ] } @@ -3028,9 +3002,8 @@ declare_lint! { } declare_lint! { - /// The `disjoint_capture_migration` lint detects variables that aren't completely - /// captured when the feature `capture_disjoint_fields` is enabled and it affects the Drop - /// order of at least one path starting at this variable. + /// The `rust_2021_incompatible_closure_captures` lint detects variables that aren't completely + /// captured in Rust 2021 and affect the Drop order of at least one path starting at this variable. /// It can also detect when a variable implements a trait, but one of its field does not and /// the field is captured by a closure and used with the assumption that said field implements /// the same trait as the root variable. @@ -3038,7 +3011,7 @@ declare_lint! { /// ### Example of drop reorder /// /// ```rust,compile_fail - /// # #![deny(disjoint_capture_migration)] + /// # #![deny(rust_2021_incompatible_closure_captures)] /// # #![allow(unused)] /// struct FancyInteger(i32); /// @@ -3067,16 +3040,16 @@ declare_lint! { /// /// ### Explanation /// - /// In the above example `p.y` will be dropped at the end of `f` instead of with `c` if - /// the feature `capture_disjoint_fields` is enabled. + /// In the above example, `p.y` will be dropped at the end of `f` instead of + /// with `c` in Rust 2021. /// /// ### Example of auto-trait /// /// ```rust,compile_fail - /// #![deny(disjoint_capture_migration)] + /// #![deny(rust_2021_incompatible_closure_captures)] /// use std::thread; /// - /// struct Pointer (*mut i32); + /// struct Pointer(*mut i32); /// unsafe impl Send for Pointer {} /// /// fn main() { @@ -3092,12 +3065,16 @@ declare_lint! { /// /// ### Explanation /// - /// In the above example `fptr.0` is captured when feature `capture_disjoint_fields` is enabled. + /// In the above example, only `fptr.0` is captured in Rust 2021. /// The field is of type *mut i32 which doesn't implement Send, making the code invalid as the /// field cannot be sent between thread safely. - pub DISJOINT_CAPTURE_MIGRATION, + pub RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, Allow, - "Drop reorder and auto traits error because of `capture_disjoint_fields`" + "detects closures affected by Rust 2021 changes", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021), + explain_reason: false, + }; } declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]); @@ -3153,7 +3130,6 @@ declare_lint! { "detects invalid `#[doc(...)]` attributes", @future_incompatible = FutureIncompatibleInfo { reference: "issue #82730 ", - edition: None, }; } @@ -3200,20 +3176,17 @@ declare_lint! { "detects usage of old versions of certain proc-macro crates", @future_incompatible = FutureIncompatibleInfo { reference: "issue #83125 ", - edition: None, - future_breakage: Some(FutureBreakage { - date: None - }) + reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } declare_lint! { - /// The `or_patterns_back_compat` lint detects usage of old versions of or-patterns. + /// The `rust_2021_incompatible_or_patterns` lint detects usage of old versions of or-patterns. /// /// ### Example /// /// ```rust,compile_fail - /// #![deny(or_patterns_back_compat)] + /// #![deny(rust_2021_incompatible_or_patterns)] /// macro_rules! match_any { /// ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { /// match $expr { @@ -3236,7 +3209,142 @@ declare_lint! { /// ### Explanation /// /// In Rust 2021, the pat matcher will match new patterns, which include the | character. - pub OR_PATTERNS_BACK_COMPAT, + pub RUST_2021_INCOMPATIBLE_OR_PATTERNS, Allow, "detects usage of old versions of or-patterns", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #84869 ", + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + }; +} + +declare_lint! { + /// The `rust_2021_prelude_collisions` lint detects the usage of trait methods which are ambiguous + /// with traits added to the prelude in future editions. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(rust_2021_prelude_collisions)] + /// + /// trait Foo { + /// fn try_into(self) -> Result; + /// } + /// + /// impl Foo for &str { + /// fn try_into(self) -> Result { + /// Ok(String::from(self)) + /// } + /// } + /// + /// fn main() { + /// let x: String = "3".try_into().unwrap(); + /// // ^^^^^^^^ + /// // This call to try_into matches both Foo:try_into and TryInto::try_into as + /// // `TryInto` has been added to the Rust prelude in 2021 edition. + /// println!("{}", x); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In Rust 2021, one of the important introductions is the [prelude changes], which add + /// `TryFrom`, `TryInto`, and `FromIterator` into the standard library's prelude. Since this + /// results in an ambiguity as to which method/function to call when an existing `try_into` + /// method is called via dot-call syntax or a `try_from`/`from_iter` associated function + /// is called directly on a type. + /// + /// [prelude changes]: https://blog.rust-lang.org/inside-rust/2021/03/04/planning-rust-2021.html#prelude-changes + pub RUST_2021_PRELUDE_COLLISIONS, + Allow, + "detects the usage of trait methods which are ambiguous with traits added to the \ + prelude in future editions", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #85684 ", + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + }; +} + +declare_lint! { + /// The `rust_2021_prefixes_incompatible_syntax` lint detects identifiers that will be parsed as a + /// prefix instead in Rust 2021. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(rust_2021_prefixes_incompatible_syntax)] + /// + /// macro_rules! m { + /// (z $x:expr) => (); + /// } + /// + /// m!(z"hey"); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In Rust 2015 and 2018, `z"hey"` is two tokens: the identifier `z` + /// followed by the string literal `"hey"`. In Rust 2021, the `z` is + /// considered a prefix for `"hey"`. + /// + /// This lint suggests to add whitespace between the `z` and `"hey"` tokens + /// to keep them separated in Rust 2021. + pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + Allow, + "identifiers that will be parsed as a prefix in Rust 2021", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #84978 ", + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021), + }; + crate_level_only +} + +declare_lint! { + /// The `unsupported_calling_conventions` lint is output whenever there is an use of the + /// `stdcall`, `fastcall`, `thiscall`, `vectorcall` calling conventions (or their unwind + /// variants) on targets that cannot meaningfully be supported for the requested target. + /// + /// For example `stdcall` does not make much sense for a x86_64 or, more apparently, powerpc + /// code, because this calling convention was never specified for those targets. + /// + /// Historically MSVC toolchains have fallen back to the regular C calling convention for + /// targets other than x86, but Rust doesn't really see a similar need to introduce a similar + /// hack across many more targets. + /// + /// ### Example + /// + /// ```rust,ignore (needs specific targets) + /// extern "stdcall" fn stdcall() {} + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: use of calling convention not supported on this target + /// --> $DIR/unsupported.rs:39:1 + /// | + /// LL | extern "stdcall" fn stdcall() {} + /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + /// | + /// = note: `#[warn(unsupported_calling_conventions)]` on by default + /// = warning: this was previously accepted by the compiler but is being phased out; + /// it will become a hard error in a future release! + /// = note: for more information, see issue ... + /// ``` + /// + /// ### Explanation + /// + /// On most of the targets the behaviour of `stdcall` and similar calling conventions is not + /// defined at all, but was previously accepted due to a bug in the implementation of the + /// compiler. + pub UNSUPPORTED_CALLING_CONVENTIONS, + Warn, + "use of unsupported calling convention", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #87678 ", + }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f1c4e5fb4a..4190e76997 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -51,6 +51,7 @@ pub enum Applicability { pub enum Level { Allow, Warn, + ForceWarn, Deny, Forbid, } @@ -63,6 +64,7 @@ impl Level { match self { Level::Allow => "allow", Level::Warn => "warn", + Level::ForceWarn => "force-warn", Level::Deny => "deny", Level::Forbid => "forbid", } @@ -142,23 +144,50 @@ pub struct Lint { pub struct FutureIncompatibleInfo { /// e.g., a URL for an issue/PR/RFC or error code pub reference: &'static str, - /// If this is an edition fixing lint, the edition in which - /// this lint becomes obsolete - pub edition: Option, - /// Information about a future breakage, which will - /// be emitted in JSON messages to be displayed by Cargo - /// for upstream deps - pub future_breakage: Option, + /// The reason for the lint used by diagnostics to provide + /// the right help message + pub reason: FutureIncompatibilityReason, + /// Whether to explain the reason to the user. + /// + /// Set to false for lints that already include a more detailed + /// explanation. + pub explain_reason: bool, } +/// The reason for future incompatibility #[derive(Copy, Clone, Debug)] -pub struct FutureBreakage { - pub date: Option<&'static str>, +pub enum FutureIncompatibilityReason { + /// This will be an error in a future release + /// for all editions + FutureReleaseError, + /// This will be an error in a future release, and + /// Cargo should create a report even for dependencies + FutureReleaseErrorReportNow, + /// Previously accepted code that will become an + /// error in the provided edition + EditionError(Edition), + /// Code that changes meaning in some way in + /// the provided edition + EditionSemanticsChange(Edition), +} + +impl FutureIncompatibilityReason { + pub fn edition(self) -> Option { + match self { + Self::EditionError(e) => Some(e), + Self::EditionSemanticsChange(e) => Some(e), + _ => None, + } + } } impl FutureIncompatibleInfo { pub const fn default_fields_for_macro() -> Self { - FutureIncompatibleInfo { reference: "", edition: None, future_breakage: None } + FutureIncompatibleInfo { + reference: "", + reason: FutureIncompatibilityReason::FutureReleaseError, + explain_reason: true, + } } } @@ -245,7 +274,7 @@ impl ToStableHashKey for LintId { } // Duplicated from rustc_session::config::ExternDepSpec to avoid cyclic dependency -#[derive(PartialEq)] +#[derive(PartialEq, Debug)] pub enum ExternDepSpec { Json(Json), Raw(String), @@ -253,7 +282,7 @@ pub enum ExternDepSpec { // This could be a closure, but then implementing derive trait // becomes hacky (and it gets allocated). -#[derive(PartialEq)] +#[derive(PartialEq, Debug)] pub enum BuiltinLintDiagnostics { Normal, BareTraitObject(Span, /* is_global */ bool), @@ -272,6 +301,7 @@ pub enum BuiltinLintDiagnostics { ExternDepSpec(String, ExternDepSpec), ProcMacroBackCompat(String), OrPatternsBackCompat(Span, String), + ReservedPrefix(Span), } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 3fca2e1ccb..1bfa489d39 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -13,4 +13,4 @@ libc = "0.2.73" [build-dependencies] build_helper = { path = "../../src/build_helper" } -cc = "1.0.68" +cc = "1.0.69" diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 9b757eb40c..4cdc8a4155 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -349,11 +349,10 @@ extern "C" void LLVMRustSetFastMath(LLVMValueRef V) { } extern "C" LLVMValueRef -LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name, - LLVMAtomicOrdering Order) { +LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source, + const char *Name, LLVMAtomicOrdering Order) { Value *Ptr = unwrap(Source); - Type *Ty = Ptr->getType()->getPointerElementType(); - LoadInst *LI = unwrap(B)->CreateLoad(Ty, Ptr, Name); + LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name); LI->setAtomic(fromRust(Order)); return wrap(LI); } diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 30569f2079..b916113a0e 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -54,7 +54,7 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma quote! {} } else if let Some(project) = attrs.project { quote! { - &#bi.#project.hash_stable(__hcx, __hasher); + (&#bi.#project).hash_stable(__hcx, __hasher); } } else { quote! { @@ -96,7 +96,7 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To quote! {} } else if let Some(project) = attrs.project { quote! { - &#bi.#project.hash_stable(__hcx, __hasher); + (&#bi.#project).hash_stable(__hcx, __hasher); } } else { quote! { diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 291e7ef045..dcd36d61bc 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -367,7 +367,7 @@ fn add_query_description_impl( tcx: QueryCtxt<'tcx>, id: SerializedDepNodeIndex ) -> Option { - tcx.on_disk_cache.as_ref()?.try_load_query_result(*tcx, id) + tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id) } } }; diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 5b932864df..2f063f75eb 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -207,7 +207,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { #keyword_stream } - #[allow(rustc::default_hash_types)] + #[cfg_attr(bootstrap, allow(rustc::default_hash_types))] #[allow(non_upper_case_globals)] #[doc(hidden)] pub mod sym_generated { diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 29fa0b7006..14b4ebf073 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -23,7 +23,6 @@ rustc_target = { path = "../rustc_target" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } -stable_deref_trait = "1.0.0" rustc_ast = { path = "../rustc_ast" } rustc_expand = { path = "../rustc_expand" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index d73cfe35dc..5373169bda 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -21,7 +21,7 @@ use rustc_session::config::{self, CrateType, ExternLocation}; use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; -use rustc_session::{CrateDisambiguator, Session}; +use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -51,6 +51,12 @@ pub struct CStore { unused_externs: Vec, } +impl std::fmt::Debug for CStore { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CStore").finish_non_exhaustive() + } +} + pub struct CrateLoader<'a> { // Immutable configuration. sess: &'a Session, @@ -124,8 +130,11 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { } impl CStore { - crate fn from_tcx(tcx: TyCtxt<'_>) -> &CStore { - tcx.cstore_as_any().downcast_ref::().expect("`tcx.cstore` is not a `CStore`") + pub fn from_tcx(tcx: TyCtxt<'_>) -> &CStore { + tcx.cstore_untracked() + .as_any() + .downcast_ref::() + .expect("`tcx.cstore` is not a `CStore`") } fn alloc_new_crate_num(&mut self) -> CrateNum { @@ -222,10 +231,8 @@ impl<'a> CrateLoader<'a> { metadata_loader: Box, local_crate_name: &str, ) -> Self { - let local_crate_stable_id = - StableCrateId::new(local_crate_name, sess.local_crate_disambiguator()); let mut stable_crate_ids = FxHashMap::default(); - stable_crate_ids.insert(local_crate_stable_id, LOCAL_CRATE); + stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE); CrateLoader { sess, @@ -327,17 +334,14 @@ impl<'a> CrateLoader<'a> { fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { // Check for (potential) conflicts with the local crate - if self.local_crate_name == root.name() - && self.sess.local_crate_disambiguator() == root.disambiguator() - { + if self.sess.local_stable_crate_id() == root.stable_crate_id() { return Err(CrateError::SymbolConflictsCurrent(root.name())); } // Check for conflicts with any crate loaded so far let mut res = Ok(()); self.cstore.iter_crate_data(|_, other| { - if other.name() == root.name() && // same crate-name - other.disambiguator() == root.disambiguator() && // same crate-disambiguator + if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id other.hash() != root.hash() { // but different SVH @@ -411,7 +415,7 @@ impl<'a> CrateLoader<'a> { None => (&source, &crate_root), }; let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?) + Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?) } else { None }; @@ -598,7 +602,11 @@ impl<'a> CrateLoader<'a> { // don't want to match a host crate against an equivalent target one // already loaded. let root = library.metadata.get_root(); - Ok(Some(if locator.triple == self.sess.opts.target_triple { + // FIXME: why is this condition necessary? It was adding in #33625 but I + // don't know why and the original author doesn't remember ... + let can_reuse_cratenum = + locator.triple == self.sess.opts.target_triple || locator.is_proc_macro == Some(true); + Ok(Some(if can_reuse_cratenum { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { if data.name() == root.name() && root.hash() == data.hash() { @@ -664,7 +672,7 @@ impl<'a> CrateLoader<'a> { fn dlsym_proc_macros( &self, path: &Path, - disambiguator: CrateDisambiguator, + stable_crate_id: StableCrateId, ) -> Result<&'static [ProcMacro], CrateError> { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); @@ -673,7 +681,7 @@ impl<'a> CrateLoader<'a> { Err(s) => return Err(CrateError::DlOpen(s)), }; - let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator); + let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); let decls = unsafe { let sym = match lib.symbol(&sym) { Ok(f) => f, @@ -769,28 +777,32 @@ impl<'a> CrateLoader<'a> { } fn inject_profiler_runtime(&mut self, krate: &ast::Crate) { - if (self.sess.instrument_coverage() - || self.sess.opts.debugging_opts.profile - || self.sess.opts.cg.profile_generate.enabled()) - && !self.sess.opts.debugging_opts.no_profiler_runtime + let profiler_runtime = &self.sess.opts.debugging_opts.profiler_runtime; + + if !(profiler_runtime.is_some() + && (self.sess.instrument_coverage() + || self.sess.opts.debugging_opts.profile + || self.sess.opts.cg.profile_generate.enabled())) { - info!("loading profiler"); + return; + } - if self.sess.contains_name(&krate.attrs, sym::no_core) { - self.sess.err( - "`profiler_builtins` crate (required by compiler options) \ - is not compatible with crate attribute `#![no_core]`", - ); - } + info!("loading profiler"); + + let name = Symbol::intern(profiler_runtime.as_ref().unwrap()); + if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) { + self.sess.err( + "`profiler_builtins` crate (required by compiler options) \ + is not compatible with crate attribute `#![no_core]`", + ); + } - let name = sym::profiler_builtins; - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None); - let data = self.cstore.get_crate_data(cnum); + let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None); + let data = self.cstore.get_crate_data(cnum); - // Sanity check the loaded crate to ensure it is indeed a profiler runtime - if !data.is_profiler_runtime() { - self.sess.err("the crate `profiler_builtins` is not a profiler runtime"); - } + // Sanity check the loaded crate to ensure it is indeed a profiler runtime + if !data.is_profiler_runtime() { + self.sess.err(&format!("the crate `{}` is not a profiler runtime", name)); } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index c3afc9f048..2d4deb1d8d 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -55,8 +55,8 @@ use crate::creader::CStore; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::CrateNum; +use rustc_middle::middle::cstore::CrateDepKind; use rustc_middle::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; -use rustc_middle::middle::cstore::{self, CrateDepKind}; use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage}; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; @@ -129,7 +129,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { && sess.crt_static(Some(ty)) && !sess.target.crt_static_allows_dylibs) { - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -152,7 +152,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -170,7 +170,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { } // Collect what we've got so far in the return vector. - let last_crate = tcx.crates().len(); + let last_crate = tcx.crates(()).len(); let mut ret = (1..last_crate + 1) .map(|cnum| match formats.get(&CrateNum::new(cnum)) { Some(&RequireDynamic) => Linkage::Dynamic, @@ -184,7 +184,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // // If the crate hasn't been included yet and it's not actually required // (e.g., it's an allocator) then we skip it here as well. - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && !formats.contains_key(&cnum) @@ -274,14 +274,24 @@ fn add_library( } fn attempt_static(tcx: TyCtxt<'_>) -> Option { - let crates = cstore::used_crates(tcx, RequireStatic); - if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) { + let all_crates_available_as_rlib = tcx + .crates(()) + .iter() + .cloned() + .filter_map(|cnum| { + if tcx.dep_kind(cnum).macros_only() { + return None; + } + Some(tcx.used_crate_source(cnum).rlib.is_some()) + }) + .all(|is_rlib| is_rlib); + if !all_crates_available_as_rlib { return None; } // All crates are available in an rlib format, so we're just going to link // everything in explicitly so long as it's actually required. - let last_crate = tcx.crates().len(); + let last_crate = tcx.crates(()).len(); let mut ret = (1..last_crate + 1) .map(|cnum| { if tcx.dep_kind(CrateNum::new(cnum)) == CrateDepKind::Explicit { diff --git a/compiler/rustc_metadata/src/dynamic_lib.rs b/compiler/rustc_metadata/src/dynamic_lib.rs index 1a900ccbf6..e8929cd5c0 100644 --- a/compiler/rustc_metadata/src/dynamic_lib.rs +++ b/compiler/rustc_metadata/src/dynamic_lib.rs @@ -70,13 +70,12 @@ mod dl { use std::sync::{Mutex, MutexGuard}; pub fn lock() -> MutexGuard<'static, Guard> { - static LOCK: SyncLazy> = SyncLazy::new(|| Mutex::new(Guard { _priv: () })); + static LOCK: SyncLazy> = SyncLazy::new(|| Mutex::new(Guard)); LOCK.lock().unwrap() } - pub struct Guard { - _priv: (), - } + #[non_exhaustive] + pub struct Guard; impl Guard { pub fn get(&mut self) -> Result<(), String> { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 6e73609509..028104fd6b 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -226,7 +226,7 @@ use rustc_session::config::{self, CrateType}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; -use rustc_session::{CrateDisambiguator, Session}; +use rustc_session::{Session, StableCrateId}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; @@ -787,7 +787,7 @@ pub fn find_plugin_registrar( metadata_loader: &dyn MetadataLoader, span: Span, name: Symbol, -) -> (PathBuf, CrateDisambiguator) { +) -> (PathBuf, StableCrateId) { match find_plugin_registrar_impl(sess, metadata_loader, name) { Ok(res) => res, // `core` is always available if we got as far as loading plugins. @@ -799,7 +799,7 @@ fn find_plugin_registrar_impl<'a>( sess: &'a Session, metadata_loader: &dyn MetadataLoader, name: Symbol, -) -> Result<(PathBuf, CrateDisambiguator), CrateError> { +) -> Result<(PathBuf, StableCrateId), CrateError> { info!("find plugin registrar `{}`", name); let mut locator = CrateLocator::new( sess, @@ -816,7 +816,7 @@ fn find_plugin_registrar_impl<'a>( match locator.maybe_load_library_crate()? { Some(library) => match library.source.dylib { - Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())), + Some(dylib) => Ok((dylib.0, library.metadata.get_root().stable_crate_id())), None => Err(CrateError::NonDylibPlugin(name)), }, None => Err(locator.into_error()), @@ -1100,7 +1100,9 @@ impl CrateError { if sess.is_nightly_build() && std::env::var("CARGO").is_ok() { err.help("consider building the standard library from source with `cargo build -Zbuild-std`"); } - } else if crate_name == sym::profiler_builtins { + } else if Some(crate_name) + == sess.opts.debugging_opts.profiler_runtime.as_deref().map(Symbol::intern) + { err.note(&"the compiler may have been built without the profiler runtime"); } err.span_label(span, "can't find crate"); diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index cd4c394ae1..16b4d26b37 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -3,8 +3,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_middle::middle::cstore::{DllImport, NativeLib}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::middle::cstore::{DllCallingConvention, DllImport, NativeLib}; +use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_session::parse::feature_err; use rustc_session::utils::NativeLibKind; use rustc_session::Session; @@ -199,22 +199,10 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { } if lib.kind == NativeLibKind::RawDylib { - match abi { - Abi::C { .. } => (), - Abi::Cdecl => (), - _ => { - if sess.target.arch == "x86" { - sess.span_fatal( - it.span, - r#"`#[link(kind = "raw-dylib")]` only supports C and Cdecl ABIs"#, - ); - } - } - }; lib.dll_imports.extend( foreign_mod_items .iter() - .map(|child_item| DllImport { name: child_item.ident.name, ordinal: None }), + .map(|child_item| self.build_dll_import(abi, child_item)), ); } @@ -396,4 +384,58 @@ impl Collector<'tcx> { } } } + + fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize { + let argument_types: &List> = self.tcx.erase_late_bound_regions( + self.tcx + .type_of(item.id.def_id) + .fn_sig(self.tcx) + .inputs() + .map_bound(|slice| self.tcx.mk_type_list(slice.iter())), + ); + + argument_types + .iter() + .map(|ty| { + let layout = self + .tcx + .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty }) + .expect("layout") + .layout; + // In both stdcall and fastcall, we always round up the argument size to the + // nearest multiple of 4 bytes. + (layout.size.bytes_usize() + 3) & !3 + }) + .sum() + } + + fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport { + let calling_convention = if self.tcx.sess.target.arch == "x86" { + match abi { + Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C, + Abi::Stdcall { .. } | Abi::System { .. } => { + DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) + } + Abi::Fastcall => DllCallingConvention::Fastcall(self.i686_arg_list_size(item)), + // Vectorcall is intentionally not supported at this time. + _ => { + self.tcx.sess.span_fatal( + item.span, + r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#, + ); + } + } + } else { + match abi { + Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C, + _ => { + self.tcx.sess.span_fatal( + item.span, + r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#, + ); + } + } + }; + DllImport { name: item.ident.name, ordinal: None, calling_convention, span: item.span } + } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 48900fecd3..8bdd4313de 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -30,13 +30,12 @@ use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::Session; -use rustc_span::hygiene::ExpnDataDecodeMode; +use rustc_span::hygiene::{ExpnIndex, MacroKind}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{self, hygiene::MacroKind, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; +use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; use proc_macro::bridge::client::ProcMacro; -use std::cell::Cell; use std::io; use std::mem; use std::num::NonZeroUsize; @@ -80,6 +79,8 @@ crate struct CrateMetadata { /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how /// this is used. def_path_hash_map: OnceCell>, + /// Likewise for ExpnHash. + expn_hash_map: OnceCell>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. alloc_decoding_state: AllocDecodingState, /// Caches decoded `DefKey`s. @@ -350,6 +351,12 @@ impl<'a, 'tcx> Decodable> for DefIndex { } } +impl<'a, 'tcx> Decodable> for ExpnIndex { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result { + Ok(ExpnIndex::from_u32(d.read_u32()?)) + } +} + impl<'a, 'tcx> Decodable> for SyntaxContext { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { let cdata = decoder.cdata(); @@ -371,36 +378,35 @@ impl<'a, 'tcx> Decodable> for ExpnId { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result { let local_cdata = decoder.cdata(); let sess = decoder.sess.unwrap(); - let expn_cnum = Cell::new(None); - let get_ctxt = |cnum| { - expn_cnum.set(Some(cnum)); - if cnum == LOCAL_CRATE { - &local_cdata.hygiene_context - } else { - &local_cdata.cstore.get_crate_data(cnum).cdata.hygiene_context - } - }; - rustc_span::hygiene::decode_expn_id( - decoder, - ExpnDataDecodeMode::Metadata(get_ctxt), - |_this, index| { - let cnum = expn_cnum.get().unwrap(); - // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s - // are stored in the owning crate, to avoid duplication. - let crate_data = if cnum == LOCAL_CRATE { - local_cdata - } else { - local_cdata.cstore.get_crate_data(cnum) - }; - Ok(crate_data - .root - .expn_data - .get(&crate_data, index) - .unwrap() - .decode((&crate_data, sess))) - }, - ) + let cnum = CrateNum::decode(decoder)?; + let index = u32::decode(decoder)?; + + let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| { + let ExpnId { krate: cnum, local_id: index } = expn_id; + // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s + // are stored in the owning crate, to avoid duplication. + debug_assert_ne!(cnum, LOCAL_CRATE); + let crate_data = if cnum == local_cdata.cnum { + local_cdata + } else { + local_cdata.cstore.get_crate_data(cnum) + }; + let expn_data = crate_data + .root + .expn_data + .get(&crate_data, index) + .unwrap() + .decode((&crate_data, sess)); + let expn_hash = crate_data + .root + .expn_hashes + .get(&crate_data, index) + .unwrap() + .decode((&crate_data, sess)); + (expn_data, expn_hash) + }); + Ok(expn_id) } } @@ -601,10 +607,23 @@ impl MetadataBlob { } crate fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> { - write!(out, "=External Dependencies=\n")?; let root = self.get_root(); + writeln!(out, "Crate info:")?; + writeln!(out, "name {}{}", root.name, root.extra_filename)?; + writeln!(out, "hash {} stable_crate_id {:?}", root.hash, root.stable_crate_id)?; + writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?; + writeln!(out, "=External Dependencies=")?; for (i, dep) in root.crate_deps.decode(self).enumerate() { - write!(out, "{} {}{}\n", i + 1, dep.name, dep.extra_filename)?; + writeln!( + out, + "{} {}{} hash {} host_hash {:?} kind {:?}", + i + 1, + dep.name, + dep.extra_filename, + dep.hash, + dep.host_hash, + dep.kind + )?; } write!(out, "\n")?; Ok(()) @@ -620,10 +639,6 @@ impl CrateRoot<'_> { self.name } - crate fn disambiguator(&self) -> CrateDisambiguator { - self.disambiguator - } - crate fn hash(&self) -> Svh { self.hash } @@ -716,37 +731,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn load_proc_macro(&self, def_id: DefId, sess: &Session) -> SyntaxExtension { - let (name, kind, helper_attrs) = match *self.raw_proc_macro(def_id.index) { + fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { + let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { ProcMacro::CustomDerive { trait_name, attributes, client } => { let helper_attrs = attributes.iter().cloned().map(Symbol::intern).collect::>(); ( trait_name, - SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { - client, - krate: def_id.krate, - })), + SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })), helper_attrs, ) } - ProcMacro::Attr { name, client } => ( - name, - SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client, krate: def_id.krate })), - Vec::new(), - ), - ProcMacro::Bang { name, client } => ( - name, - SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client, krate: def_id.krate })), - Vec::new(), - ), + ProcMacro::Attr { name, client } => { + (name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()) + } + ProcMacro::Bang { name, client } => { + (name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()) + } }; - let attrs: Vec<_> = self.get_item_attrs(def_id.index, sess).collect(); + let attrs: Vec<_> = self.get_item_attrs(id, sess).collect(); SyntaxExtension::new( sess, kind, - self.get_span(def_id.index, sess), + self.get_span(id, sess), helper_attrs, self.root.edition, Symbol::intern(name), @@ -950,6 +958,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.get_impl_data(id).defaultness } + fn get_impl_constness(&self, id: DefIndex) -> hir::Constness { + self.get_impl_data(id).constness + } + fn get_coerce_unsized_info(&self, id: DefIndex) -> Option { self.get_impl_data(id).coerce_unsized_info } @@ -1609,6 +1621,41 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.def_path_hash_unlocked(index, &mut def_path_hashes) } + fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId { + debug_assert_eq!(ExpnId::from_hash(hash), None); + let index_guess = ExpnIndex::from_u32(index_guess); + let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self)); + + let index = if old_hash == Some(hash) { + // Fast path: the expn and its index is unchanged from the + // previous compilation session. There is no need to decode anything + // else. + index_guess + } else { + // Slow path: We need to find out the new `DefIndex` of the provided + // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash` + // stored in this crate. + let map = self.cdata.expn_hash_map.get_or_init(|| { + let end_id = self.root.expn_hashes.size() as u32; + let mut map = + UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default()); + for i in 0..end_id { + let i = ExpnIndex::from_u32(i); + if let Some(hash) = self.root.expn_hashes.get(self, i) { + map.insert(hash.decode(self), i); + } else { + panic!("Missing expn_hash entry for {:?}", i); + } + } + map + }); + map[&hash] + }; + + let data = self.root.expn_data.get(self, index).unwrap().decode(self); + rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash) + } + /// Imports the source_map from an external crate into the source_map of the crate /// currently being compiled (the "local crate"). /// @@ -1847,6 +1894,7 @@ impl CrateMetadata { raw_proc_macros, source_map_import_info: OnceCell::new(), def_path_hash_map: Default::default(), + expn_hash_map: Default::default(), alloc_decoding_state, cnum, cnum_map, @@ -1927,8 +1975,8 @@ impl CrateMetadata { self.root.name } - crate fn disambiguator(&self) -> CrateDisambiguator { - self.root.disambiguator + crate fn stable_crate_id(&self) -> StableCrateId { + self.root.stable_crate_id } crate fn hash(&self) -> Svh { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9a97835d9c..41839c5802 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -4,9 +4,7 @@ use crate::native_libs; use crate::rmeta::encoder; use rustc_ast as ast; -use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::stable_map::FxHashMap; -use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -19,12 +17,12 @@ use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::utils::NativeLibKind; -use rustc_session::{CrateDisambiguator, Session}; +use rustc_session::{Session, StableCrateId}; +use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::Symbol; use rustc_data_structures::sync::Lrc; -use rustc_span::ExpnId; use smallvec::SmallVec; use std::any::Any; @@ -169,6 +167,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, is_no_builtins => { cdata.root.no_builtins } symbol_mangling_version => { cdata.root.symbol_mangling_version } impl_defaultness => { cdata.get_impl_defaultness(def_id.index) } + impl_constness => { cdata.get_impl_constness(def_id.index) } reachable_non_generics => { let reachable_non_generics = tcx .exported_symbols(cdata.cnum) @@ -186,7 +185,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } foreign_modules => { cdata.get_foreign_modules(tcx) } - crate_disambiguator => { cdata.root.disambiguator } crate_hash => { cdata.root.hash } crate_host_hash => { cdata.host_hash } crate_name => { cdata.root.name } @@ -242,6 +240,7 @@ pub fn provide(providers: &mut Providers) { // therefore no actual inputs, they're just reading tables calculated in // 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, @@ -312,7 +311,7 @@ pub fn provide(providers: &mut Providers) { // which is to say, its not deterministic in general. But // we believe that libstd is consistently assigned crate // num 1, so it should be enough to resolve #46112. - let mut crates: Vec = (*tcx.crates()).to_owned(); + let mut crates: Vec = (*tcx.crates(())).to_owned(); crates.sort(); for &cnum in crates.iter() { @@ -369,6 +368,7 @@ pub fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, + crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()), ..*providers }; @@ -412,7 +412,7 @@ impl CStore { let data = self.get_crate_data(id.krate); if data.root.is_proc_macro_crate() { - return LoadedMacro::ProcMacro(data.load_proc_macro(id, sess)); + return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess)); } let span = data.get_span(id.index, sess); @@ -451,6 +451,16 @@ impl CStore { self.get_crate_data(def_id.krate).get_span(def_id.index, sess) } + pub fn def_kind(&self, def: DefId) -> DefKind { + self.get_crate_data(def.krate).def_kind(def.index) + } + + pub fn crates_untracked(&self) -> Vec { + let mut result = vec![]; + self.iter_crate_data(|cnum, _| result.push(cnum)); + result + } + pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes } @@ -485,16 +495,12 @@ impl CrateStore for CStore { self } - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { + fn crate_name(&self, cnum: CrateNum) -> Symbol { self.get_crate_data(cnum).root.name } - fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator { - self.get_crate_data(cnum).root.disambiguator - } - - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { - self.get_crate_data(cnum).root.hash + fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId { + self.get_crate_data(cnum).root.stable_crate_id } /// Returns the `DefKey` for a given `DefId`. This indicates the @@ -504,10 +510,6 @@ impl CrateStore for CStore { self.get_crate_data(def.krate).def_key(def.index) } - fn def_kind(&self, def: DefId) -> DefKind { - self.get_crate_data(def.krate).def_kind(def.index) - } - fn def_path(&self, def: DefId) -> DefPath { self.get_crate_data(def.krate).def_path(def.index) } @@ -526,17 +528,11 @@ impl CrateStore for CStore { self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash) } - fn crates_untracked(&self) -> Vec { - let mut result = vec![]; - self.iter_crate_data(|cnum, _| result.push(cnum)); - result + fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId { + self.get_crate_data(cnum).expn_hash_to_expn_id(index_guess, hash) } fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata { encoder::encode_metadata(tcx) } - - fn allocator_kind(&self) -> Option { - self.allocator_kind() - } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7600739800..a4913a32e8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -31,7 +31,7 @@ use rustc_session::config::CrateType; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext}; use rustc_span::{ - hygiene::{ExpnDataEncodeMode, HygieneEncodeContext, MacroKind}, + hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind}, RealFileName, }; use rustc_target::abi::VariantIdx; @@ -168,6 +168,12 @@ impl<'a, 'tcx> Encodable> for DefIndex { } } +impl<'a, 'tcx> Encodable> for ExpnIndex { + fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { + s.emit_u32(self.as_u32()) + } +} + impl<'a, 'tcx> Encodable> for SyntaxContext { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s) @@ -176,12 +182,15 @@ impl<'a, 'tcx> Encodable> for SyntaxContext { impl<'a, 'tcx> Encodable> for ExpnId { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { - rustc_span::hygiene::raw_encode_expn_id( - *self, - &s.hygiene_ctxt, - ExpnDataEncodeMode::Metadata, - s, - ) + if self.krate == LOCAL_CRATE { + // We will only write details for local expansions. Non-local expansions will fetch + // data from the corresponding crate's metadata. + // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external + // metadata from proc-macro crates. + s.hygiene_ctxt.schedule_expn_data_for_encoding(*self); + } + self.krate.encode(s)?; + self.local_id.encode(s) } } @@ -445,7 +454,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_table(&mut self) { - let table = self.tcx.hir().definitions().def_path_table(); + let table = self.tcx.resolutions(()).definitions.def_path_table(); if self.is_proc_macro { for def_index in std::iter::once(CRATE_DEF_INDEX) .chain(self.tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index)) @@ -653,7 +662,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // 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) = self.encode_hygiene(); + let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene(); let hygiene_bytes = self.position() - i; // Encode source_map. This needs to be done last, @@ -671,7 +680,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), hash: tcx.crate_hash(LOCAL_CRATE), - disambiguator: tcx.sess.local_crate_disambiguator(), stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), panic_strategy: tcx.sess.panic_strategy(), edition: tcx.sess.edition(), @@ -702,6 +710,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { tables, syntax_contexts, expn_data, + expn_hashes, }); let total_bytes = self.position(); @@ -1061,10 +1070,7 @@ impl EncodeContext<'a, 'tcx> { Lazy::empty() }; - let data = ModData { - reexports, - expansion: tcx.hir().definitions().expansion_that_defined(local_def_id), - }; + let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) }; record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data))); if self.is_proc_macro { @@ -1223,7 +1229,12 @@ impl EncodeContext<'a, 'tcx> { let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind { FnData { asyncness: sig.header.asyncness, - constness: sig.header.constness, + // Can be inside `impl const Trait`, so using sig.header.constness is not reliable + constness: if self.tcx.is_const_fn_raw(def_id) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }, param_names: self.encode_fn_param_names_for_body(body), } } else { @@ -1408,7 +1419,7 @@ impl EncodeContext<'a, 'tcx> { adt_def.repr, ) } - hir::ItemKind::Impl(hir::Impl { defaultness, .. }) => { + hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { let trait_ref = self.tcx.impl_trait_ref(def_id); let polarity = self.tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { @@ -1433,8 +1444,13 @@ impl EncodeContext<'a, 'tcx> { } }); - let data = - ImplData { polarity, defaultness, parent_impl: parent, coerce_unsized_info }; + let data = ImplData { + polarity, + defaultness, + constness, + parent_impl: parent, + coerce_unsized_info, + }; EntryKind::Impl(self.lazy(data)) } @@ -1565,7 +1581,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> { empty_proc_macro!(self); let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); - self.lazy(used_libraries.iter().cloned()) + self.lazy(used_libraries.iter()) } fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> { @@ -1574,23 +1590,31 @@ impl EncodeContext<'a, 'tcx> { self.lazy(foreign_modules.iter().map(|(_, m)| m).cloned()) } - fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable) { + fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) { let mut syntax_contexts: TableBuilder<_, _> = Default::default(); let mut expn_data_table: TableBuilder<_, _> = Default::default(); + let mut expn_hash_table: TableBuilder<_, _> = Default::default(); let _: Result<(), !> = self.hygiene_ctxt.encode( - &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table), - |(this, syntax_contexts, _), index, ctxt_data| { + &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table), + |(this, syntax_contexts, _, _), index, ctxt_data| { syntax_contexts.set(index, this.lazy(ctxt_data)); Ok(()) }, - |(this, _, expn_data_table), index, expn_data| { - expn_data_table.set(index, this.lazy(expn_data)); + |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| { + if let Some(index) = index.as_local() { + expn_data_table.set(index.as_raw(), this.lazy(expn_data)); + expn_hash_table.set(index.as_raw(), this.lazy(hash)); + } Ok(()) }, ); - (syntax_contexts.encode(&mut self.opaque), expn_data_table.encode(&mut self.opaque)) + ( + syntax_contexts.encode(&mut self.opaque), + expn_data_table.encode(&mut self.opaque), + expn_hash_table.encode(&mut self.opaque), + ) } fn encode_proc_macros(&mut self) -> Option { @@ -1668,7 +1692,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { empty_proc_macro!(self); - let crates = self.tcx.crates(); + let crates = self.tcx.crates(()); let mut deps = crates .iter() @@ -1755,7 +1779,7 @@ impl EncodeContext<'a, 'tcx> { .map(|(trait_def_id, mut impls)| { // Bring everything into deterministic order for hashing impls.sort_by_cached_key(|&(index, _)| { - tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index }) + tcx.hir().def_path_hash(LocalDefId { local_def_index: index }) }); TraitImpls { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 99ea0cc8f2..a487753f46 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -18,11 +18,10 @@ use rustc_middle::mir; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; -use rustc_session::CrateDisambiguator; use rustc_span::edition::Edition; -use rustc_span::hygiene::MacroKind; +use rustc_span::hygiene::{ExpnIndex, MacroKind}; use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::{self, ExpnData, ExpnId, Span}; +use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use std::marker::PhantomData; @@ -171,7 +170,8 @@ macro_rules! Lazy { } type SyntaxContextTable = Lazy>>; -type ExpnDataTable = Lazy>>; +type ExpnDataTable = Lazy>>; +type ExpnHashTable = Lazy>>; #[derive(MetadataEncodable, MetadataDecodable)] crate struct ProcMacroData { @@ -202,7 +202,6 @@ crate struct CrateRoot<'tcx> { triple: TargetTriple, extra_filename: String, hash: Svh, - disambiguator: CrateDisambiguator, stable_crate_id: StableCrateId, panic_strategy: PanicStrategy, edition: Edition, @@ -228,6 +227,7 @@ crate struct CrateRoot<'tcx> { syntax_contexts: SyntaxContextTable, expn_data: ExpnDataTable, + expn_hashes: ExpnHashTable, source_map: Lazy<[rustc_span::SourceFile]>, @@ -392,6 +392,7 @@ struct TraitData { #[derive(TyEncodable, TyDecodable)] struct ImplData { polarity: ty::ImplPolarity, + constness: hir::Constness, defaultness: hir::Defaultness, parent_impl: Option, diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 8cb30e72f7..90ad0256ae 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -28,6 +28,5 @@ rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } chalk-ir = "0.55.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } -measureme = "9.1.0" rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 20bbf9097f..392372fad5 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,7 +1,6 @@ use self::collector::NodeCollector; use crate::hir::{AttributeMap, IndexedHir}; -use crate::middle::cstore::CrateStore; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; @@ -9,15 +8,16 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::definitions::{DefKey, DefPath, Definitions}; +use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::*; use rustc_index::vec::Idx; +use rustc_span::def_id::StableCrateId; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; @@ -29,7 +29,10 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. }) | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl), - Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) => Some(fn_decl), + Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. }) + | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => { + Some(fn_decl) + } _ => None, } } @@ -153,13 +156,9 @@ impl<'hir> Map<'hir> { self.tcx.hir_crate(()) } - #[inline] - pub fn definitions(&self) -> &'hir Definitions { - &self.tcx.definitions - } - pub fn def_key(&self, def_id: LocalDefId) -> DefKey { - self.tcx.definitions.def_key(def_id) + // Accessing the DefKey is ok, since it is part of DefPathHash. + self.tcx.untracked_resolutions.definitions.def_key(def_id) } pub fn def_path_from_hir_id(&self, id: HirId) -> Option { @@ -167,7 +166,14 @@ impl<'hir> Map<'hir> { } pub fn def_path(&self, def_id: LocalDefId) -> DefPath { - self.tcx.definitions.def_path(def_id) + // Accessing the DefPath is ok, since it is part of DefPathHash. + self.tcx.untracked_resolutions.definitions.def_path(def_id) + } + + #[inline] + pub fn def_path_hash(self, def_id: LocalDefId) -> DefPathHash { + // Accessing the DefPathHash is ok, it is incr. comp. stable. + self.tcx.untracked_resolutions.definitions.def_path_hash(def_id) } #[inline] @@ -183,16 +189,21 @@ impl<'hir> Map<'hir> { #[inline] pub fn opt_local_def_id(&self, hir_id: HirId) -> Option { - self.tcx.definitions.opt_hir_id_to_local_def_id(hir_id) + // FIXME(#85914) is this access safe for incr. comp.? + self.tcx.untracked_resolutions.definitions.opt_hir_id_to_local_def_id(hir_id) } #[inline] pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { - self.tcx.definitions.local_def_id_to_hir_id(def_id) + // FIXME(#85914) is this access safe for incr. comp.? + self.tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id) } pub fn iter_local_def_id(&self) -> impl Iterator + '_ { - self.tcx.definitions.iter_local_def_id() + // Create a dependency to the crate to be sure we reexcute this when the amount of + // definitions change. + self.tcx.ensure().hir_crate(()); + self.tcx.untracked_resolutions.definitions.iter_local_def_id() } pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option { @@ -456,6 +467,9 @@ impl<'hir> Map<'hir> { /// Returns the `ConstContext` of the body associated with this `LocalDefId`. /// /// Panics if `LocalDefId` does not have an associated body. + /// + /// This should only be used for determining the context of a body, a return + /// value of `Some` does not always suggest that the owner of the body is `const`. pub fn body_const_context(&self, did: LocalDefId) -> Option { let hir_id = self.local_def_id_to_hir_id(did); let ccx = match self.body_owner_kind(hir_id) { @@ -464,6 +478,11 @@ impl<'hir> Map<'hir> { BodyOwnerKind::Fn if self.tcx.is_constructor(did.to_def_id()) => return None, BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(did.to_def_id()) => ConstContext::ConstFn, + BodyOwnerKind::Fn + if self.tcx.has_attr(did.to_def_id(), sym::default_method_body_is_const) => + { + ConstContext::ConstFn + } BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None, }; @@ -931,9 +950,15 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tcx> { let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map"); + // We can access untracked state since we are an eval_always query. let hcx = tcx.create_stable_hashing_context(); - let mut collector = - NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx); + let mut collector = NodeCollector::root( + tcx.sess, + &**tcx.arena, + tcx.untracked_crate, + &tcx.untracked_resolutions.definitions, + hcx, + ); intravisit::walk_crate(&mut collector, tcx.untracked_crate); let map = collector.finalize_and_compute_crate_hash(); @@ -943,6 +968,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tc pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { assert_eq!(crate_num, LOCAL_CRATE); + // We can access untracked state since we are an eval_always query. let mut hcx = tcx.create_stable_hashing_context(); let mut hir_body_nodes: Vec<_> = tcx @@ -950,7 +976,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { .map .iter_enumerated() .filter_map(|(def_id, hod)| { - let def_path_hash = tcx.definitions.def_path_hash(def_id); + let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id); let mut hasher = StableHasher::new(); hod.as_ref()?.hash_stable(&mut hcx, &mut hasher); AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id } @@ -967,7 +993,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { }, ); - let upstream_crates = upstream_crates(&*tcx.cstore); + let upstream_crates = upstream_crates(tcx); // We hash the final, remapped names of all local source files so we // don't have to include the path prefix remapping commandline args. @@ -990,25 +1016,24 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); source_file_names.hash_stable(&mut hcx, &mut stable_hasher); tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); - tcx.sess.local_crate_disambiguator().to_fingerprint().hash_stable(&mut hcx, &mut stable_hasher); + tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher); let crate_hash: Fingerprint = stable_hasher.finish(); Svh::new(crate_hash.to_smaller_hash()) } -fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { - let mut upstream_crates: Vec<_> = cstore - .crates_untracked() +fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { + let mut upstream_crates: Vec<_> = tcx + .crates(()) .iter() .map(|&cnum| { - let name = cstore.crate_name_untracked(cnum); - let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); - let hash = cstore.crate_hash_untracked(cnum); - (name, disambiguator, hash) + let stable_crate_id = tcx.resolutions(()).cstore.stable_crate_id(cnum); + let hash = tcx.crate_hash(cnum); + (stable_crate_id, hash) }) .collect(); - upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis)); + upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id); upstream_crates } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 087f772c81..3026bf8274 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -169,6 +169,6 @@ pub fn provide(providers: &mut Providers) { providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls; providers.expn_that_defined = |tcx, id| { let id = id.expect_local(); - tcx.definitions.expansion_that_defined(id) + tcx.resolutions(()).definitions.expansion_that_defined(id) }; } diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs index b2fef731b7..32ccdafaeb 100644 --- a/compiler/rustc_middle/src/ich/hcx.rs +++ b/compiler/rustc_middle/src/ich/hcx.rs @@ -14,10 +14,8 @@ use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData}; -use rustc_span::def_id::{CrateNum, CRATE_DEF_INDEX}; use smallvec::SmallVec; use std::cmp::Ord; -use std::thread::LocalKey; fn compute_ignored_attr_names() -> FxHashSet { debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); @@ -227,22 +225,8 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { } #[inline] - fn hash_crate_num(&mut self, cnum: CrateNum, hasher: &mut StableHasher) { - let hcx = self; - hcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher); - } - - #[inline] - fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) { - let hcx = self; - hcx.def_path_hash(def_id).hash_stable(hcx, hasher); - } - - fn expn_id_cache() -> &'static LocalKey { - thread_local! { - static CACHE: rustc_span::ExpnIdCache = Default::default(); - } - &CACHE + fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + self.def_path_hash(def_id) } fn span_data_to_lines_and_cols( @@ -253,6 +237,8 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { } } +impl rustc_session::HashStableContext for StableHashingContext<'a> {} + pub fn hash_stable_trait_impls<'a>( hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher, diff --git a/compiler/rustc_middle/src/ich/impls_hir.rs b/compiler/rustc_middle/src/ich/impls_hir.rs index abf5683232..5dfd00bc6d 100644 --- a/compiler/rustc_middle/src/ich/impls_hir.rs +++ b/compiler/rustc_middle/src/ich/impls_hir.rs @@ -6,7 +6,6 @@ use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::definitions::DefPathHash; use smallvec::SmallVec; use std::mem; @@ -113,46 +112,6 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { self.node_id_hashing_mode = prev_hash_node_ids; } - - #[inline] - fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { - self.local_def_path_hash(def_id) - } -} - -impl<'a> ToStableHashKey> for DefId { - type KeyType = DefPathHash; - - #[inline] - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { - hcx.def_path_hash(*self) - } -} - -impl<'a> HashStable> for LocalDefId { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher); - } -} - -impl<'a> ToStableHashKey> for LocalDefId { - type KeyType = DefPathHash; - - #[inline] - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { - hcx.def_path_hash(self.to_def_id()) - } -} - -impl<'a> ToStableHashKey> for CrateNum { - type KeyType = DefPathHash; - - #[inline] - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { - let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX }; - def_id.to_stable_hash_key(hcx) - } } impl<'a> ToStableHashKey> for hir::ItemLocalId { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e1d7bc4be5..f2acc601d4 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -42,13 +42,14 @@ #![feature(crate_visibility_modifier)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] -#![feature(int_error_matching)] #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] #![feature(iter_zip)] #![feature(thread_local_const_init)] +#![feature(try_reserve)] +#![feature(nonzero_ops)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 4c7ea937ce..6ad6887723 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -1,13 +1,14 @@ use std::cmp; use crate::ich::StableHashingContext; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; +use rustc_index::vec::IndexVec; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, - Level, Lint, LintId, + FutureIncompatibilityReason, Level, Lint, LintId, }; use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::hygiene::MacroKind; @@ -28,9 +29,6 @@ pub enum LintLevelSource { /// The provided `Level` is the level specified on the command line. /// (The actual level may be lower due to `--cap-lints`.) CommandLine(Symbol, Level), - - /// Lint is being forced to warn no matter what. - ForceWarn(Symbol), } impl LintLevelSource { @@ -39,7 +37,6 @@ impl LintLevelSource { LintLevelSource::Default => symbol::kw::Default, LintLevelSource::Node(name, _, _) => name, LintLevelSource::CommandLine(name, _) => name, - LintLevelSource::ForceWarn(name) => name, } } @@ -48,7 +45,6 @@ impl LintLevelSource { LintLevelSource::Default => DUMMY_SP, LintLevelSource::Node(_, span, _) => span, LintLevelSource::CommandLine(_, _) => DUMMY_SP, - LintLevelSource::ForceWarn(_) => DUMMY_SP, } } } @@ -56,48 +52,40 @@ impl LintLevelSource { /// A tuple of a lint level and its source. pub type LevelAndSource = (Level, LintLevelSource); -#[derive(Debug)] +#[derive(Debug, HashStable)] pub struct LintLevelSets { - pub list: Vec, + pub list: IndexVec, pub lint_cap: Level, - pub force_warns: FxHashSet, } -#[derive(Debug)] -pub enum LintSet { - CommandLine { - // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which - // flag. - specs: FxHashMap, - }, - - Node { - specs: FxHashMap, - parent: u32, - }, +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, + + pub parent: LintStackIndex, } impl LintLevelSets { pub fn new() -> Self { - LintLevelSets { - list: Vec::new(), - lint_cap: Level::Forbid, - force_warns: FxHashSet::default(), - } + LintLevelSets { list: IndexVec::new(), lint_cap: Level::Forbid } } pub fn get_lint_level( &self, lint: &'static Lint, - idx: u32, + idx: LintStackIndex, aux: Option<&FxHashMap>, sess: &Session, ) -> LevelAndSource { - // Check whether we should always warn - if self.force_warns.contains(&LintId::of(lint)) { - return (Level::Warn, LintLevelSource::ForceWarn(Symbol::intern(lint.name))); - } - 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 @@ -123,8 +111,13 @@ impl LintLevelSets { } } - // Ensure that we never exceed the `--cap-lints` argument. - level = cmp::min(level, self.lint_cap); + // 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. @@ -137,7 +130,7 @@ impl LintLevelSets { pub fn get_lint_id_level( &self, id: LintId, - mut idx: u32, + mut idx: LintStackIndex, aux: Option<&FxHashMap>, ) -> (Option, LintLevelSource) { if let Some(specs) = aux { @@ -146,20 +139,14 @@ impl LintLevelSets { } } loop { - match self.list[idx as usize] { - LintSet::CommandLine { ref specs } => { - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - return (None, LintLevelSource::Default); - } - LintSet::Node { ref specs, parent } => { - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - idx = parent; - } + 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; } } } @@ -167,7 +154,7 @@ impl LintLevelSets { #[derive(Debug)] pub struct LintLevelMap { pub sets: LintLevelSets, - pub id_to_set: FxHashMap, + pub id_to_set: FxHashMap, } impl LintLevelMap { @@ -191,33 +178,11 @@ impl LintLevelMap { impl<'a> HashStable> for LintLevelMap { #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let LintLevelMap { ref sets, ref id_to_set, .. } = *self; + let LintLevelMap { ref sets, ref id_to_set } = *self; id_to_set.hash_stable(hcx, hasher); - let LintLevelSets { ref list, lint_cap, .. } = *sets; - - lint_cap.hash_stable(hcx, hasher); - - hcx.while_hashing_spans(true, |hcx| { - list.len().hash_stable(hcx, hasher); - - // We are working under the assumption here that the list of - // lint-sets is built in a deterministic order. - for lint_set in list { - ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher); - - match *lint_set { - LintSet::CommandLine { ref specs } => { - specs.hash_stable(hcx, hasher); - } - LintSet::Node { ref specs, parent } => { - specs.hash_stable(hcx, hasher); - parent.hash_stable(hcx, hasher); - } - } - } - }) + hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher)) } } @@ -258,8 +223,13 @@ pub fn struct_lint_level<'s, 'd>( let lint_id = LintId::of(lint); let future_incompatible = lint.future_incompatible; - let has_future_breakage = - future_incompatible.map_or(false, |incompat| incompat.future_breakage.is_some()); + let has_future_breakage = future_incompatible.map_or( + // Default allow lints trigger too often for testing. + sess.opts.debugging_opts.future_incompat_test && lint.default_level != Level::Allow, + |incompat| { + matches!(incompat.reason, FutureIncompatibilityReason::FutureReleaseErrorReportNow) + }, + ); let mut err = match (level, span) { (Level::Allow, span) => { @@ -275,6 +245,8 @@ pub fn struct_lint_level<'s, 'd>( } (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""), (Level::Warn, None) => sess.struct_warn(""), + (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""), + (Level::ForceWarn, None) => sess.struct_force_warn(""), (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""), (Level::Deny | Level::Forbid, None) => sess.struct_err(""), }; @@ -292,7 +264,7 @@ pub fn struct_lint_level<'s, 'd>( // if this lint occurs in the expansion of a macro from an external crate, // allow individual lints to opt-out from being reported. let not_future_incompatible = - future_incompatible.map(|f| f.edition.is_some()).unwrap_or(true); + future_incompatible.map(|f| f.reason.edition().is_some()).unwrap_or(true); if not_future_incompatible && !lint.report_in_external_macro { err.cancel(); // Don't continue further, since we don't want to have @@ -316,6 +288,7 @@ pub fn struct_lint_level<'s, 'd>( Level::Deny => "-D", Level::Forbid => "-F", Level::Allow => "-A", + Level::ForceWarn => "--force-warn", }; let hyphen_case_lint_name = name.replace("_", "-"); if lint_flag_val.as_str() == name { @@ -361,21 +334,12 @@ pub fn struct_lint_level<'s, 'd>( ); } } - LintLevelSource::ForceWarn(_) => { - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - "warning forced by `force-warns` commandline option", - ); - } } - err.code(DiagnosticId::Lint { name, has_future_breakage }); + let is_force_warn = matches!(level, Level::ForceWarn); + err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn }); if let Some(future_incompatible) = future_incompatible { - const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ - it will become a hard error"; - let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { "once this associated item is added to the standard library, the ambiguity may \ cause an error or change in behavior!" @@ -384,14 +348,31 @@ pub fn struct_lint_level<'s, 'd>( "this borrowing pattern was not meant to be accepted, and may become a hard error \ in the future" .to_owned() - } else if let Some(edition) = future_incompatible.edition { - format!("{} in the {} edition!", STANDARD_MESSAGE, edition) + } else if let FutureIncompatibilityReason::EditionError(edition) = + future_incompatible.reason + { + let current_edition = sess.edition(); + format!( + "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!", + current_edition, edition + ) + } else if let FutureIncompatibilityReason::EditionSemanticsChange(edition) = + future_incompatible.reason + { + format!("this changes meaning in Rust {}", edition) } else { - format!("{} in a future release!", STANDARD_MESSAGE) + "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error in a future release!" + .to_owned() }; - let citation = format!("for more information, see {}", future_incompatible.reference); - err.warn(&explanation); - err.note(&citation); + if future_incompatible.explain_reason { + err.warn(&explanation); + } + if !future_incompatible.reference.is_empty() { + let citation = + format!("for more information, see {}", future_incompatible.reference); + err.note(&citation); + } } // Finally, run `decorate`. This function is also responsible for emitting the diagnostic. @@ -411,7 +392,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { false } ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" - ExpnKind::Macro { kind: MacroKind::Bang, name: _, proc_macro: _ } => { + ExpnKind::Macro(MacroKind::Bang, _) => { // Dummy span for the `def_site` means it's an external macro. expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site) } diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index fc3dafe99e..93e7aeaffc 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -38,6 +38,9 @@ pub struct CodegenFnAttrs { /// be generated against a specific instruction set. Only usable on architectures which allow /// switching between multiple instruction sets. pub instruction_set: Option, + /// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be + /// aligned to. + pub alignment: Option, } bitflags! { @@ -107,6 +110,7 @@ impl CodegenFnAttrs { link_section: None, no_sanitize: SanitizerSet::empty(), instruction_set: None, + alignment: None, } } diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index a7ab43d106..8150e67929 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -5,16 +5,13 @@ use crate::ty::TyCtxt; use rustc_ast as ast; -use rustc_ast::expand::allocator::AllocatorKind; -use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, MetadataRef}; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_macros::HashStable; use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; -use rustc_session::CrateDisambiguator; +use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::Target; @@ -61,33 +58,13 @@ impl CrateDepKind { } } -#[derive(PartialEq, Clone, Debug, Encodable, Decodable)] -pub enum LibSource { - Some(PathBuf), - MetadataOnly, - None, -} - -impl LibSource { - pub fn is_some(&self) -> bool { - matches!(self, LibSource::Some(_)) - } - - pub fn option(&self) -> Option { - match *self { - LibSource::Some(ref p) => Some(p.clone()), - LibSource::MetadataOnly | LibSource::None => None, - } - } -} - #[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)] pub enum LinkagePreference { RequireDynamic, RequireStatic, } -#[derive(Clone, Debug, Encodable, Decodable, HashStable)] +#[derive(Debug, Encodable, Decodable, HashStable)] pub struct NativeLib { pub kind: NativeLibKind, pub name: Option, @@ -102,6 +79,25 @@ pub struct NativeLib { pub struct DllImport { pub name: Symbol, pub ordinal: Option, + /// Calling convention for the function. + /// + /// On x86_64, this is always `DllCallingConvention::C`; on i686, it can be any + /// of the values, and we use `DllCallingConvention::C` to represent `"cdecl"`. + pub calling_convention: DllCallingConvention, + /// Span of import's "extern" declaration; used for diagnostics. + pub span: Span, +} + +/// Calling convention for a function defined in an external library. +/// +/// The usize value, where present, indicates the size of the function's argument list +/// in bytes. +#[derive(Clone, PartialEq, Debug, Encodable, Decodable, HashStable)] +pub enum DllCallingConvention { + C, + Stdcall(usize), + Fastcall(usize), + Vectorcall(usize), } #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)] @@ -189,75 +185,32 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; /// that it's *not* tracked for dependency information throughout compilation /// (it'd break incremental compilation) and should only be called pre-HIR (e.g. /// during resolve) -pub trait CrateStore { +pub trait CrateStore: std::fmt::Debug { fn as_any(&self) -> &dyn Any; - // resolve + // Foreign definitions. + // This information is safe to access, since it's hashed as part of the DefPathHash, which incr. + // comp. uses to identify a DefId. fn def_key(&self, def: DefId) -> DefKey; - fn def_kind(&self, def: DefId) -> DefKind; fn def_path(&self, def: DefId) -> DefPath; fn def_path_hash(&self, def: DefId) -> DefPathHash; + + // This information is safe to access, since it's hashed as part of the StableCrateId, which + // incr. comp. uses to identify a CrateNum. + fn crate_name(&self, cnum: CrateNum) -> Symbol; + fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId; + + /// Fetch a DefId from a DefPathHash for a foreign crate. fn def_path_hash_to_def_id( &self, cnum: CrateNum, index_guess: u32, hash: DefPathHash, ) -> Option; - - // "queries" used in resolve that aren't tracked for incremental compilation - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; - fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; - - // This is basically a 1-based range of ints, which is a little - // silly - I may fix that. - fn crates_untracked(&self) -> Vec; + fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId; // utility functions fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata; - fn allocator_kind(&self) -> Option; } pub type CrateStoreDyn = dyn CrateStore + sync::Sync; - -// This method is used when generating the command line to pass through to -// system linker. The linker expects undefined symbols on the left of the -// command line to be defined in libraries on the right, not the other way -// around. For more info, see some comments in the add_used_library function -// below. -// -// In order to get this left-to-right dependency ordering, we perform a -// topological sort of all crates putting the leaves at the right-most -// positions. -pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { - let mut libs = tcx - .crates() - .iter() - .cloned() - .filter_map(|cnum| { - if tcx.dep_kind(cnum).macros_only() { - return None; - } - let source = tcx.used_crate_source(cnum); - let path = match prefer { - LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0), - LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0), - }; - let path = match path { - Some(p) => LibSource::Some(p), - None => { - if source.rmeta.is_some() { - LibSource::MetadataOnly - } else { - LibSource::None - } - } - }; - Some((cnum, path)) - }) - .collect::>(); - let mut ordering = tcx.postorder_cnums(()).to_owned(); - ordering.reverse(); - libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a)); - libs -} diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 288dd03944..5ea78e087f 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -48,8 +48,8 @@ impl<'tcx> ExportedSymbol<'tcx> { pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String { format!( - "rust_metadata_{}_{}", + "rust_metadata_{}_{:08x}", tcx.crate_name(LOCAL_CRATE), - tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex() + tcx.sess.local_stable_crate_id().to_u64(), ) } diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index 601198fd0d..c4bfd0ebb2 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -10,38 +10,46 @@ //! just peeks and looks for that attribute. use crate::bug; -use rustc_ast as ast; -use rustc_data_structures::sync::OnceCell; +use crate::ty; +use rustc_ast::Attribute; use rustc_session::Session; +use rustc_session::{Limit, Limits}; use rustc_span::symbol::{sym, Symbol}; use std::num::IntErrorKind; -pub fn update_limits(sess: &Session, krate: &ast::Crate) { - update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); - update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0); - update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); - update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000); +pub fn provide(providers: &mut ty::query::Providers) { + providers.limits = |tcx, ()| Limits { + recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess), + move_size_limit: get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0), + type_length_limit: get_limit( + tcx.hir().krate_attrs(), + tcx.sess, + sym::type_length_limit, + 1048576, + ), + const_eval_limit: get_limit( + tcx.hir().krate_attrs(), + tcx.sess, + sym::const_eval_limit, + 1_000_000, + ), + } +} + +pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit { + get_limit(krate_attrs, sess, sym::recursion_limit, 128) } -fn update_limit( - sess: &Session, - krate: &ast::Crate, - limit: &OnceCell + std::fmt::Debug>, - name: Symbol, - default: usize, -) { - for attr in &krate.attrs { +fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit { + for attr in krate_attrs { if !sess.check_name(attr, name) { continue; } if let Some(s) = attr.value_str() { match s.as_str().parse() { - Ok(n) => { - limit.set(From::from(n)).unwrap(); - return; - } + Ok(n) => return Limit::new(n), Err(e) => { let mut err = sess.struct_span_err(attr.span, "`limit` must be a non-negative integer"); @@ -68,5 +76,5 @@ fn update_limit( } } } - limit.set(From::from(default)).unwrap(); + return Limit::new(default); } diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index a369e85306..b370ec152e 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -32,3 +32,7 @@ pub mod privacy; pub mod region; pub mod resolve_lifetime; pub mod stability; + +pub fn provide(providers: &mut crate::ty::query::Providers) { + limits::provide(providers); +} diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index aa0f18846d..2804fe5806 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -226,18 +226,19 @@ fn late_report_deprecation( suggestion: Option, lint: &'static Lint, span: Span, + method_span: Option, hir_id: HirId, def_id: DefId, ) { if span.in_derive_expansion() { return; } - - tcx.struct_span_lint_hir(lint, hir_id, span, |lint| { + 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); 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, span); + deprecation_suggestion(&mut diag, kind, suggestion, method_span); } diag.emit() }); @@ -306,13 +307,13 @@ impl<'tcx> TyCtxt<'tcx> { let path = &with_no_trimmed_paths(|| self.def_path_str(def_id)); let kind = self.def_kind(def_id).descr(def_id); let (message, lint) = deprecation_message(&depr_entry.attr, kind, path); - let span = method_span.unwrap_or(span); late_report_deprecation( self, &message, depr_entry.attr.suggestion, lint, span, + method_span, id, def_id, ); diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs index 776a777b1b..1ef1024114 100644 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ b/compiler/rustc_middle/src/mir/abstract_const.rs @@ -1,6 +1,6 @@ //! A subset of a mir body used for const evaluatability checking. -use crate::mir; -use crate::ty; +use crate::mir::{self, CastKind}; +use crate::ty::{self, Ty}; rustc_index::newtype_index! { /// An index into an `AbstractConst`. @@ -17,6 +17,7 @@ pub enum Node<'tcx> { Binop(mir::BinOp, NodeId, NodeId), UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), + Cast(CastKind, NodeId, Ty<'tcx>), } #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index ee3902991e..bbf792edcd 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -3,17 +3,20 @@ use std::borrow::Cow; use std::convert::TryFrom; use std::iter; -use std::ops::{Deref, DerefMut, Range}; +use std::ops::{Deref, Range}; use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::sorted_map::SortedMap; +use rustc_span::DUMMY_SP; use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ - read_target_uint, write_target_uint, AllocId, InterpError, Pointer, Scalar, ScalarMaybeUninit, - UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo, + read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, + ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, UndefinedBehaviorInfo, UninitBytesAccess, + UnsupportedOpInfo, }; +use crate::ty; /// This type represents an Allocation in the Miri/CTFE core engine. /// @@ -22,7 +25,7 @@ use super::{ /// module provides higher-level access. #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] -pub struct Allocation { +pub struct Allocation { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. bytes: Vec, @@ -121,38 +124,62 @@ impl Allocation { Allocation::from_bytes(slice, Align::ONE, Mutability::Not) } - pub fn uninit(size: Size, align: Align) -> Self { - Allocation { - bytes: vec![0; size.bytes_usize()], + /// Try to create an Allocation of `size` bytes, failing if there is not enough memory + /// available to the compiler to do so. + pub fn uninit(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'static, Self> { + let mut bytes = Vec::new(); + bytes.try_reserve(size.bytes_usize()).map_err(|_| { + // This results in an error that can happen non-deterministically, since the memory + // available to the compiler can change between runs. Normally queries are always + // deterministic. However, we can be non-determinstic here because all uses of const + // evaluation (including ConstProp!) will make compilation fail (via hard error + // or ICE) upon encountering a `MemoryExhausted` error. + if panic_on_fail { + panic!("Allocation::uninit called with panic_on_fail had allocation failure") + } + ty::tls::with(|tcx| { + tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpreation") + }); + InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) + })?; + bytes.resize(size.bytes_usize(), 0); + Ok(Allocation { + bytes, relocations: Relocations::new(), init_mask: InitMask::new(size, false), align, mutability: Mutability::Mut, extra: (), - } + }) } } -impl Allocation<()> { - /// Add Tag and Extra fields - pub fn with_tags_and_extra( +impl Allocation { + /// Convert Tag and add Extra fields + pub fn convert_tag_add_extra( self, - mut tagger: impl FnMut(AllocId) -> T, - extra: E, - ) -> Allocation { + cx: &impl HasDataLayout, + extra: Extra, + mut tagger: impl FnMut(Pointer) -> Pointer, + ) -> Allocation { + // Compute new pointer tags, which also adjusts the bytes. + let mut bytes = self.bytes; + let mut new_relocations = Vec::with_capacity(self.relocations.0.len()); + let ptr_size = cx.data_layout().pointer_size.bytes_usize(); + let endian = cx.data_layout().endian; + for &(offset, alloc_id) in self.relocations.iter() { + let idx = offset.bytes_usize(); + let ptr_bytes = &mut bytes[idx..idx + ptr_size]; + let bits = read_target_uint(endian, ptr_bytes).unwrap(); + let (ptr_tag, ptr_offset) = + tagger(Pointer::new(alloc_id, Size::from_bytes(bits))).into_parts(); + write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap(); + new_relocations.push((offset, ptr_tag)); + } + // Create allocation. Allocation { - bytes: self.bytes, - relocations: Relocations::from_presorted( - self.relocations - .iter() - // The allocations in the relocations (pointers stored *inside* this allocation) - // all get the base pointer tag. - .map(|&(offset, ((), alloc))| { - let tag = tagger(alloc); - (offset, (tag, alloc)) - }) - .collect(), - ), + bytes, + relocations: Relocations::from_presorted(new_relocations), init_mask: self.init_mask, align: self.align, mutability: self.mutability, @@ -258,6 +285,9 @@ impl Allocation { /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory. pub fn get_bytes_mut_ptr(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> *mut [u8] { self.mark_init(range, true); + // This also clears relocations that just overlap with the written range. So writing to some + // byte can de-initialize its neighbors! See + // for details. self.clear_relocations(cx, range); assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check @@ -300,7 +330,11 @@ impl Allocation { cx: &impl HasDataLayout, range: AllocRange, ) -> AllocResult> { - // `get_bytes_unchecked` tests relocation edges. + // `get_bytes_with_uninit_and_ptr` tests relocation edges. + // We deliberately error when loading data that partially has provenance, or partially + // initialized data (that's the check below), into a scalar. The LLVM semantics of this are + // unclear so we are conservative. See for + // further discussion. let bytes = self.get_bytes_with_uninit_and_ptr(cx, range)?; // Uninit check happens *after* we established that the alignment is correct. // We must not return `Ok()` for unaligned pointers! @@ -318,9 +352,9 @@ impl Allocation { self.check_relocations(cx, range)?; } else { // Maybe a pointer. - if let Some(&(tag, alloc_id)) = self.relocations.get(&range.start) { - let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits), tag); - return Ok(ScalarMaybeUninit::Scalar(ptr.into())); + if let Some(&prov) = self.relocations.get(&range.start) { + let ptr = Pointer::new(prov, Size::from_bytes(bits)); + return Ok(ScalarMaybeUninit::from_pointer(ptr, cx)); } } // We don't. Just return the bits. @@ -340,6 +374,8 @@ impl Allocation { range: AllocRange, val: ScalarMaybeUninit, ) -> AllocResult { + assert!(self.mutability == Mutability::Mut); + let val = match val { ScalarMaybeUninit::Scalar(scalar) => scalar, ScalarMaybeUninit::Uninit => { @@ -348,9 +384,14 @@ impl Allocation { } }; - let bytes = match val.to_bits_or_ptr(range.size, cx) { - Err(val) => u128::from(val.offset.bytes()), - Ok(data) => data, + // `to_bits_or_ptr_internal` is the right method because we just want to store this data + // as-is into memory. + let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size) { + Err(val) => { + let (provenance, offset) = val.into_parts(); + (u128::from(offset.bytes()), Some(provenance)) + } + Ok(data) => (data, None), }; let endian = cx.data_layout().endian; @@ -358,8 +399,8 @@ impl Allocation { write_target_uint(endian, dst, bytes).unwrap(); // See if we have to also write a relocation. - if let Scalar::Ptr(val) = val { - self.relocations.insert(range.start, (val.tag, val.alloc_id)); + if let Some(provenance) = provenance { + self.relocations.0.insert(range.start, provenance); } Ok(()) @@ -369,11 +410,7 @@ impl Allocation { /// Relocations. impl Allocation { /// Returns all relocations overlapping with the given pointer-offset pair. - pub fn get_relocations( - &self, - cx: &impl HasDataLayout, - range: AllocRange, - ) -> &[(Size, (Tag, AllocId))] { + pub fn get_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Tag)] { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let start = range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1); @@ -423,7 +460,7 @@ impl Allocation { } // Forget all the relocations. - self.relocations.remove_range(first..last); + self.relocations.0.remove_range(first..last); } /// Errors if there are relocations overlapping with the edges of the @@ -463,6 +500,7 @@ impl Allocation { if range.size.bytes() == 0 { return; } + assert!(self.mutability == Mutability::Mut); self.init_mask.set_range(range.start, range.end(), is_init); } } @@ -488,7 +526,7 @@ impl InitMaskCompressed { /// Transferring the initialization mask to other allocations. impl Allocation { /// Creates a run-length encoding of the initialization mask. - pub fn compress_uninit_range(&self, src: Pointer, size: Size) -> InitMaskCompressed { + pub fn compress_uninit_range(&self, range: AllocRange) -> InitMaskCompressed { // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from // the source and write it to the destination. Even if we optimized the memory accesses, @@ -502,13 +540,13 @@ impl Allocation { // where each element toggles the state. let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); - let initial = self.init_mask.get(src.offset); + let initial = self.init_mask.get(range.start); let mut cur_len = 1; let mut cur = initial; - for i in 1..size.bytes() { + for i in 1..range.size.bytes() { // FIXME: optimize to bitshift the current uninitialized block's bits and read the top bit. - if self.init_mask.get(src.offset + Size::from_bytes(i)) == cur { + if self.init_mask.get(range.start + Size::from_bytes(i)) == cur { cur_len += 1; } else { ranges.push(cur_len); @@ -526,24 +564,23 @@ impl Allocation { pub fn mark_compressed_init_range( &mut self, defined: &InitMaskCompressed, - dest: Pointer, - size: Size, + range: AllocRange, repeat: u64, ) { // An optimization where we can just overwrite an entire range of initialization // bits if they are going to be uniformly `1` or `0`. if defined.ranges.len() <= 1 { self.init_mask.set_range_inbounds( - dest.offset, - dest.offset + size * repeat, // `Size` operations + range.start, + range.start + range.size * repeat, // `Size` operations defined.initial, ); return; } for mut j in 0..repeat { - j *= size.bytes(); - j += dest.offset.bytes(); + j *= range.size.bytes(); + j += range.start.bytes(); let mut cur = defined.initial; for range in &defined.ranges { let old_j = j; @@ -559,39 +596,33 @@ impl Allocation { } } -/// Relocations. +/// "Relocations" stores the provenance information of pointers stored in memory. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -pub struct Relocations(SortedMap); +pub struct Relocations(SortedMap); -impl Relocations { +impl Relocations { pub fn new() -> Self { Relocations(SortedMap::new()) } // The caller must guarantee that the given relocations are already sorted // by address and contain no duplicates. - pub fn from_presorted(r: Vec<(Size, (Tag, Id))>) -> Self { + pub fn from_presorted(r: Vec<(Size, Tag)>) -> Self { Relocations(SortedMap::from_presorted_elements(r)) } } impl Deref for Relocations { - type Target = SortedMap; + type Target = SortedMap; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for Relocations { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - /// A partial, owned list of relocations to transfer into another allocation. pub struct AllocationRelocations { - relative_relocations: Vec<(Size, (Tag, AllocId))>, + relative_relocations: Vec<(Size, Tag)>, } impl Allocation { @@ -629,7 +660,7 @@ impl Allocation { /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected /// to be clear of relocations. pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations) { - self.relocations.insert_presorted(relocations.relative_relocations); + self.relocations.0.insert_presorted(relocations.relative_relocations); } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 65d9c1dd90..94ac303b10 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -170,6 +170,8 @@ impl fmt::Display for InvalidProgramInfo<'_> { /// Details of why a pointer had to be in-bounds. #[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)] pub enum CheckInAllocMsg { + /// We are dereferencing a pointer (i.e., creating a place). + DerefTest, /// We are access memory. MemoryAccessTest, /// We are doing pointer arithmetic. @@ -179,13 +181,14 @@ pub enum CheckInAllocMsg { } impl fmt::Display for CheckInAllocMsg { - /// When this is printed as an error the context looks like this - /// "{msg}pointer must be in-bounds at offset..." + /// When this is printed as an error the context looks like this: + /// "{msg}0x01 is not a valid pointer". fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{}", match *self { + CheckInAllocMsg::DerefTest => "dereferencing pointer failed: ", CheckInAllocMsg::MemoryAccessTest => "memory access failed: ", CheckInAllocMsg::PointerArithmeticTest => "pointer arithmetic failed: ", CheckInAllocMsg::InboundsTest => "", @@ -227,16 +230,23 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Invalid metadata in a wide pointer (using `str` to avoid allocations). InvalidMeta(&'static str), /// Invalid drop function in vtable. - InvalidDropFn(FnSig<'tcx>), + InvalidVtableDropFn(FnSig<'tcx>), + /// Invalid size in a vtable: too large. + InvalidVtableSize, + /// Invalid alignment in a vtable: too large, or not a power of 2. + InvalidVtableAlignment(String), /// Reading a C string that does not end within its allocation. UnterminatedCString(Pointer), /// Dereferencing a dangling pointer after it got freed. PointerUseAfterFree(AllocId), /// Used a pointer outside the bounds it is valid for. + /// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.) PointerOutOfBounds { - ptr: Pointer, + alloc_id: AllocId, + alloc_size: Size, + ptr_offset: i64, + ptr_size: Size, msg: CheckInAllocMsg, - allocation_size: Size, }, /// Using an integer as a pointer in the wrong way. DanglingIntPointer(u64, CheckInAllocMsg), @@ -252,7 +262,12 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// The value validity check found a problem. /// Should only be thrown by `validity.rs` and always point out which part of the value /// is the problem. - ValidationFailure(String), + ValidationFailure { + /// The "path" to the value in question, e.g. `.0[5].field` for a struct + /// field in the 6th element of an array that is the first element of a tuple. + path: Option, + msg: String, + }, /// Using a non-boolean `u8` as bool. InvalidBool(u8), /// Using a non-character `u32` as character. @@ -287,27 +302,42 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"), PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"), InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg), - InvalidDropFn(sig) => write!( + InvalidVtableDropFn(sig) => write!( f, "invalid drop function signature: got {}, expected exactly one argument which must be a pointer type", sig ), + InvalidVtableSize => { + write!(f, "invalid vtable: size is bigger than largest supported object") + } + InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg), UnterminatedCString(p) => write!( f, - "reading a null-terminated string starting at {} with no null found before end of allocation", + "reading a null-terminated string starting at {:?} with no null found before end of allocation", p, ), PointerUseAfterFree(a) => { write!(f, "pointer to {} was dereferenced after this allocation got freed", a) } - PointerOutOfBounds { ptr, msg, allocation_size } => write!( + PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => { + write!( + f, + "{}{alloc_id} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds", + msg, + alloc_id = alloc_id, + alloc_size = alloc_size.bytes(), + ptr_offset = ptr_offset, + ) + } + PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!( f, - "{}pointer must be in-bounds at offset {}, \ - but is outside bounds of {} which has size {}", + "{}{alloc_id} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds", msg, - ptr.offset.bytes(), - ptr.alloc_id, - allocation_size.bytes() + alloc_id = alloc_id, + alloc_size = alloc_size.bytes(), + ptr_size = ptr_size.bytes(), + ptr_size_p = pluralize!(ptr_size.bytes()), + ptr_offset = ptr_offset, ), DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => { write!(f, "null pointer is not a valid pointer for this operation") @@ -323,7 +353,10 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { ), WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a), DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a), - ValidationFailure(ref err) => write!(f, "type validation failed: {}", err), + ValidationFailure { path: None, msg } => write!(f, "type validation failed: {}", msg), + ValidationFailure { path: Some(path), msg } => { + write!(f, "type validation failed at {}: {}", path, msg) + } InvalidBool(b) => { write!(f, "interpreting an invalid 8-bit value as a bool: 0x{:02x}", b) } @@ -332,13 +365,13 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { } InvalidTag(val) => write!(f, "enum value has invalid tag: {}", val), InvalidFunctionPointer(p) => { - write!(f, "using {} as function pointer but it does not point to a function", p) + write!(f, "using {:?} as function pointer but it does not point to a function", p) } InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err), InvalidUninitBytes(Some((alloc, access))) => write!( f, - "reading {} byte{} of memory starting at {}, \ - but {} byte{} {} uninitialized starting at {}, \ + "reading {} byte{} of memory starting at {:?}, \ + but {} byte{} {} uninitialized starting at {:?}, \ and this operation requires initialized memory", access.access_size.bytes(), pluralize!(access.access_size.bytes()), @@ -376,8 +409,6 @@ pub enum UnsupportedOpInfo { // // The variants below are only reachable from CTFE/const prop, miri will never emit them. // - /// Encountered raw bytes where we needed a pointer. - ReadBytesAsPointer, /// Accessing thread local statics ThreadLocalStatic(DefId), /// Accessing an unsupported extern static. @@ -392,7 +423,6 @@ impl fmt::Display for UnsupportedOpInfo { ReadExternStatic(did) => write!(f, "cannot read from extern static ({:?})", did), NoMirFor(did) => write!(f, "no MIR body is available for {:?}", did), ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",), - ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"), ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({:?})", did), } } @@ -407,6 +437,8 @@ pub enum ResourceExhaustionInfo { /// /// The exact limit is set by the `const_eval_limit` attribute. StepLimitReached, + /// There is not enough memory to perform an allocation. + MemoryExhausted, } impl fmt::Display for ResourceExhaustionInfo { @@ -419,6 +451,9 @@ impl fmt::Display for ResourceExhaustionInfo { StepLimitReached => { write!(f, "exceeded interpreter step limit (see `#[const_eval_limit]`)") } + MemoryExhausted => { + write!(f, "tried to allocate more memory than available to compiler") + } } } } @@ -491,15 +526,27 @@ impl fmt::Debug for InterpError<'_> { } impl InterpError<'_> { - /// Some errors to string formatting even if the error is never printed. + /// Some errors do string formatting even if the error is never printed. /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors, /// so this method lets us detect them and `bug!` on unexpected errors. pub fn formatted_string(&self) -> bool { match self { InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) - | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. }) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true, _ => false, } } + + /// 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/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 14bdb0a5a2..dd9ac7f5c3 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -99,7 +99,7 @@ use std::convert::TryFrom; use std::fmt; use std::io; use std::io::{Read, Write}; -use std::num::NonZeroU32; +use std::num::{NonZeroU32, NonZeroU64}; use std::sync::atomic::{AtomicU32, Ordering}; use rustc_ast::LitKind; @@ -127,7 +127,7 @@ pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMay pub use self::allocation::{alloc_range, AllocRange, Allocation, InitMask, Relocations}; -pub use self::pointer::{Pointer, PointerArithmetic}; +pub use self::pointer::{Pointer, PointerArithmetic, Provenance}; /// Uniquely identifies one of the following: /// - A constant @@ -172,12 +172,11 @@ pub enum LitToConstError { /// This is used for graceful error handling (`delay_span_bug`) in /// type checking (`Const::from_anon_const`). TypeError, - UnparseableFloat, Reported, } #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct AllocId(pub u64); +pub struct AllocId(pub NonZeroU64); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. @@ -428,7 +427,11 @@ crate struct AllocMap<'tcx> { impl<'tcx> AllocMap<'tcx> { crate fn new() -> Self { - AllocMap { alloc_map: Default::default(), dedup: Default::default(), next_id: AllocId(0) } + AllocMap { + alloc_map: Default::default(), + dedup: Default::default(), + next_id: AllocId(NonZeroU64::new(1).unwrap()), + } } fn reserve(&mut self) -> AllocId { let next = self.next_id; diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 8774b48fb3..568b3f252b 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -36,6 +36,20 @@ pub trait PointerArithmetic: HasDataLayout { i64::try_from(max_isize_plus_1 - 1).unwrap() } + #[inline] + fn machine_usize_to_isize(&self, val: u64) -> i64 { + let val = val as i64; + // Now clamp into the machine_isize range. + if val > self.machine_isize_max() { + // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into + // i64. + let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); + val - i64::try_from(max_usize_plus_1).unwrap() + } else { + val + } + } + /// Helper function: truncate given value-"overflowed flag" pair to pointer size and /// update "overflowed flag" if there was an overflow. /// This should be called by all the other methods before returning! @@ -83,55 +97,77 @@ pub trait PointerArithmetic: HasDataLayout { impl PointerArithmetic for T {} +/// This trait abstracts over the kind of provenance that is associated with a `Pointer`. It is +/// mostly opaque; the `Machine` trait extends it with some more operations that also have access to +/// some global state. +/// We don't actually care about this `Debug` bound (we use `Provenance::fmt` to format the entire +/// pointer), but `derive` adds some unecessary bounds. +pub trait Provenance: Copy + fmt::Debug { + /// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address. + /// If `true, ptr-to-int casts work by simply discarding the provenance. + /// If `false`, ptr-to-int casts are not supported. The offset *must* be relative in that case. + const OFFSET_IS_ADDR: bool; + + /// Determines how a pointer should be printed. + fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result + where + Self: Sized; + + /// Provenance must always be able to identify the allocation this ptr points to. + /// (Identifying the offset in that allocation, however, is harder -- use `Memory::ptr_get_alloc` for that.) + fn get_alloc_id(self) -> AllocId; +} + +impl Provenance for AllocId { + // With the `AllocId` as provenance, the `offset` is interpreted *relative to the allocation*, + // so ptr-to-int casts are not possible (since we do not know the global physical offset). + const OFFSET_IS_ADDR: bool = false; + + fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Forward `alternate` flag to `alloc_id` printing. + if f.alternate() { + write!(f, "{:#?}", ptr.provenance)?; + } else { + write!(f, "{:?}", ptr.provenance)?; + } + // Print offset only if it is non-zero. + if ptr.offset.bytes() > 0 { + write!(f, "+0x{:x}", ptr.offset.bytes())?; + } + Ok(()) + } + + fn get_alloc_id(self) -> AllocId { + self + } +} + /// Represents a pointer in the Miri engine. /// -/// `Pointer` is generic over the `Tag` associated with each pointer, -/// which is used to do provenance tracking during execution. +/// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)] #[derive(HashStable)] -pub struct Pointer { - pub alloc_id: AllocId, - pub offset: Size, - pub tag: Tag, +pub struct Pointer { + pub(super) offset: Size, // kept private to avoid accidental misinterpretation (meaning depends on `Tag` type) + pub provenance: Tag, } static_assert_size!(Pointer, 16); -/// Print the address of a pointer (without the tag) -fn print_ptr_addr(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Forward `alternate` flag to `alloc_id` printing. - if f.alternate() { - write!(f, "{:#?}", ptr.alloc_id)?; - } else { - write!(f, "{:?}", ptr.alloc_id)?; - } - // Print offset only if it is non-zero. - if ptr.offset.bytes() > 0 { - write!(f, "+0x{:x}", ptr.offset.bytes())?; - } - Ok(()) -} - // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. -// We have to use `Debug` output for the tag, because `()` does not implement -// `Display` so we cannot specialize that. -impl fmt::Debug for Pointer { - default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - print_ptr_addr(self, f)?; - write!(f, "[{:?}]", self.tag) - } -} -// Specialization for no tag -impl fmt::Debug for Pointer<()> { +impl fmt::Debug for Pointer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - print_ptr_addr(self, f) + Provenance::fmt(self, f) } } -impl fmt::Display for Pointer { +impl fmt::Debug for Pointer> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self, f) + match self.provenance { + Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f), + None => write!(f, "0x{:x}", self.offset.bytes()), + } } } @@ -143,37 +179,61 @@ impl From for Pointer { } } -impl Pointer<()> { +impl From> for Pointer> { #[inline(always)] - pub fn new(alloc_id: AllocId, offset: Size) -> Self { - Pointer { alloc_id, offset, tag: () } + fn from(ptr: Pointer) -> Self { + let (tag, offset) = ptr.into_parts(); + Pointer::new(Some(tag), offset) } +} +impl Pointer> { + pub fn into_pointer_or_addr(self) -> Result, Size> { + match self.provenance { + Some(tag) => Ok(Pointer::new(tag, self.offset)), + None => Err(self.offset), + } + } +} + +impl Pointer> { #[inline(always)] - pub fn with_tag(self, tag: Tag) -> Pointer { - Pointer::new_with_tag(self.alloc_id, self.offset, tag) + pub fn null() -> Self { + Pointer { provenance: None, offset: Size::ZERO } } } impl<'tcx, Tag> Pointer { #[inline(always)] - pub fn new_with_tag(alloc_id: AllocId, offset: Size, tag: Tag) -> Self { - Pointer { alloc_id, offset, tag } + pub fn new(provenance: Tag, offset: Size) -> Self { + Pointer { provenance, offset } + } + + /// Obtain the constituents of this pointer. Not that the meaning of the offset depends on the type `Tag`! + /// This function must only be used in the implementation of `Machine::ptr_get_alloc`, + /// and when a `Pointer` is taken apart to be stored efficiently in an `Allocation`. + #[inline(always)] + pub fn into_parts(self) -> (Tag, Size) { + (self.provenance, self.offset) + } + + pub fn map_provenance(self, f: impl FnOnce(Tag) -> Tag) -> Self { + Pointer { provenance: f(self.provenance), ..self } } #[inline] pub fn offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - Ok(Pointer::new_with_tag( - self.alloc_id, - Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?), - self.tag, - )) + Ok(Pointer { + offset: Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?), + ..self + }) } #[inline] pub fn overflowing_offset(self, i: Size, cx: &impl HasDataLayout) -> (Self, bool) { let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes()); - (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over) + let ptr = Pointer { offset: Size::from_bytes(res), ..self }; + (ptr, over) } #[inline(always)] @@ -183,26 +243,21 @@ impl<'tcx, Tag> Pointer { #[inline] pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - Ok(Pointer::new_with_tag( - self.alloc_id, - Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?), - self.tag, - )) + Ok(Pointer { + offset: Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?), + ..self + }) } #[inline] pub fn overflowing_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> (Self, bool) { let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i); - (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over) + let ptr = Pointer { offset: Size::from_bytes(res), ..self }; + (ptr, over) } #[inline(always)] pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { self.overflowing_signed_offset(i, cx).0 } - - #[inline(always)] - pub fn erase_tag(self) -> Pointer { - Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } - } } diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 66ff6990e8..62b71b10d5 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -6,11 +6,13 @@ use rustc_apfloat::{ Float, }; use rustc_macros::HashStable; -use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout}; +use rustc_target::abi::{HasDataLayout, Size}; use crate::ty::{Lift, ParamEnv, ScalarInt, Ty, TyCtxt}; -use super::{AllocId, AllocRange, Allocation, InterpResult, Pointer, PointerArithmetic}; +use super::{ + AllocId, AllocRange, Allocation, InterpResult, Pointer, PointerArithmetic, Provenance, +}; /// Represents the result of const evaluation via the `eval_to_allocation` query. #[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)] @@ -47,12 +49,6 @@ pub enum ConstValue<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstValue<'_>, 32); -impl From for ConstValue<'tcx> { - fn from(s: Scalar) -> Self { - Self::Scalar(s) - } -} - impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> { type Lifted = ConstValue<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option> { @@ -70,7 +66,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> { impl<'tcx> ConstValue<'tcx> { #[inline] - pub fn try_to_scalar(&self) -> Option { + pub fn try_to_scalar(&self) -> Option> { match *self { ConstValue::ByRef { .. } | ConstValue::Slice { .. } => None, ConstValue::Scalar(val) => Some(val), @@ -120,16 +116,23 @@ impl<'tcx> ConstValue<'tcx> { /// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 16 bytes in /// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes /// of a simple value or a pointer into another `Allocation` +/// +/// These variants would be private if there was a convenient way to achieve that in Rust. +/// Do *not* match on a `Scalar`! Use the various `to_*` methods instead. #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)] #[derive(HashStable)] -pub enum Scalar { +pub enum Scalar { /// The raw bytes of a simple value. Int(ScalarInt), /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the /// relocation and its associated offset together as a `Pointer` here. - Ptr(Pointer), + /// + /// We also store the size of the pointer, such that a `Scalar` always knows how big it is. + /// The size is always the pointer size of the current target, but this is not information + /// that we always have readily available. + Ptr(Pointer, u8), } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -137,20 +140,20 @@ static_assert_size!(Scalar, 24); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. -impl fmt::Debug for Scalar { +impl fmt::Debug for Scalar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Scalar::Ptr(ptr) => write!(f, "{:?}", ptr), + Scalar::Ptr(ptr, _size) => write!(f, "{:?}", ptr), Scalar::Int(int) => write!(f, "{:?}", int), } } } -impl fmt::Display for Scalar { +impl fmt::Display for Scalar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Scalar::Ptr(ptr) => write!(f, "pointer to {}", ptr), - Scalar::Int { .. } => fmt::Debug::fmt(self, f), + Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr), + Scalar::Int(int) => write!(f, "{:?}", int), } } } @@ -169,83 +172,34 @@ impl From for Scalar { } } -impl Scalar<()> { - /// Tag this scalar with `new_tag` if it is a pointer, leave it unchanged otherwise. - /// - /// Used by `MemPlace::replace_tag`. - #[inline] - pub fn with_tag(self, new_tag: Tag) -> Scalar { - match self { - Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)), - Scalar::Int(int) => Scalar::Int(int), - } +impl From for Scalar { + #[inline(always)] + fn from(ptr: ScalarInt) -> Self { + Scalar::Int(ptr) } } -impl<'tcx, Tag> Scalar { +impl Scalar { pub const ZST: Self = Scalar::Int(ScalarInt::ZST); - /// Erase the tag from the scalar, if any. - /// - /// Used by error reporting code to avoid having the error type depend on `Tag`. - #[inline] - pub fn erase_tag(self) -> Scalar { - match self { - Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()), - Scalar::Int(int) => Scalar::Int(int), - } - } - - #[inline] - pub fn null_ptr(cx: &impl HasDataLayout) -> Self { - Scalar::Int(ScalarInt::null(cx.data_layout().pointer_size)) - } - #[inline(always)] - fn ptr_op( - self, - dl: &TargetDataLayout, - f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>, - f_ptr: impl FnOnce(Pointer) -> InterpResult<'tcx, Pointer>, - ) -> InterpResult<'tcx, Self> { - match self { - Scalar::Int(int) => Ok(Scalar::Int(int.ptr_sized_op(dl, f_int)?)), - Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)), - } - } - - #[inline] - pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - let dl = cx.data_layout(); - self.ptr_op(dl, |int| dl.offset(int, i.bytes()), |ptr| ptr.offset(i, dl)) + pub fn from_pointer(ptr: Pointer, cx: &impl HasDataLayout) -> Self { + Scalar::Ptr(ptr, u8::try_from(cx.pointer_size().bytes()).unwrap()) } - #[inline] - pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self { - let dl = cx.data_layout(); - self.ptr_op( - dl, - |int| Ok(dl.overflowing_offset(int, i.bytes()).0), - |ptr| Ok(ptr.wrapping_offset(i, dl)), - ) - .unwrap() - } - - #[inline] - pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - let dl = cx.data_layout(); - self.ptr_op(dl, |int| dl.signed_offset(int, i), |ptr| ptr.signed_offset(i, dl)) + /// Create a Scalar from a pointer with an `Option<_>` tag (where `None` represents a plain integer). + pub fn from_maybe_pointer(ptr: Pointer>, cx: &impl HasDataLayout) -> Self { + match ptr.into_parts() { + (Some(tag), offset) => Scalar::from_pointer(Pointer::new(tag, offset), cx), + (None, offset) => { + Scalar::Int(ScalarInt::try_from_uint(offset.bytes(), cx.pointer_size()).unwrap()) + } + } } #[inline] - pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { - let dl = cx.data_layout(); - self.ptr_op( - dl, - |int| Ok(dl.overflowing_signed_offset(int, i).0), - |ptr| Ok(ptr.wrapping_signed_offset(i, dl)), - ) - .unwrap() + pub fn null_ptr(cx: &impl HasDataLayout) -> Self { + Scalar::Int(ScalarInt::null(cx.pointer_size())) } #[inline] @@ -332,74 +286,71 @@ impl<'tcx, Tag> Scalar { Scalar::Int(f.into()) } - /// This is very rarely the method you want! You should dispatch on the type - /// and use `force_bits`/`assert_bits`/`force_ptr`/`assert_ptr`. - /// This method only exists for the benefit of low-level memory operations - /// as well as the implementation of the `force_*` methods. + /// This is almost certainly not the method you want! You should dispatch on the type + /// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed. + /// + /// This method only exists for the benefit of low-level operations that truly need to treat the + /// scalar in whatever form it is. #[inline] - pub fn to_bits_or_ptr( - self, - target_size: Size, - cx: &impl HasDataLayout, - ) -> Result> { + pub fn to_bits_or_ptr_internal(self, target_size: Size) -> Result> { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); match self { Scalar::Int(int) => Ok(int.assert_bits(target_size)), - Scalar::Ptr(ptr) => { - assert_eq!(target_size, cx.data_layout().pointer_size); + Scalar::Ptr(ptr, sz) => { + assert_eq!(target_size.bytes(), u64::from(sz)); Err(ptr) } } } +} - /// This method is intentionally private! - /// It is just a helper for other methods in this file. +impl<'tcx, Tag: Provenance> Scalar { + /// Fundamental scalar-to-int (cast) operation. Many convenience wrappers exist below, that you + /// likely want to use instead. + /// + /// Will perform ptr-to-int casts if needed and possible. + /// If that fails, we know the offset is relative, so we return an "erased" Scalar + /// (which is useful for error messages but not much else). #[inline] - fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { - assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); + pub fn try_to_int(self) -> Result> { match self { - Scalar::Int(int) => int.to_bits(target_size).map_err(|size| { - err_ub!(ScalarSizeMismatch { - target_size: target_size.bytes(), - data_size: size.bytes(), - }) - .into() - }), - Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes), + Scalar::Int(int) => Ok(int), + Scalar::Ptr(ptr, sz) => { + if Tag::OFFSET_IS_ADDR { + Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap()) + } else { + // We know `offset` is relative, since `OFFSET_IS_ADDR == false`. + let (tag, offset) = ptr.into_parts(); + Err(Scalar::Ptr(Pointer::new(tag.get_alloc_id(), offset), sz)) + } + } } } #[inline(always)] - pub fn assert_bits(self, target_size: Size) -> u128 { - self.to_bits(target_size).expect("expected Raw bits but got a Pointer") - } - - #[inline] pub fn assert_int(self) -> ScalarInt { - match self { - Scalar::Ptr(_) => bug!("expected an int but got an abstract pointer"), - Scalar::Int(int) => int, - } + self.try_to_int().unwrap() } + /// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in + /// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type. #[inline] - pub fn assert_ptr(self) -> Pointer { - match self { - Scalar::Ptr(p) => p, - Scalar::Int { .. } => bug!("expected a Pointer but got Raw bits"), - } - } - - /// Do not call this method! Dispatch based on the type instead. - #[inline] - pub fn is_bits(self) -> bool { - matches!(self, Scalar::Int { .. }) + pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { + assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); + self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err( + |size| { + err_ub!(ScalarSizeMismatch { + target_size: target_size.bytes(), + data_size: size.bytes(), + }) + .into() + }, + ) } - /// Do not call this method! Dispatch based on the type instead. - #[inline] - pub fn is_ptr(self) -> bool { - matches!(self, Scalar::Ptr(_)) + #[inline(always)] + pub fn assert_bits(self, target_size: Size) -> u128 { + self.to_bits(target_size).unwrap() } pub fn to_bool(self) -> InterpResult<'tcx, bool> { @@ -507,22 +458,8 @@ impl<'tcx, Tag> Scalar { } } -impl From> for Scalar { - #[inline(always)] - fn from(ptr: Pointer) -> Self { - Scalar::Ptr(ptr) - } -} - -impl From for Scalar { - #[inline(always)] - fn from(ptr: ScalarInt) -> Self { - Scalar::Int(ptr) - } -} - #[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, HashStable, Hash)] -pub enum ScalarMaybeUninit { +pub enum ScalarMaybeUninit { Scalar(Scalar), Uninit, } @@ -537,16 +474,9 @@ impl From> for ScalarMaybeUninit { } } -impl From> for ScalarMaybeUninit { - #[inline(always)] - fn from(s: Pointer) -> Self { - ScalarMaybeUninit::Scalar(s.into()) - } -} - // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. -impl fmt::Debug for ScalarMaybeUninit { +impl fmt::Debug for ScalarMaybeUninit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ScalarMaybeUninit::Uninit => write!(f, ""), @@ -555,7 +485,7 @@ impl fmt::Debug for ScalarMaybeUninit { } } -impl fmt::Display for ScalarMaybeUninit { +impl fmt::Display for ScalarMaybeUninit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ScalarMaybeUninit::Uninit => write!(f, "uninitialized bytes"), @@ -564,16 +494,15 @@ impl fmt::Display for ScalarMaybeUninit { } } -impl<'tcx, Tag> ScalarMaybeUninit { - /// Erase the tag from the scalar, if any. - /// - /// Used by error reporting code to avoid having the error type depend on `Tag`. +impl ScalarMaybeUninit { #[inline] - pub fn erase_tag(self) -> ScalarMaybeUninit { - match self { - ScalarMaybeUninit::Scalar(s) => ScalarMaybeUninit::Scalar(s.erase_tag()), - ScalarMaybeUninit::Uninit => ScalarMaybeUninit::Uninit, - } + pub fn from_pointer(ptr: Pointer, cx: &impl HasDataLayout) -> Self { + ScalarMaybeUninit::Scalar(Scalar::from_pointer(ptr, cx)) + } + + #[inline] + pub fn from_maybe_pointer(ptr: Pointer>, cx: &impl HasDataLayout) -> Self { + ScalarMaybeUninit::Scalar(Scalar::from_maybe_pointer(ptr, cx)) } #[inline] @@ -583,7 +512,9 @@ impl<'tcx, Tag> ScalarMaybeUninit { ScalarMaybeUninit::Uninit => throw_ub!(InvalidUninitBytes(None)), } } +} +impl<'tcx, Tag: Provenance> ScalarMaybeUninit { #[inline(always)] pub fn to_bool(self) -> InterpResult<'tcx, bool> { self.check_init()?.to_bool() diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7ae7eab6e5..da0d2575dc 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -3,7 +3,7 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html use crate::mir::coverage::{CodeRegion, CoverageKind}; -use crate::mir::interpret::{Allocation, GlobalAlloc, Scalar}; +use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar}; use crate::mir::visit::MirVisitable; use crate::ty::adjustment::PointerCast; use crate::ty::codec::{TyDecoder, TyEncoder}; @@ -494,7 +494,7 @@ impl<'tcx> Body<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] pub enum Safety { Safe, - /// Unsafe because of a PushUnsafeBlock + /// Unsafe because of compiler-generated unsafe code, like `await` desugaring BuiltinUnsafe, /// Unsafe because of an unsafe fn FnUnsafe, @@ -651,7 +651,7 @@ pub enum BorrowKind { /// in an aliasable location. To solve, you'd have to translate with /// an `&mut` borrow: /// - /// struct Env { x: & &mut isize } + /// struct Env { x: &mut &mut isize } /// let x: &mut isize = ...; /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x /// fn fn_ptr(env: &mut Env) { **env.x += 5; } @@ -2095,7 +2095,7 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(box Constant { span, user_ty: None, - literal: ConstantKind::Val(val.into(), ty), + literal: ConstantKind::Val(ConstValue::Scalar(val), ty), }) } @@ -2458,7 +2458,7 @@ pub enum ConstantKind<'tcx> { impl Constant<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { match self.literal.const_for_ty()?.val.try_to_scalar() { - Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) { + Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); Some(def_id) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 74650f50a1..776cf002c1 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -490,15 +490,23 @@ impl CodegenUnitNameBuilder<'tcx> { // local crate's ID. Otherwise there can be collisions between CGUs // instantiating stuff for upstream crates. let local_crate_id = if cnum != LOCAL_CRATE { - let local_crate_disambiguator = format!("{}", tcx.crate_disambiguator(LOCAL_CRATE)); - format!("-in-{}.{}", tcx.crate_name(LOCAL_CRATE), &local_crate_disambiguator[0..8]) + let local_stable_crate_id = tcx.sess.local_stable_crate_id(); + format!( + "-in-{}.{:08x}", + tcx.crate_name(LOCAL_CRATE), + local_stable_crate_id.to_u64() as u32, + ) } else { String::new() }; - let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string(); - // Using a shortened disambiguator of about 40 bits - format!("{}.{}{}", tcx.crate_name(cnum), &crate_disambiguator[0..8], local_crate_id) + let stable_crate_id = tcx.sess.local_stable_crate_id(); + format!( + "{}.{:08x}{}", + tcx.crate_name(cnum), + stable_crate_id.to_u64() as u32, + local_crate_id, + ) }); write!(cgu_name, "{}", crate_prefix).unwrap(); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0860520ef9..0908b6a176 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -14,6 +14,12 @@ rustc_queries! { desc { "trigger a delay span bug" } } + query resolutions(_: ()) -> &'tcx ty::ResolverOutputs { + eval_always + no_hash + desc { "get the resolver outputs" } + } + /// Represents crate as a whole (as distinct from the top-level crate module). /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`), /// we will have to assume that any change means that you need to be recompiled. @@ -191,10 +197,6 @@ rustc_queries! { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } - query projection_ty_from_predicates(key: (DefId, DefId)) -> Option> { - desc { |tcx| "finding projection type inside predicates of `{}`", tcx.def_path_str(key.0) } - } - query native_libraries(_: CrateNum) -> Lrc> { desc { "looking up the native libraries of a linked crate" } } @@ -211,6 +213,7 @@ rustc_queries! { } query expn_that_defined(key: DefId) -> rustc_span::ExpnId { + // This query reads from untracked data in definitions. eval_always desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } } @@ -721,7 +724,7 @@ rustc_queries! { cache_on_disk_if { true } load_cached(tcx, id) { let typeck_results: Option> = tcx - .on_disk_cache.as_ref() + .on_disk_cache().as_ref() .and_then(|c| c.try_load_query_result(*tcx, id)); typeck_results.map(|x| &*tcx.arena.alloc(x)) @@ -920,6 +923,10 @@ rustc_queries! { desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) } } + query should_inherit_track_caller(def_id: DefId) -> bool { + desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) } + } + query lookup_deprecation_entry(def_id: DefId) -> Option { desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } } @@ -959,9 +966,9 @@ rustc_queries! { desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) } } - query vtable_methods(key: ty::PolyTraitRef<'tcx>) - -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] { - desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) } + query vtable_entries(key: ty::PolyTraitRef<'tcx>) + -> &'tcx [ty::VtblEntry<'tcx>] { + desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) } } query codegen_fulfill_obligation( @@ -1133,13 +1140,16 @@ rustc_queries! { query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) } - eval_always } query impl_defaultness(def_id: DefId) -> hir::Defaultness { desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) } } + query impl_constness(def_id: DefId) -> hir::Constness { + desc { |tcx| "looking up whether `{}` is a const impl", tcx.def_path_str(def_id) } + } + query check_item_well_formed(key: LocalDefId) -> () { desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) } } @@ -1237,10 +1247,6 @@ rustc_queries! { query proc_macro_decls_static(_: ()) -> Option { desc { "looking up the derive registrar for a crate" } } - query crate_disambiguator(_: CrateNum) -> CrateDisambiguator { - eval_always - desc { "looking up the disambiguator a crate" } - } // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. // Changing the name should cause a compiler error, but in case that changes, be aware. query crate_hash(_: CrateNum) -> Svh { @@ -1327,7 +1333,6 @@ rustc_queries! { } query visibility(def_id: DefId) -> ty::Visibility { - eval_always desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) } } @@ -1352,8 +1357,6 @@ rustc_queries! { desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) } } query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option { - // This depends on untracked global state (`tcx.extern_crate_map`) - eval_always desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) } } @@ -1420,22 +1423,22 @@ rustc_queries! { eval_always desc { "check whether crate {} is a private dependency", c } } + query allocator_kind(_: ()) -> Option { + eval_always + desc { "allocator kind for the current crate" } + } query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } eval_always } query maybe_unused_trait_import(def_id: LocalDefId) -> bool { - eval_always desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) } } query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] { - eval_always desc { "looking up all possibly unused extern crates" } } - query names_imported_by_glob_use(def_id: LocalDefId) - -> &'tcx FxHashSet { - eval_always + query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet { desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) } } @@ -1444,7 +1447,7 @@ rustc_queries! { eval_always desc { "calculating the stability index for the local crate" } } - query all_crate_nums(_: ()) -> &'tcx [CrateNum] { + query crates(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching all foreign CrateNum instances" } } @@ -1559,12 +1562,6 @@ rustc_queries! { desc { "evaluating trait selection obligation `{}`", goal.value } } - query type_implements_trait( - key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, ) - ) -> bool { - desc { "evaluating `type_implements_trait` `{:?}`", key } - } - /// Do not call this query directly: part of the `Eq` type-op query type_op_ascribe_user_type( goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> @@ -1712,4 +1709,22 @@ rustc_queries! { query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "conservatively checking if {:?} is privately uninhabited", key } } + + query limits(key: ()) -> Limits { + desc { "looking up limits" } + } + + /// Performs an HIR-based well-formed check on the item with the given `HirId`. If + /// we get an `Umimplemented` error that matches the provided `Predicate`, return + /// the cause of the newly created obligation. + /// + /// This is only used by error-reporting code to get a better cause (in particular, a better + /// span) for an *existing* error. Therefore, it is best-effort, and may never handle + /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, + /// because the `ty::Ty`-based wfcheck is always run. + query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option> { + eval_always + no_hash + desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 } + } } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index a506911370..cdefc9effa 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -1,3 +1,13 @@ +//! THIR datatypes and definitions. See the [rustc dev guide] for more info. +//! +//! If you compare the THIR [`ExprKind`] to [`hir::ExprKind`], you will see it is +//! a good bit simpler. In fact, a number of the more straight-forward +//! MIR simplifications are already done in the lowering to THIR. For +//! example, method calls and overloaded operators are absent: they are +//! expected to be converted into [`ExprKind::Call`] instances. +//! +//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html + use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -24,6 +34,7 @@ use std::fmt; use std::ops::Index; newtype_index! { + /// An index to an [`Arm`] stored in [`Thir::arms`] #[derive(HashStable)] pub struct ArmId { DEBUG_FORMAT = "a{}" @@ -31,6 +42,7 @@ newtype_index! { } newtype_index! { + /// An index to an [`Expr`] stored in [`Thir::exprs`] #[derive(HashStable)] pub struct ExprId { DEBUG_FORMAT = "e{}" @@ -39,6 +51,7 @@ newtype_index! { newtype_index! { #[derive(HashStable)] + /// An index to a [`Stmt`] stored in [`Thir::stmts`] pub struct StmtId { DEBUG_FORMAT = "s{}" } @@ -46,6 +59,9 @@ newtype_index! { macro_rules! thir_with_elements { ($($name:ident: $id:ty => $value:ty,)*) => { + /// A container for a THIR body. + /// + /// This can be indexed directly by any THIR index (e.g. [`ExprId`]). #[derive(Debug, HashStable)] pub struct Thir<'tcx> { $( @@ -88,21 +104,47 @@ pub enum LintLevel { #[derive(Debug, HashStable)] pub struct Block { + /// Whether the block itself has a label. Used by `label: {}` + /// and `try` blocks. + /// + /// This does *not* include labels on loops, e.g. `'label: loop {}`. pub targeted_by_break: bool, pub region_scope: region::Scope, pub opt_destruction_scope: Option, + /// The span of the block, including the opening braces, + /// the label, and the `unsafe` keyword, if present. pub span: Span, + /// The statements in the blocK. pub stmts: Box<[StmtId]>, + /// The trailing expression of the block, if any. pub expr: Option, pub safety_mode: BlockSafety, } +#[derive(Debug, HashStable)] +pub struct Adt<'tcx> { + /// The ADT we're constructing. + pub adt_def: &'tcx AdtDef, + /// The variant of the ADT. + pub variant_index: VariantIdx, + pub substs: SubstsRef<'tcx>, + + /// Optional user-given substs: for something like `let x = + /// Bar:: { ... }`. + pub user_ty: Option>>, + + pub fields: Box<[FieldExpr]>, + /// The base, e.g. `Foo {x: 1, .. base}`. + pub base: Option>, +} + #[derive(Copy, Clone, Debug, HashStable)] pub enum BlockSafety { Safe, + /// A compiler-generated unsafe block + BuiltinUnsafe, + /// An `unsafe` block. The `HirId` is the ID of the block. ExplicitUnsafe(hir::HirId), - PushUnsafe, - PopUnsafe, } #[derive(Debug, HashStable)] @@ -113,61 +155,50 @@ pub struct Stmt<'tcx> { #[derive(Debug, HashStable)] pub enum StmtKind<'tcx> { + /// An expression with a trailing semicolon. Expr { - /// scope for this statement; may be used as lifetime of temporaries + /// The scope for this statement; may be used as lifetime of temporaries. scope: region::Scope, - /// expression being evaluated in this statement + /// The expression being evaluated in this statement. expr: ExprId, }, + /// A `let` binding. Let { - /// scope for variables bound in this let; covers this and - /// remaining statements in block + /// The scope for variables bound in this `let`; it covers this and + /// all the remaining statements in the block. remainder_scope: region::Scope, - /// scope for the initialization itself; might be used as - /// lifetime of temporaries + /// The scope for the initialization itself; might be used as + /// lifetime of temporaries. init_scope: region::Scope, /// `let = ...` /// - /// if a type is included, it is added as an ascription pattern + /// If a type annotation is included, it is added as an ascription pattern. pattern: Pat<'tcx>, - /// let pat: ty = ... + /// `let pat: ty = ` initializer: Option, - /// the lint level for this let-statement + /// The lint level for this `let` statement. lint_level: LintLevel, }, } // `Expr` 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!(Expr<'_>, 144); - -/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`) -/// into instances of this `Expr` enum. This lowering can be done -/// basically as lazily or as eagerly as desired: every recursive -/// reference to an expression in this enum is an `ExprId`, which -/// may in turn be another instance of this enum (boxed), or else an -/// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very -/// short-lived. They are created by `Thir::to_expr`, analyzed and -/// converted into MIR, and then discarded. -/// -/// If you compare `Expr` to the full compiler AST, you will see it is -/// a good bit simpler. In fact, a number of the more straight-forward -/// MIR simplifications are already done in the impl of `Thir`. For -/// example, method calls and overloaded operators are absent: they are -/// expected to be converted into `Expr::Call` instances. +rustc_data_structures::static_assert_size!(Expr<'_>, 104); + +/// A THIR expression. #[derive(Debug, HashStable)] pub struct Expr<'tcx> { - /// type of this expression + /// The type of this expression pub ty: Ty<'tcx>, - /// lifetime of this expression if it should be spilled into a - /// temporary; should be None only if in a constant context + /// The lifetime of this expression if it should be spilled into a + /// temporary; should be `None` only if in a constant context pub temp_lifetime: Option, /// span of the expression in the source @@ -179,88 +210,120 @@ pub struct Expr<'tcx> { #[derive(Debug, HashStable)] pub enum ExprKind<'tcx> { + /// `Scope`s are used to explicitely mark destruction scopes, + /// and to track the `HirId` of the expressions within the scope. Scope { region_scope: region::Scope, lint_level: LintLevel, value: ExprId, }, + /// A `box ` expression. Box { value: ExprId, }, + /// An `if` expression. If { cond: ExprId, then: ExprId, else_opt: Option, }, + /// A function call. Method calls and overloaded operators are converted to plain function calls. Call { + /// The type of the function. This is often a [`FnDef`] or a [`FnPtr`]. + /// + /// [`FnDef`]: ty::TyKind::FnDef + /// [`FnPtr`]: ty::TyKind::FnPtr ty: Ty<'tcx>, + /// The function itself. fun: ExprId, + /// The arguments passed to the function. + /// + /// Note: in some cases (like calling a closure), the function call `f(...args)` gets + /// rewritten as a call to a function trait method (e.g. `FnOnce::call_once(f, (...args))`). args: Box<[ExprId]>, - /// Whether this is from a call in HIR, rather than from an overloaded - /// operator. `true` for overloaded function call. + /// Whether this is from an overloaded operator rather than a + /// function call from HIR. `true` for overloaded function call. from_hir_call: bool, - /// This `Span` is the span of the function, without the dot and receiver - /// (e.g. `foo(a, b)` in `x.foo(a, b)` + /// The span of the function, without the dot and receiver + /// (e.g. `foo(a, b)` in `x.foo(a, b)`). fn_span: Span, }, + /// A *non-overloaded* dereference. Deref { arg: ExprId, - }, // NOT overloaded! + }, + /// A *non-overloaded* binary operation. Binary { op: BinOp, lhs: ExprId, rhs: ExprId, - }, // NOT overloaded! + }, + /// A logical operation. This is distinct from `BinaryOp` because + /// the operands need to be lazily evaluated. LogicalOp { op: LogicalOp, lhs: ExprId, rhs: ExprId, - }, // NOT overloaded! - // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands. + }, + /// A *non-overloaded* unary operation. Note that here the deref (`*`) + /// operator is represented by `ExprKind::Deref`. Unary { op: UnOp, arg: ExprId, - }, // NOT overloaded! + }, + /// A cast: ` as `. The type we cast to is the type of + /// the parent expression. Cast { source: ExprId, }, Use { source: ExprId, }, // Use a lexpr to get a vexpr. + /// A coercion from `!` to any type. NeverToAny { source: ExprId, }, + /// A pointer cast. More information can be found in [`PointerCast`]. Pointer { cast: PointerCast, source: ExprId, }, + /// A `loop` expression. Loop { body: ExprId, }, + /// A `match` expression. Match { scrutinee: ExprId, arms: Box<[ArmId]>, }, + /// A block. Block { body: Block, }, + /// An assignment: `lhs = rhs`. Assign { lhs: ExprId, rhs: ExprId, }, + /// A *non-overloaded* operation assignment, e.g. `lhs += rhs`. AssignOp { op: BinOp, lhs: ExprId, rhs: ExprId, }, + /// Access to a struct or tuple field. Field { lhs: ExprId, + /// This can be a named (`.foo`) or unnamed (`.0`) field. name: Field, }, + /// A *non-overloaded* indexing operation. Index { lhs: ExprId, index: ExprId, }, + /// A local variable. VarRef { id: hir::HirId, }, @@ -272,6 +335,7 @@ pub enum ExprKind<'tcx> { /// HirId of the root variable var_hir_id: hir::HirId, }, + /// A borrow, e.g. `&arg`. Borrow { borrow_kind: BorrowKind, arg: ExprId, @@ -281,51 +345,51 @@ pub enum ExprKind<'tcx> { mutability: hir::Mutability, arg: ExprId, }, + /// A `break` expression. Break { label: region::Scope, value: Option, }, + /// A `continue` expression. Continue { label: region::Scope, }, + /// A `return` expression. Return { value: Option, }, + /// An inline `const` block, e.g. `const {}`. ConstBlock { value: &'tcx Const<'tcx>, }, + /// An array literal constructed from one repeated element, e.g. `[1; 5]`. Repeat { value: ExprId, count: &'tcx Const<'tcx>, }, + /// An array, e.g. `[a, b, c, d]`. Array { fields: Box<[ExprId]>, }, + /// A tuple, e.g. `(a, b, c, d)`. Tuple { fields: Box<[ExprId]>, }, - Adt { - adt_def: &'tcx AdtDef, - variant_index: VariantIdx, - substs: SubstsRef<'tcx>, - - /// Optional user-given substs: for something like `let x = - /// Bar:: { ... }`. - user_ty: Option>>, - - fields: Box<[FieldExpr]>, - base: Option>, - }, + /// An ADT constructor, e.g. `Foo {x: 1, y: 2}`. + Adt(Box>), + /// A type ascription on a place. PlaceTypeAscription { source: ExprId, /// Type that the user gave to this expression user_ty: Option>>, }, + /// A type ascription on a value, e.g. `42: i32`. ValueTypeAscription { source: ExprId, /// Type that the user gave to this expression user_ty: Option>>, }, + /// A closure definition. Closure { closure_id: DefId, substs: UpvarSubsts<'tcx>, @@ -333,6 +397,7 @@ pub enum ExprKind<'tcx> { movability: Option, fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>, }, + /// A literal. Literal { literal: &'tcx Const<'tcx>, user_ty: Option>>, @@ -349,6 +414,7 @@ pub enum ExprKind<'tcx> { literal: &'tcx Const<'tcx>, def_id: DefId, }, + /// Inline assembly, i.e. `asm!()`. InlineAsm { template: &'tcx [InlineAsmTemplatePiece], operands: Box<[InlineAsmOperand<'tcx>]>, @@ -357,16 +423,21 @@ pub enum ExprKind<'tcx> { }, /// An expression taking a reference to a thread local. ThreadLocalRef(DefId), + /// Inline LLVM assembly, i.e. `llvm_asm!()`. LlvmInlineAsm { asm: &'tcx hir::LlvmInlineAsmInner, outputs: Box<[ExprId]>, inputs: Box<[ExprId]>, }, + /// A `yield` expression. Yield { value: ExprId, }, } +/// Represents the association of a field identifier and an expression. +/// +/// This is used in struct constructors. #[derive(Debug, HashStable)] pub struct FieldExpr { pub name: Field, @@ -379,6 +450,7 @@ pub struct FruInfo<'tcx> { pub field_types: Box<[Ty<'tcx>]>, } +/// A `match` arm. #[derive(Debug, HashStable)] pub struct Arm<'tcx> { pub pattern: Pat<'tcx>, @@ -389,6 +461,7 @@ pub struct Arm<'tcx> { pub span: Span, } +/// A `match` guard. #[derive(Debug, HashStable)] pub enum Guard<'tcx> { If(ExprId), @@ -397,7 +470,9 @@ pub enum Guard<'tcx> { #[derive(Copy, Clone, Debug, HashStable)] pub enum LogicalOp { + /// The `&&` operator. And, + /// The `||` operator. Or, } @@ -514,6 +589,7 @@ pub struct Ascription<'tcx> { #[derive(Clone, Debug, PartialEq, HashStable)] pub enum PatKind<'tcx> { + /// A wildward pattern: `_`. Wild, AscribeUserType { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index c9b73c6820..a4a2e82463 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -13,9 +13,10 @@ use crate::mir::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; +use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::Constness; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -24,7 +25,6 @@ use smallvec::SmallVec; use std::borrow::Cow; use std::fmt; use std::ops::Deref; -use std::rc::Rc; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; @@ -87,7 +87,7 @@ pub enum Reveal { #[derive(Clone, PartialEq, Eq, Hash, Lift)] pub struct ObligationCause<'tcx> { /// `None` for `ObligationCause::dummy`, `Some` otherwise. - data: Option>>, + data: Option>>, } const DUMMY_OBLIGATION_CAUSE_DATA: ObligationCauseData<'static> = @@ -131,7 +131,7 @@ impl<'tcx> ObligationCause<'tcx> { body_id: hir::HirId, code: ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx> { - ObligationCause { data: Some(Rc::new(ObligationCauseData { span, body_id, code })) } + ObligationCause { data: Some(Lrc::new(ObligationCauseData { span, body_id, code })) } } pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> { @@ -148,7 +148,7 @@ impl<'tcx> ObligationCause<'tcx> { } pub fn make_mut(&mut self) -> &mut ObligationCauseData<'tcx> { - Rc::make_mut(self.data.get_or_insert_with(|| Rc::new(DUMMY_OBLIGATION_CAUSE_DATA))) + Lrc::make_mut(self.data.get_or_insert_with(|| Lrc::new(DUMMY_OBLIGATION_CAUSE_DATA))) } pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span { @@ -326,6 +326,38 @@ pub enum ObligationCauseCode<'tcx> { /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` OpaqueType, + + /// Well-formed checking. If a `WellFormedLoc` is provided, + /// then it will be used to eprform HIR-based wf checking + /// after an error occurs, in order to generate a more precise error span. + /// This is purely for diagnostic purposes - it is always + /// correct to use `MiscObligation` instead, or to specify + /// `WellFormed(None)` + WellFormed(Option), + + /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against. + MatchImpl(Lrc>, DefId), +} + +/// The 'location' at which we try to perform HIR-based wf checking. +/// This information is used to obtain an `hir::Ty`, which +/// we can walk in order to obtain precise spans for any +/// 'nested' types (e.g. `Foo` in `Option`). +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum WellFormedLoc { + /// Use the type of the provided definition. + Ty(LocalDefId), + /// Use the type of the parameter of the provided function. + /// We cannot use `hir::Param`, since the function may + /// not have a body (e.g. a trait method definition) + Param { + /// The function to lookup the parameter in + function: LocalDefId, + /// The index of the parameter to use. + /// Parameters are indexed from 0, with the return type + /// being the last 'parameter' + param_idx: u16, + }, } impl ObligationCauseCode<'_> { @@ -389,7 +421,7 @@ pub struct DerivedObligationCause<'tcx> { pub parent_trait_ref: ty::PolyTraitRef<'tcx>, /// The parent trait had this cause. - pub parent_code: Rc>, + pub parent_code: Lrc>, } #[derive(Clone, Debug, TypeFoldable, Lift)] @@ -426,10 +458,10 @@ pub type SelectionResult<'tcx, T> = Result, SelectionError<'tcx>>; /// impl Clone for i32 { ... } // Impl_3 /// /// fn foo(concrete: Option>, param: T, mixed: Option) { -/// // Case A: Vtable points at a specific impl. Only possible when +/// // Case A: ImplSource points at a specific impl. Only possible when /// // type is concretely known. If the impl itself has bounded -/// // type parameters, Vtable will carry resolutions for those as well: -/// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])]) +/// // type parameters, ImplSource will carry resolutions for those as well: +/// concrete.clone(); // ImpleSource(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 diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index d005f63ed4..2d17755166 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -124,7 +124,7 @@ impl<'tcx> AssocItems<'tcx> { &self, name: Symbol, ) -> impl '_ + Iterator { - self.items.get_by_key(&name).copied() + self.items.get_by_key(name).copied() } /// Returns an iterator over all associated items with the given name. diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 0706a057dd..6b51adc6aa 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -281,11 +281,10 @@ pub struct CaptureInfo<'tcx> { } pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String { - let name = match place.base { + let mut curr_string: String = match place.base { HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), }; - let mut curr_string = name; for (i, proj) in place.projections.iter().enumerate() { match proj.kind { @@ -314,7 +313,7 @@ pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> } } - curr_string.to_string() + curr_string } #[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)] @@ -347,7 +346,7 @@ pub enum BorrowKind { /// an `&mut` borrow: /// /// ``` - /// struct Env { x: & &mut isize } + /// struct Env { x: &mut &mut isize } /// let x: &mut isize = ...; /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x /// fn fn_ptr(env: &mut Env) { **env.x += 5; } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 8ed8ea6a0b..8262bc2619 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -1,7 +1,7 @@ use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use rustc_target::abi::{Size, TargetDataLayout}; +use rustc_target::abi::Size; use std::convert::{TryFrom, TryInto}; use std::fmt; @@ -193,15 +193,6 @@ impl ScalarInt { self.data == 0 } - pub(crate) fn ptr_sized_op( - self, - dl: &TargetDataLayout, - f_int: impl FnOnce(u64) -> Result, - ) -> Result { - assert_eq!(u64::from(self.size), dl.pointer_size.bytes()); - Ok(Self::try_from_uint(f_int(u64::try_from(self.data).unwrap())?, self.size()).unwrap()) - } - #[inline] pub fn try_from_uint(i: impl Into, size: Size) -> Option { let data = i.into(); diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 875d8d00a9..f2db95d162 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,7 +1,6 @@ use std::convert::TryInto; -use crate::mir::interpret::ConstValue; -use crate::mir::interpret::Scalar; +use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::mir::Promoted; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; @@ -59,7 +58,7 @@ impl<'tcx> ConstKind<'tcx> { } #[inline] - pub fn try_to_scalar(self) -> Option { + pub fn try_to_scalar(self) -> Option> { self.try_to_value()?.try_to_scalar() } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 73991436b7..4ce4903239 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,32 +1,30 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::DepGraph; -use crate::hir::exports::ExportMap; +use crate::dep_graph::{DepGraph, DepNode}; use crate::hir::place::Place as HirPlace; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; use crate::middle; -use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata}; +use crate::middle::cstore::EncodedMetadata; use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; +use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar}; use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::thir::Thir; use crate::traits; -use crate::ty::query::{self, OnDiskCache, TyCtxtAt}; +use crate::ty::query::{self, TyCtxtAt}; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts}; use crate::ty::TyKind::*; use crate::ty::{ - self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, - DefIdTree, ExistentialPredicate, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferConst, - InferTy, IntTy, IntVar, IntVid, List, MainDefinition, ParamConst, ParamTy, PolyFnSig, - Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, ReprOptions, - TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, Visibility, + self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, + ClosureSizeProfileData, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar, + FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, ParamConst, + ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, + ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, }; use rustc_ast as ast; -use rustc_ast::expand::allocator::AllocatorKind; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::SelfProfilerRef; @@ -39,11 +37,11 @@ use rustc_errors::ErrorReported; 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::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ - Constness, HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate, + Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, + Node, TraitCandidate, TraitItemKind, }; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; @@ -52,9 +50,10 @@ use rustc_middle::ty::OpaqueTypeKey; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; use rustc_session::lint::{Level, Lint}; +use rustc_session::Limit; use rustc_session::Session; -use rustc_span::def_id::StableCrateId; -use rustc_span::source_map::MultiSpan; +use rustc_span::def_id::{DefPathHash, StableCrateId}; +use rustc_span::source_map::{MultiSpan, SourceMap}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; @@ -72,6 +71,40 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; +pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { + /// Creates a new `OnDiskCache` instance from the serialized data in `data`. + fn new(sess: &'tcx Session, data: Vec, start_pos: usize) -> Self + where + Self: Sized; + + fn new_empty(source_map: &'tcx SourceMap) -> Self + where + Self: Sized; + + /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation + /// session, if it still exists. This is used during incremental compilation to + /// turn a deserialized `DefPathHash` into its current `DefId`. + fn def_path_hash_to_def_id( + &self, + tcx: TyCtxt<'tcx>, + def_path_hash: DefPathHash, + ) -> Option; + + /// If the given `dep_node`'s hash still exists in the current compilation, + /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it. + /// + /// Normally, `store_foreign_def_id_hash` can be called directly by + /// the dependency graph when we construct a `DepNode`. However, + /// when we re-use a deserialized `DepNode` from the previous compilation + /// session, we only have the `DefPathHash` available. This method is used + /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written + /// out for usage in the next compilation session. + fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode); + fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash); + + fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult; +} + /// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s /// except through the error-reporting functions on a [`tcx`][TyCtxt]. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] @@ -392,6 +425,34 @@ pub struct TypeckResults<'tcx> { /// (including late-bound regions) are replaced with free /// equivalents. This table is not used in codegen (since regions /// are erased there) and hence is not serialized to metadata. + /// + /// This table also contains the "revealed" values for any `impl Trait` + /// that appear in the signature and whose values are being inferred + /// by this function. + /// + /// # Example + /// + /// ```rust + /// fn foo(x: &u32) -> impl Debug { *x } + /// ``` + /// + /// The function signature here would be: + /// + /// ``` + /// for<'a> fn(&'a u32) -> Foo + /// ``` + /// + /// where `Foo` is an opaque type created for this function. + /// + /// + /// The *liberated* form of this would be + /// + /// ``` + /// fn(&'a u32) -> u32 + /// ``` + /// + /// Note that `'a` is not bound (it would be an `ReFree`) and + /// that the `Foo` opaque type is replaced by its hidden type. liberated_fn_sigs: ItemLocalMap>, /// For each FRU expression, record the normalized types of the fields @@ -455,6 +516,10 @@ pub struct TypeckResults<'tcx> { /// This hashset records all instances where we behave /// like this to allow `const_to_pat` to reliably handle this situation. pub treat_byte_string_as_slice: ItemLocalSet, + + /// Contains the data for evaluating the effect of feature `capture_disjoint_fields` + /// on closure size. + pub closure_size_eval: FxHashMap>, } impl<'tcx> TypeckResults<'tcx> { @@ -481,6 +546,7 @@ impl<'tcx> TypeckResults<'tcx> { closure_fake_reads: Default::default(), generator_interior_types: ty::Binder::dummy(Default::default()), treat_byte_string_as_slice: Default::default(), + closure_size_eval: Default::default(), } } @@ -725,6 +791,7 @@ impl<'a, 'tcx> HashStable> for TypeckResults<'tcx> { ref closure_fake_reads, ref generator_interior_types, ref treat_byte_string_as_slice, + ref closure_size_eval, } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { @@ -751,6 +818,7 @@ impl<'a, 'tcx> HashStable> for TypeckResults<'tcx> { closure_fake_reads.hash_stable(hcx, hasher); generator_interior_types.hash_stable(hcx, hasher); treat_byte_string_as_slice.hash_stable(hcx, hasher); + closure_size_eval.hash_stable(hcx, hasher); }) } } @@ -929,8 +997,6 @@ pub struct GlobalCtxt<'tcx> { interners: CtxtInterners<'tcx>, - pub(crate) cstore: Box, - pub sess: &'tcx Session, /// This only ever stores a `LintStore` but we don't want a dependency on that type here. @@ -952,36 +1018,20 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, - /// Visibilities produced by resolver. - pub visibilities: FxHashMap, - - /// Resolutions of `extern crate` items produced by resolver. - extern_crate_map: FxHashMap, - - /// Export map produced by name resolution. - export_map: ExportMap, + /// Output of the resolver. + pub(crate) untracked_resolutions: ty::ResolverOutputs, pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, - pub(crate) definitions: Definitions, /// This provides access to the incremental compilation on-disk cache for query results. /// Do not access this directly. It is only meant to be used by /// `DepGraph::try_mark_green()` and the query infrastructure. /// This is `None` if we are not incremental compilation mode - pub on_disk_cache: Option>, + pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, pub queries: &'tcx dyn query::QueryEngine<'tcx>, pub query_caches: query::QueryCaches<'tcx>, - maybe_unused_trait_imports: FxHashSet, - maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, - /// A map of glob use to a set of names it actually imports. Currently only - /// used in save-analysis. - pub(crate) glob_map: FxHashMap>, - /// Extern prelude entries. The value is `true` if the entry was introduced - /// via `extern crate` item and not `--extern` option or compiler built-in. - pub extern_prelude: FxHashMap, - // Internal caches for metadata decoding. No need to track deps on this. pub ty_rcache: Lock>>, pub pred_rcache: Lock>>, @@ -1015,7 +1065,8 @@ pub struct GlobalCtxt<'tcx> { output_filenames: Arc, - pub main_def: Option, + pub(super) vtables_cache: + Lock, Option>), AllocId>>, } impl<'tcx> TyCtxt<'tcx> { @@ -1124,7 +1175,7 @@ impl<'tcx> TyCtxt<'tcx> { resolutions: ty::ResolverOutputs, krate: &'tcx hir::Crate<'tcx>, dep_graph: DepGraph, - on_disk_cache: Option>, + on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, crate_name: &str, output_filenames: OutputFilenames, @@ -1136,28 +1187,19 @@ impl<'tcx> TyCtxt<'tcx> { let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); - let cstore = resolutions.cstore; GlobalCtxt { sess: s, lint_store, - cstore, arena, interners, dep_graph, + untracked_resolutions: resolutions, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, consts: common_consts, - visibilities: resolutions.visibilities, - extern_crate_map: resolutions.extern_crate_map, - export_map: resolutions.export_map, - maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, - maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates, - glob_map: resolutions.glob_map, - extern_prelude: resolutions.extern_prelude, untracked_crate: krate, - definitions: resolutions.definitions, on_disk_cache, queries, query_caches: query::QueryCaches::default(), @@ -1172,7 +1214,7 @@ impl<'tcx> TyCtxt<'tcx> { const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), - main_def: resolutions.main_def, + vtables_cache: Default::default(), } } @@ -1227,20 +1269,17 @@ impl<'tcx> TyCtxt<'tcx> { self.stability_index(()) } - pub fn crates(self) -> &'tcx [CrateNum] { - self.all_crate_nums(()) - } - - pub fn allocator_kind(self) -> Option { - self.cstore.allocator_kind() - } - pub fn features(self) -> &'tcx rustc_feature::Features { self.features_query(()) } pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey { - if let Some(id) = id.as_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) } + // Accessing the DefKey is ok, since it is part of DefPathHash. + if let Some(id) = id.as_local() { + self.untracked_resolutions.definitions.def_key(id) + } else { + self.untracked_resolutions.cstore.def_key(id) + } } /// Converts a `DefId` into its fully expanded `DefPath` (every @@ -1249,74 +1288,91 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that if `id` is not local to this crate, the result will /// be a non-local `DefPath`. pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath { + // Accessing the DefPath is ok, since it is part of DefPathHash. if let Some(id) = id.as_local() { - self.hir().def_path(id) + self.untracked_resolutions.definitions.def_path(id) } else { - self.cstore.def_path(id) + self.untracked_resolutions.cstore.def_path(id) } } #[inline] pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash { + // Accessing the DefPathHash is ok, it is incr. comp. stable. if let Some(def_id) = def_id.as_local() { - self.definitions.def_path_hash(def_id) + self.untracked_resolutions.definitions.def_path_hash(def_id) } else { - self.cstore.def_path_hash(def_id) + self.untracked_resolutions.cstore.def_path_hash(def_id) } } #[inline] - pub fn stable_crate_id(self, cnum: CrateNum) -> StableCrateId { - self.def_path_hash(cnum.as_def_id()).stable_crate_id() + pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId { + if crate_num == LOCAL_CRATE { + self.sess.local_stable_crate_id() + } else { + self.untracked_resolutions.cstore.stable_crate_id(crate_num) + } } pub fn def_path_debug_str(self, def_id: DefId) -> String { // We are explicitly not going through queries here in order to get - // crate name and disambiguator since this code is called from debug!() + // crate name and stable crate id since this code is called from debug!() // statements within the query system and we'd run into endless // recursion otherwise. - let (crate_name, crate_disambiguator) = if def_id.is_local() { - (self.crate_name, self.sess.local_crate_disambiguator()) + let (crate_name, stable_crate_id) = if def_id.is_local() { + (self.crate_name, self.sess.local_stable_crate_id()) } else { - ( - self.cstore.crate_name_untracked(def_id.krate), - self.cstore.crate_disambiguator_untracked(def_id.krate), - ) + let cstore = &self.untracked_resolutions.cstore; + (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; format!( "{}[{}]{}", crate_name, - // Don't print the whole crate disambiguator. That's just + // Don't print the whole stable crate id. That's just // annoying in debug output. - &(crate_disambiguator.to_fingerprint().to_hex())[..4], + &(format!("{:08x}", stable_crate_id.to_u64()))[..4], self.def_path(def_id).to_string_no_crate_verbose() ) } pub fn encode_metadata(self) -> EncodedMetadata { let _prof_timer = self.prof.verbose_generic_activity("generate_crate_metadata"); - self.cstore.encode_metadata(self) + self.untracked_resolutions.cstore.encode_metadata(self) } - // Note that this is *untracked* and should only be used within the query - // system if the result is otherwise tracked through queries - pub fn cstore_as_any(self) -> &'tcx dyn Any { - self.cstore.as_any() + /// Note that this is *untracked* and should only be used within the query + /// system if the result is otherwise tracked through queries + pub fn cstore_untracked(self) -> &'tcx ty::CrateStoreDyn { + &*self.untracked_resolutions.cstore + } + + /// Note that this is *untracked* and should only be used within the query + /// system if the result is otherwise tracked through queries + pub fn definitions_untracked(self) -> &'tcx hir::definitions::Definitions { + &self.untracked_resolutions.definitions } #[inline(always)] pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { let krate = self.gcx.untracked_crate; + let resolutions = &self.gcx.untracked_resolutions; - StableHashingContext::new(self.sess, krate, &self.definitions, &*self.cstore) + StableHashingContext::new(self.sess, krate, &resolutions.definitions, &*resolutions.cstore) } #[inline(always)] pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> { let krate = self.gcx.untracked_crate; + let resolutions = &self.gcx.untracked_resolutions; - StableHashingContext::ignore_spans(self.sess, krate, &self.definitions, &*self.cstore) + StableHashingContext::ignore_spans( + self.sess, + krate, + &resolutions.definitions, + &*resolutions.cstore, + ) } pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult { @@ -1470,18 +1526,14 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> { - // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`. + // `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures. let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); match self.hir().get(hir_id) { - Node::Item(item) => { - match item.kind { - ItemKind::Fn(..) => { /* `type_of_def_id()` will work */ } - _ => { - return None; - } - } - } - _ => { /* `type_of_def_id()` will work or panic */ } + Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {} + Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {} + Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {} + Node::Expr(&hir::Expr { kind: ExprKind::Closure(..), .. }) => {} + _ => return None, } let ret_ty = self.type_of(scope_def_id); @@ -1541,6 +1593,22 @@ impl<'tcx> TyCtxt<'tcx> { def_kind => (def_kind.article(), def_kind.descr(def_id)), } } + + pub fn type_length_limit(self) -> Limit { + self.limits(()).type_length_limit + } + + pub fn recursion_limit(self) -> Limit { + self.limits(()).recursion_limit + } + + pub fn move_size_limit(self) -> Limit { + self.limits(()).move_size_limit + } + + pub fn const_eval_limit(self) -> Limit { + self.limits(()).const_eval_limit + } } /// A trait implemented for all `X<'a>` types that can be safely and @@ -1614,7 +1682,7 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} -CloneLiftImpls! { for<'tcx> { Constness, } } +CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } } pub mod tls { use super::{ptr_eq, GlobalCtxt, TyCtxt}; @@ -2772,15 +2840,19 @@ fn ptr_eq(t: *const T, u: *const U) -> bool { pub fn provide(providers: &mut ty::query::Providers) { providers.in_scope_traits_map = |tcx, id| tcx.hir_crate(()).trait_map.get(&id); - providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).map(|v| &v[..]); + providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; + providers.module_exports = |tcx, id| tcx.resolutions(()).export_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { assert_eq!(id, LOCAL_CRATE); tcx.crate_name }; - providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id); - providers.maybe_unused_extern_crates = |tcx, ()| &tcx.maybe_unused_extern_crates[..]; - providers.names_imported_by_glob_use = - |tcx, id| tcx.arena.alloc(tcx.glob_map.get(&id).cloned().unwrap_or_default()); + providers.maybe_unused_trait_import = + |tcx, id| tcx.resolutions(()).maybe_unused_trait_imports.contains(&id); + providers.maybe_unused_extern_crates = + |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..]; + providers.names_imported_by_glob_use = |tcx, id| { + tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default()) + }; providers.lookup_stability = |tcx, id| { let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); @@ -2794,8 +2866,8 @@ pub fn provide(providers: &mut ty::query::Providers) { let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); tcx.stability().local_deprecation_entry(id) }; - providers.extern_mod_stmt_cnum = |tcx, id| tcx.extern_crate_map.get(&id).cloned(); - providers.all_crate_nums = |tcx, ()| tcx.arena.alloc_slice(&tcx.cstore.crates_untracked()); + providers.extern_mod_stmt_cnum = + |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); providers.output_filenames = |tcx, ()| tcx.output_filenames.clone(); providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index eb6d163312..a40210d5a3 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -754,88 +754,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -pub struct BoundVarsCollector<'tcx> { - binder_index: ty::DebruijnIndex, - vars: BTreeMap, - // We may encounter the same variable at different levels of binding, so - // this can't just be `Ty` - visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, -} - -impl<'tcx> BoundVarsCollector<'tcx> { - pub fn new() -> Self { - BoundVarsCollector { - binder_index: ty::INNERMOST, - vars: BTreeMap::new(), - visited: SsoHashSet::default(), - } - } - - pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List { - let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0); - for i in 0..max { - if let None = self.vars.get(&i) { - panic!("Unknown variable: {:?}", i); - } - } - - tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v)) - } -} - -impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - type BreakTy = (); - - fn visit_binder>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { - self.binder_index.shift_in(1); - let result = t.super_visit_with(self); - self.binder_index.shift_out(1); - result - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - if t.outer_exclusive_binder < self.binder_index - || !self.visited.insert((self.binder_index, t)) - { - return ControlFlow::CONTINUE; - } - use std::collections::btree_map::Entry; - match *t.kind() { - ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { - match self.vars.entry(bound_ty.var.as_u32()) { - Entry::Vacant(entry) => { - entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind)); - } - Entry::Occupied(entry) => match entry.get() { - ty::BoundVariableKind::Ty(_) => {} - _ => bug!("Conflicting bound vars"), - }, - } - } - - _ => (), - }; - - t.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - match r { - ty::ReLateBound(index, _br) if *index == self.binder_index => { - // If you hit this, you should be using `Binder::bind_with_vars` or `Binder::rebind` - bug!("Trying to collect bound vars with a bound region: {:?} {:?}", index, _br) - } - - _ => (), - }; - - r.super_visit_with(self) - } -} - pub struct ValidateBoundVars<'tcx> { bound_vars: &'tcx ty::List, binder_index: ty::DebruijnIndex, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 41d953216e..261a19f862 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -227,8 +227,9 @@ impl<'tcx> InstanceDef<'tcx> { pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { match *self { - InstanceDef::Item(def) => { - tcx.codegen_fn_attrs(def.did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) + InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. }) + | InstanceDef::Virtual(def_id, _) => { + tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } _ => false, } @@ -403,7 +404,7 @@ impl<'tcx> Instance<'tcx> { def_id: DefId, substs: SubstsRef<'tcx>, ) -> Option> { - debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); + debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs); let fn_sig = tcx.fn_sig(def_id); let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty() && fn_sig.input(0).skip_binder().is_param(0) @@ -412,7 +413,50 @@ impl<'tcx> Instance<'tcx> { debug!(" => associated item with unsizeable self: Self"); Some(Instance { def: InstanceDef::VtableShim(def_id), substs }) } else { - Instance::resolve_for_fn_ptr(tcx, param_env, def_id, substs) + Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| { + match resolved.def { + InstanceDef::Item(def) => { + // We need to generate a shim when we cannot guarantee that + // the caller of a trait object method will be aware of + // `#[track_caller]` - this ensures that the caller + // and callee ABI will always match. + // + // The shim is generated when all of these conditions are met: + // + // 1) The underlying method expects a caller location parameter + // in the ABI + if resolved.def.requires_caller_location(tcx) + // 2) The caller location parameter comes from having `#[track_caller]` + // on the implementation, and *not* on the trait method. + && !tcx.should_inherit_track_caller(def.did) + // If the method implementation comes from the trait definition itself + // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`), + // then we don't need to generate a shim. This check is needed because + // `should_inherit_track_caller` returns `false` if our method + // implementation comes from the trait block, and not an impl block + && !matches!( + tcx.opt_associated_item(def.did), + Some(ty::AssocItem { + container: ty::AssocItemContainer::TraitContainer(_), + .. + }) + ) + { + debug!( + " => vtable fn pointer created for function with #[track_caller]" + ); + resolved.def = InstanceDef::ReifyShim(def.did); + } + } + InstanceDef::Virtual(def_id, _) => { + debug!(" => vtable fn pointer created for virtual call"); + resolved.def = InstanceDef::ReifyShim(def_id); + } + _ => {} + } + + resolved + }) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 28a44b09de..95ea38d32b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -221,7 +221,7 @@ fn layout_raw<'tcx>( ty::tls::with_related_context(tcx, move |icx| { let (param_env, ty) = query.into_parts(); - if !tcx.sess.recursion_limit().value_within_limit(icx.layout_depth) { + if !tcx.recursion_limit().value_within_limit(icx.layout_depth) { tcx.sess.fatal(&format!("overflow representing the type `{}`", ty)); } @@ -312,7 +312,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let dl = self.data_layout(); let pack = repr.pack; if pack.is_some() && repr.align.is_some() { - bug!("struct cannot be packed and aligned"); + 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 }; @@ -672,6 +673,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // 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); @@ -799,7 +809,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if def.is_union() { if def.repr.pack.is_some() && def.repr.align.is_some() { - bug!("union cannot be packed and aligned"); + 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 = @@ -2469,9 +2483,10 @@ impl<'tcx> ty::Instance<'tcx> { // `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 + ty::FnDef(def_id, substs) if tcx.sess.opts.debugging_opts.polymorphize => tcx .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id)) .subst(tcx, substs), + ty::FnDef(def_id, substs) => tcx.fn_sig(def_id).subst(tcx, substs), _ => unreachable!(), }; diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 44dfcbf186..1dceda6c7a 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -63,17 +63,17 @@ impl List { let (layout, _offset) = Layout::new::().extend(Layout::for_value::<[T]>(slice)).unwrap(); - let mem = arena.dropless.alloc_raw(layout); + let mem = arena.dropless.alloc_raw(layout) as *mut List; unsafe { - let result = &mut *(mem as *mut List); // Write the length - result.len = slice.len(); + ptr::addr_of_mut!((*mem).len).write(slice.len()); // Write the elements - let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len); - arena_slice.copy_from_slice(slice); + ptr::addr_of_mut!((*mem).data) + .cast::() + .copy_from_nonoverlapping(slice.as_ptr(), slice.len()); - result + &mut *mem } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 227aa8dc28..a6aff42479 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -18,6 +18,7 @@ pub use adt::*; pub use assoc::*; pub use closure::*; pub use generics::*; +pub use vtable::*; use crate::hir::exports::ExportMap; use crate::ich::StableHashingContext; @@ -58,7 +59,7 @@ pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Uneval pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, - Lift, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex, + Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex, }; pub use self::instance::{Instance, InstanceDef}; pub use self::list::List; @@ -94,6 +95,7 @@ pub mod relate; pub mod subst; pub mod trait_def; pub mod util; +pub mod vtable; pub mod walk; mod adt; @@ -111,6 +113,7 @@ mod sty; // Data types +#[derive(Debug)] pub struct ResolverOutputs { pub definitions: rustc_hir::definitions::Definitions, pub cstore: Box, @@ -126,7 +129,7 @@ pub struct ResolverOutputs { pub main_def: Option, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct MainDefinition { pub res: Res, pub is_import: bool, @@ -173,6 +176,25 @@ pub enum Visibility { Invisible, } +#[derive( + Clone, + Debug, + PartialEq, + Eq, + Copy, + Hash, + TyEncodable, + TyDecodable, + HashStable, + TypeFoldable +)] +pub struct ClosureSizeProfileData<'tcx> { + /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` + pub before_feature_tys: Ty<'tcx>, + /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields` + pub after_feature_tys: Ty<'tcx>, +} + pub trait DefIdTree: Copy { fn parent(self, id: DefId) -> Option; @@ -835,7 +857,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, TypeFoldable)] pub struct OpaqueTypeKey<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, @@ -1881,13 +1903,11 @@ impl<'tcx> TyCtxt<'tcx> { scope: DefId, block: hir::HirId, ) -> (Ident, DefId) { - let scope = - match ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) { - Some(actual_expansion) => { - self.hir().definitions().parent_module_of_macro_def(actual_expansion) - } - None => self.parent_module(block).to_def_id(), - }; + let scope = ident + .span + .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) + .and_then(|actual_expansion| actual_expansion.expn_data().parent_module) + .unwrap_or_else(|| self.parent_module(block).to_def_id()); (ident, scope) } @@ -1966,6 +1986,7 @@ pub fn provide(providers: &mut ty::query::Providers) { util::provide(providers); print::provide(providers); super::util::bug::provide(providers); + super::middle::provide(providers); *providers = ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, type_uninhabited_from: inhabitedness::type_uninhabited_from, diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index a4f736654a..11399506b9 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -88,23 +88,32 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> { param_env: ty::ParamEnv<'tcx>, } +impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { + fn normalize_generic_arg_after_erasing_regions( + &self, + arg: ty::GenericArg<'tcx>, + ) -> ty::GenericArg<'tcx> { + let arg = self.param_env.and(arg); + self.tcx.normalize_generic_arg_after_erasing_regions(arg) + } +} + impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let arg = self.param_env.and(ty.into()); - self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_ty() + self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty() } fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let arg = self.param_env.and(c.into()); - self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const() + 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.normalize_mir_const_after_erasing_regions(arg) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 25557bdd10..b5733bd2ed 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,5 +1,5 @@ use crate::middle::cstore::{ExternCrate, ExternCrateSource}; -use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Scalar}; +use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; @@ -685,10 +685,10 @@ pub trait PrettyPrinter<'tcx>: self = self.comma_sep(substs.as_generator().upvar_tys())?; } p!(")"); - } - if substs.as_generator().is_valid() { - p!(" ", print(substs.as_generator().witness())); + if substs.as_generator().is_valid() { + p!(" ", print(substs.as_generator().witness())); + } } p!("]") @@ -974,7 +974,7 @@ pub trait PrettyPrinter<'tcx>: print_ty: bool, ) -> Result { match scalar { - Scalar::Ptr(ptr) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty), + Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty), Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty), } } @@ -987,6 +987,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); + let (alloc_id, offset) = ptr.into_parts(); match ty.kind() { // Byte strings (&[u8; N]) ty::Ref( @@ -1002,10 +1003,10 @@ pub trait PrettyPrinter<'tcx>: .. }, _, - ) => match self.tcx().get_global_alloc(ptr.alloc_id) { + ) => match self.tcx().get_global_alloc(alloc_id) { Some(GlobalAlloc::Memory(alloc)) => { let len = int.assert_bits(self.tcx().data_layout.pointer_size); - let range = AllocRange { start: ptr.offset, size: Size::from_bytes(len) }; + let range = AllocRange { start: offset, size: Size::from_bytes(len) }; if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), range) { p!(pretty_print_byte_str(byte_str)) } else { @@ -1020,7 +1021,7 @@ pub trait PrettyPrinter<'tcx>: ty::FnPtr(_) => { // FIXME: We should probably have a helper method to share code with the "Byte strings" // printing above (which also has to handle pointers to all sorts of things). - match self.tcx().get_global_alloc(ptr.alloc_id) { + match self.tcx().get_global_alloc(alloc_id) { Some(GlobalAlloc::Function(instance)) => { self = self.typed_value( |this| this.print_value_path(instance.def_id(), instance.substs), @@ -1068,8 +1069,8 @@ pub trait PrettyPrinter<'tcx>: ty::Char if char::try_from(int).is_ok() => { p!(write("{:?}", char::try_from(int).unwrap())) } - // Raw pointers - ty::RawPtr(_) | ty::FnPtr(_) => { + // Pointer types + ty::Ref(..) | ty::RawPtr(_) | ty::FnPtr(_) => { let data = int.assert_bits(self.tcx().data_layout.pointer_size); self = self.typed_value( |mut this| { @@ -1106,9 +1107,9 @@ pub trait PrettyPrinter<'tcx>: /// This is overridden for MIR printing because we only want to hide alloc ids from users, not /// from MIR where it is actually useful. - fn pretty_print_const_pointer( + fn pretty_print_const_pointer( mut self, - _: Pointer, + _: Pointer, ty: Ty<'tcx>, print_ty: bool, ) -> Result { @@ -1437,7 +1438,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } fn print_type(mut self, ty: Ty<'tcx>) -> Result { - let type_length_limit = self.tcx.sess.type_length_limit(); + let type_length_limit = self.tcx.type_length_limit(); if type_length_limit.value_within_limit(self.printed_type_count) { self.printed_type_count += 1; self.pretty_print_type(ty) @@ -1679,9 +1680,9 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { } } - fn pretty_print_const_pointer( + fn pretty_print_const_pointer( self, - p: Pointer, + p: Pointer, ty: Ty<'tcx>, print_ty: bool, ) -> Result { @@ -1775,13 +1776,73 @@ impl FmtPrinter<'_, '_, F> { } } +/// Folds through bound vars and placeholders, naming them +struct RegionFolder<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + current_index: ty::DebruijnIndex, + region_map: BTreeMap>, + name: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), +} + +impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match *t.kind() { + _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => { + return t.super_fold_with(self); + } + _ => {} + } + t + } + + 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::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 + match kind { + ty::BrAnon(_) | ty::BrEnv => r, + _ => { + // 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)) + } + } + } + _ => return r, + }; + if let ty::ReLateBound(debruijn1, br) = *region { + assert_eq!(debruijn1, ty::INNERMOST); + self.tcx.mk_region(ty::ReLateBound(self.current_index, br)) + } else { + region + } + } +} + // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, // `region_index` and `used_region_names`. impl FmtPrinter<'_, 'tcx, F> { pub fn name_all_regions( mut self, value: &ty::Binder<'tcx, T>, - ) -> Result<(Self, (T, BTreeMap>)), fmt::Error> + ) -> Result<(Self, T, BTreeMap>), fmt::Error> where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { @@ -1804,16 +1865,16 @@ impl FmtPrinter<'_, 'tcx, F> { let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - write!( - cx, - "{}", - if empty { - empty = false; - start - } else { - cont - } - ) + let w = if empty { + empty = false; + start + } else { + cont + }; + let _ = write!(cx, "{}", w); + }; + let do_continue = |cx: &mut Self, cont: Symbol| { + let _ = write!(cx, "{}", cont); }; define_scoped_cx!(self); @@ -1823,18 +1884,18 @@ impl FmtPrinter<'_, 'tcx, F> { // aren't named. Eventually, we might just want this as the default, but // this is not *quite* right and changes the ordering of some output // anyways. - let new_value = if self.tcx().sess.verbose() { + let (new_value, map) = if self.tcx().sess.verbose() { // anon index + 1 (BrEnv takes 0) -> name let mut region_map: BTreeMap = BTreeMap::default(); let bound_vars = value.bound_vars(); for var in bound_vars { match var { ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => { - let _ = start_or_continue(&mut self, "for<", ", "); - let _ = write!(self, "{}", name); + start_or_continue(&mut self, "for<", ", "); + do_continue(&mut self, name); } ty::BoundVariableKind::Region(ty::BrAnon(i)) => { - let _ = start_or_continue(&mut self, "for<", ", "); + start_or_continue(&mut self, "for<", ", "); let name = loop { let name = name_by_region_index(region_index); region_index += 1; @@ -1842,11 +1903,11 @@ impl FmtPrinter<'_, 'tcx, F> { break name; } }; - let _ = write!(self, "{}", name); + do_continue(&mut self, name); region_map.insert(i + 1, name); } ty::BoundVariableKind::Region(ty::BrEnv) => { - let _ = start_or_continue(&mut self, "for<", ", "); + start_or_continue(&mut self, "for<", ", "); let name = loop { let name = name_by_region_index(region_index); region_index += 1; @@ -1854,13 +1915,13 @@ impl FmtPrinter<'_, 'tcx, F> { break name; } }; - let _ = write!(self, "{}", name); + do_continue(&mut self, name); region_map.insert(0, name); } _ => continue, } } - start_or_continue(&mut self, "", "> ")?; + start_or_continue(&mut self, "", "> "); self.tcx.replace_late_bound_regions(value.clone(), |br| { let kind = match br.kind { @@ -1880,11 +1941,12 @@ impl FmtPrinter<'_, 'tcx, F> { )) }) } else { - let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| { - let _ = start_or_continue(&mut self, "for<", ", "); + let tcx = self.tcx; + let mut name = |br: ty::BoundRegion| { + start_or_continue(&mut self, "for<", ", "); let kind = match br.kind { ty::BrNamed(_, name) => { - let _ = write!(self, "{}", name); + do_continue(&mut self, name); br.kind } ty::BrAnon(_) | ty::BrEnv => { @@ -1895,22 +1957,27 @@ impl FmtPrinter<'_, 'tcx, F> { break name; } }; - let _ = write!(self, "{}", name); + do_continue(&mut self, name); ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) } }; - self.tcx.mk_region(ty::ReLateBound( - ty::INNERMOST, - ty::BoundRegion { var: br.var, kind }, - )) - }); - start_or_continue(&mut self, "", "> ")?; - new_value + tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })) + }; + let mut folder = RegionFolder { + tcx, + current_index: ty::INNERMOST, + name: &mut name, + region_map: BTreeMap::new(), + }; + let new_value = value.clone().skip_binder().fold_with(&mut folder); + let region_map = folder.region_map; + start_or_continue(&mut self, "", "> "); + (new_value, region_map) }; self.binder_depth += 1; self.region_index = region_index; - Ok((self, new_value)) + Ok((self, new_value, map)) } pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result @@ -1918,8 +1985,8 @@ impl FmtPrinter<'_, 'tcx, F> { T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { let old_region_index = self.region_index; - let (new, new_value) = self.name_all_regions(value)?; - let mut inner = new_value.0.print(new)?; + let (new, new_value, _) = self.name_all_regions(value)?; + let mut inner = new_value.print(new)?; inner.region_index = old_region_index; inner.binder_depth -= 1; Ok(inner) @@ -1934,8 +2001,8 @@ impl FmtPrinter<'_, 'tcx, F> { T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { let old_region_index = self.region_index; - let (new, new_value) = self.name_all_regions(value)?; - let mut inner = f(&new_value.0, new)?; + let (new, new_value, _) = self.name_all_regions(value)?; + let mut inner = f(&new_value, new)?; inner.region_index = old_region_index; inner.binder_depth -= 1; Ok(inner) @@ -1959,6 +2026,12 @@ impl FmtPrinter<'_, 'tcx, F> { debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r); if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { self.used_region_names.insert(name); + } else if let ty::RePlaceholder(ty::PlaceholderRegion { + name: ty::BrNamed(_, name), + .. + }) = *r + { + self.used_region_names.insert(name); } r.super_visit_with(self) } @@ -2248,7 +2321,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N let queue = &mut Vec::new(); let mut seen_defs: DefIdSet = Default::default(); - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; // Ignore crates that are not direct dependencies. @@ -2313,7 +2386,7 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option> = &mut FxHashMap::default(); - for symbol_set in tcx.glob_map.values() { + for symbol_set in tcx.resolutions(()).glob_map.values() { for symbol in symbol_set { unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None); unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None); diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query.rs similarity index 91% rename from compiler/rustc_middle/src/ty/query/mod.rs rename to compiler/rustc_middle/src/ty/query.rs index 297110ee3e..15a8888ee6 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -33,21 +33,21 @@ use crate::traits::{self, ImplSource}; use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; +use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; -use rustc_errors::{ErrorReported, Handler}; +use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; -use rustc_serialize::opaque; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::utils::NativeLibKind; -use rustc_session::CrateDisambiguator; +use rustc_session::Limits; use rustc_target::spec::PanicStrategy; use rustc_ast as ast; @@ -62,9 +62,6 @@ use std::sync::Arc; pub(crate) use rustc_query_system::query::QueryJobId; use rustc_query_system::query::*; -pub mod on_disk_cache; -pub use self::on_disk_cache::OnDiskCache; - #[derive(Copy, Clone)] pub struct TyCtxtAt<'tcx> { pub tcx: TyCtxt<'tcx>, @@ -234,28 +231,10 @@ macro_rules! define_callbacks { } pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync { - #[cfg(parallel_compiler)] - unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry); - - fn encode_query_results( - &'tcx self, - tcx: TyCtxt<'tcx>, - encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>, - query_result_index: &mut on_disk_cache::EncodedQueryResultIndex, - ) -> opaque::FileEncodeResult; - - fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>); + fn as_any(&'tcx self) -> &'tcx dyn std::any::Any; fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool; - fn try_print_query_stack( - &'tcx self, - tcx: TyCtxt<'tcx>, - query: Option>, - handler: &Handler, - num_frames: Option, - ) -> usize; - $($(#[$attr])* fn $name( &'tcx self, diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 3f426b1368..a4c36be219 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -595,9 +595,12 @@ fn check_const_value_eq>( (ConstValue::Scalar(Scalar::Int(a_val)), ConstValue::Scalar(Scalar::Int(b_val))) => { a_val == b_val } - (ConstValue::Scalar(Scalar::Ptr(a_val)), ConstValue::Scalar(Scalar::Ptr(b_val))) => { + ( + ConstValue::Scalar(Scalar::Ptr(a_val, _a_size)), + ConstValue::Scalar(Scalar::Ptr(b_val, _b_size)), + ) => { a_val == b_val - || match (tcx.global_alloc(a_val.alloc_id), tcx.global_alloc(b_val.alloc_id)) { + || match (tcx.global_alloc(a_val.provenance), tcx.global_alloc(b_val.provenance)) { (GlobalAlloc::Function(a_instance), GlobalAlloc::Function(b_instance)) => { a_instance == b_instance } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1d9ff51228..6a7e349819 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,7 +5,6 @@ use self::TyKind::*; use crate::infer::canonical::Canonical; -use crate::ty::fold::BoundVarsCollector; use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; @@ -966,17 +965,10 @@ where /// binder. This is commonly used to 'inject' a value T into a /// different binding level. pub fn dummy(value: T) -> Binder<'tcx, T> { - debug_assert!(!value.has_escaping_bound_vars()); + assert!(!value.has_escaping_bound_vars()); Binder(value, ty::List::empty()) } - /// Wraps `value` in a binder, binding higher-ranked vars (if any). - pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> { - let mut collector = BoundVarsCollector::new(); - value.visit_with(&mut collector); - Binder(value, collector.into_vars(tcx)) - } - pub fn bind_with_vars(value: T, vars: &'tcx List) -> Binder<'tcx, T> { if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(vars); @@ -1370,8 +1362,8 @@ pub type Region<'tcx> = &'tcx RegionKind; /// happen, you can use `leak_check`. This is more clearly explained /// by the [rustc dev guide]. /// -/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ -/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ +/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ +/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[derive(Clone, PartialEq, Eq, Hash, Copy, TyEncodable, TyDecodable, PartialOrd, Ord)] pub enum RegionKind { @@ -2189,7 +2181,7 @@ impl<'tcx> TyS<'tcx> { /// a miscompilation or unsoundness. /// /// When in doubt, use `VarianceDiagInfo::default()` -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum VarianceDiagInfo<'tcx> { /// No additional information - this is the default. /// We will not add any additional information to error messages. @@ -2208,7 +2200,7 @@ pub enum VarianceDiagInfo<'tcx> { }, } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum VarianceDiagMutKind { /// A mutable raw pointer (`*mut T`) RawPtr, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 79166472ac..ae86f51e6a 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -215,7 +215,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait // Traits defined in the current crate can't have impls in upstream // crates, so we don't bother querying the cstore. if !trait_id.is_local() { - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { for &(impl_def_id, simplified_self_ty) in tcx.implementations_of_trait((cnum, trait_id)).iter() { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7bf69b9e63..485be4c998 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -7,7 +7,7 @@ use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; use crate::ty::TyKind::*; -use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, DebruijnIndex, DefIdTree, List, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::Float as _; use rustc_ast as ast; use rustc_attr::{self as attr, SignedInt, UnsignedInt}; @@ -206,8 +206,9 @@ impl<'tcx> TyCtxt<'tcx> { mut ty: Ty<'tcx>, normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, ) -> Ty<'tcx> { + let recursion_limit = self.recursion_limit(); for iteration in 0.. { - if !self.sess.recursion_limit().value_within_limit(iteration) { + if !recursion_limit.value_within_limit(iteration) { return self.ty_error_with_message( DUMMY_SP, &format!("reached the recursion limit finding the struct tail for {}", ty), @@ -816,6 +817,15 @@ impl<'tcx> ty::TyS<'tcx> { [component_ty] => component_ty, _ => self, }; + + // FIXME(#86868): We should be canonicalizing, or else moving this to a method of inference + // context, or *something* like that, but for now just avoid passing inference + // variables to queries that can't cope with them. Instead, conservatively + // return "true" (may change drop order). + if query_ty.needs_infer() { + return true; + } + // This doesn't depend on regions, so try to minimize distinct // query keys used. let erased = tcx.normalize_erasing_regions(param_env, query_ty); @@ -905,6 +915,10 @@ impl<'tcx> ty::TyS<'tcx> { } ty } + + pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex { + self.outer_exclusive_binder + } } pub enum ExplicitSelf<'tcx> { diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs new file mode 100644 index 0000000000..78109fc7b5 --- /dev/null +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -0,0 +1,107 @@ +use std::convert::TryFrom; + +use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, ScalarMaybeUninit}; +use crate::ty::fold::TypeFoldable; +use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt}; +use rustc_ast::Mutability; + +#[derive(Clone, Copy, Debug, PartialEq, HashStable)] +pub enum VtblEntry<'tcx> { + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Vacant, + Method(DefId, SubstsRef<'tcx>), +} + +pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] = + &[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign]; + +pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0; +pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1; +pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; + +impl<'tcx> TyCtxt<'tcx> { + /// Retrieves an allocation that represents the contents of a vtable. + /// There's a cache within `TyCtxt` so it will be deduplicated. + pub fn vtable_allocation( + self, + ty: Ty<'tcx>, + poly_trait_ref: Option>, + ) -> AllocId { + let tcx = self; + let vtables_cache = tcx.vtables_cache.lock(); + if let Some(alloc_id) = vtables_cache.get(&(ty, poly_trait_ref)).cloned() { + return alloc_id; + } + drop(vtables_cache); + + // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674 + assert!( + !ty.needs_subst() && !poly_trait_ref.map_or(false, |trait_ref| trait_ref.needs_subst()) + ); + let param_env = ty::ParamEnv::reveal_all(); + let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { + let trait_ref = poly_trait_ref.with_self_ty(tcx, ty); + let trait_ref = tcx.erase_regions(trait_ref); + + tcx.vtable_entries(trait_ref) + } else { + COMMON_VTABLE_ENTRIES + }; + + let layout = + tcx.layout_of(param_env.and(ty)).expect("failed to build vtable representation"); + assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); + let size = layout.size.bytes(); + let align = layout.align.abi.bytes(); + + let ptr_size = tcx.data_layout.pointer_size; + let ptr_align = tcx.data_layout.pointer_align.abi; + + let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); + let mut vtable = + Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap(); + + // No need to do any alignment checks on the memory accesses below, because we know the + // allocation is correctly aligned as we created it above. Also we're only offsetting by + // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. + + for (idx, entry) in vtable_entries.iter().enumerate() { + let idx: u64 = u64::try_from(idx).unwrap(); + let scalar = match entry { + VtblEntry::MetadataDropInPlace => { + let instance = ty::Instance::resolve_drop_in_place(tcx, ty); + let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_ptr = Pointer::from(fn_alloc_id); + ScalarMaybeUninit::from_pointer(fn_ptr, &tcx) + } + VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(), + VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(), + VtblEntry::Vacant => continue, + VtblEntry::Method(def_id, substs) => { + // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674 + assert!(!substs.needs_subst()); + + // Prepare the fn ptr we write into the vtable. + let instance = + ty::Instance::resolve_for_vtable(tcx, param_env, *def_id, substs) + .expect("resolution failed during building vtable representation") + .polymorphize(tcx); + let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_ptr = Pointer::from(fn_alloc_id); + ScalarMaybeUninit::from_pointer(fn_ptr, &tcx) + } + }; + vtable + .write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar) + .expect("failed to build vtable representation"); + } + + vtable.mutability = Mutability::Not; + let alloc_id = tcx.create_memory_alloc(tcx.intern_const_alloc(vtable)); + let mut vtables_cache = self.vtables_cache.lock(); + vtables_cache.insert((ty, poly_trait_ref), alloc_id); + alloc_id + } +} diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 8b0761889b..2e854ea5be 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -9,10 +9,11 @@ use rustc_middle::mir::{ FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, }; -use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TypeFoldable}; +use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::sym; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_trait_selection::infer::InferCtxtExt; use crate::dataflow::drop_flag_effects; use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex}; @@ -65,7 +66,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.move_spans(moved_place, location).or_else(|| self.borrow_spans(span, location)); let span = use_spans.args_or_use(); - let move_site_vec = self.get_moved_indexes(location, mpi); + let (move_site_vec, maybe_reinitialized_locations) = self.get_moved_indexes(location, mpi); debug!( "report_use_of_moved_or_uninitialized: move_site_vec={:?} use_spans={:?}", move_site_vec, use_spans @@ -138,6 +139,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.describe_place_with_options(moved_place, IncludingDowncast(true)), ); + let reinit_spans = maybe_reinitialized_locations + .iter() + .take(3) + .map(|loc| { + self.move_spans(self.move_data.move_paths[mpi].place.as_ref(), *loc) + .args_or_use() + }) + .collect::>(); + let reinits = maybe_reinitialized_locations.len(); + if reinits == 1 { + err.span_label(reinit_spans[0], "this reinitialization might get skipped"); + } else if reinits > 1 { + err.span_note( + MultiSpan::from_spans(reinit_spans), + &if reinits <= 3 { + format!("these {} reinitializations might get skipped", reinits) + } else { + format!( + "these 3 reinitializations and {} other{} might get skipped", + reinits - 3, + if reinits == 4 { "" } else { "s" } + ) + }, + ); + } + self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; @@ -218,7 +245,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ), ); } - if is_option_or_result { + if is_option_or_result && maybe_reinitialized_locations.is_empty() { err.span_suggestion_verbose( fn_call_span.shrink_to_lo(), "consider calling `.as_ref()` to borrow the type's contents", @@ -259,19 +286,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - if let UseSpans::PatUse(span) = move_spans { - err.span_suggestion_verbose( - span.shrink_to_lo(), - &format!( - "borrow this field in the pattern to avoid moving {}", - self.describe_place(moved_place.as_ref()) - .map(|n| format!("`{}`", n)) - .unwrap_or_else(|| "the value".to_string()) - ), - "ref ".to_string(), - Applicability::MachineApplicable, - ); - in_pattern = true; + if let (UseSpans::PatUse(span), []) = + (move_spans, &maybe_reinitialized_locations[..]) + { + if maybe_reinitialized_locations.is_empty() { + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "borrow this field in the pattern to avoid moving {}", + self.describe_place(moved_place.as_ref()) + .map(|n| format!("`{}`", n)) + .unwrap_or_else(|| "the value".to_string()) + ), + "ref ".to_string(), + Applicability::MachineApplicable, + ); + in_pattern = true; + } } if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() { @@ -453,6 +484,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", Some(borrow_span), + None, ); err.buffer(&mut self.errors_buffer); } @@ -498,6 +530,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); err } @@ -718,6 +751,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, first_borrow_desc, None, + Some((issued_span, span)), ); err @@ -1076,6 +1110,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); } } else { @@ -1093,6 +1128,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); } @@ -1158,6 +1194,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); err.buffer(&mut self.errors_buffer); @@ -1236,6 +1273,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); let within = if borrow_spans.for_generator() { " by generator" } else { "" }; @@ -1322,18 +1360,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let return_ty = tcx.erase_regions(return_ty); // to avoid panics - if !return_ty.has_infer_types() { - if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) { - if tcx.type_implements_trait((iter_trait, return_ty, ty_params, self.param_env)) - { - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) { - err.span_suggestion_hidden( - return_span, - "use `.collect()` to allocate the iterator", - format!("{}{}", snippet, ".collect::>()"), - Applicability::MaybeIncorrect, - ); - } + if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) { + if self + .infcx + .type_implements_trait(iter_trait, return_ty, ty_params, self.param_env) + .must_apply_modulo_regions() + { + if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) { + err.span_suggestion_hidden( + return_span, + "use `.collect()` to allocate the iterator", + format!("{}{}", snippet, ".collect::>()"), + Applicability::MaybeIncorrect, + ); } } } @@ -1456,7 +1495,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err } - fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec { + fn get_moved_indexes( + &mut self, + location: Location, + mpi: MovePathIndex, + ) -> (Vec, Vec) { fn predecessor_locations( body: &'a mir::Body<'tcx>, location: Location, @@ -1479,6 +1522,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { })); let mut visited = FxHashSet::default(); + let mut move_locations = FxHashSet::default(); + let mut reinits = vec![]; let mut result = vec![]; 'dfs: while let Some((location, is_back_edge)) = stack.pop() { @@ -1520,6 +1565,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_paths[path].place ); result.push(MoveSite { moi: *moi, traversed_back_edge: is_back_edge }); + move_locations.insert(location); // Strictly speaking, we could continue our DFS here. There may be // other moves that can reach the point of error. But it is kind of @@ -1556,6 +1602,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, ); if any_match { + reinits.push(location); continue 'dfs; } @@ -1565,7 +1612,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { })); } - result + // Check if we can reach these reinits from a move location. + let reinits_reachable = reinits + .into_iter() + .filter(|reinit| { + let mut visited = FxHashSet::default(); + let mut stack = vec![*reinit]; + while let Some(location) = stack.pop() { + if !visited.insert(location) { + continue; + } + if move_locations.contains(&location) { + return true; + } + stack.extend(predecessor_locations(self.body, location)); + } + false + }) + .collect::>(); + (result, reinits_reachable) } pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed( @@ -1614,6 +1679,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); self.explain_deref_coercion(loan, &mut err); diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs index e9f1ecb9bb..76de010d13 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs @@ -66,6 +66,7 @@ impl BorrowExplanation { err: &mut DiagnosticBuilder<'_>, borrow_desc: &str, borrow_span: Option, + multiple_borrow_span: Option<(Span, Span)>, ) { match *self { BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => { @@ -192,14 +193,23 @@ impl BorrowExplanation { if let Some(info) = &local_decl.is_block_tail { if info.tail_result_is_ignored { - err.span_suggestion_verbose( - info.span.shrink_to_hi(), - "consider adding semicolon after the expression so its \ - temporaries are dropped sooner, before the local variables \ - declared by the block are dropped", - ";".to_string(), - Applicability::MaybeIncorrect, - ); + // #85581: If the first mutable borrow's scope contains + // the second borrow, this suggestion isn't helpful. + if !multiple_borrow_span + .map(|(old, new)| { + old.to(info.span.shrink_to_hi()).contains(new) + }) + .unwrap_or(false) + { + err.span_suggestion_verbose( + info.span.shrink_to_hi(), + "consider adding semicolon after the expression so its \ + temporaries are dropped sooner, before the local variables \ + declared by the block are dropped", + ";".to_string(), + Applicability::MaybeIncorrect, + ); + } } else { err.note( "the temporary is part of an expression at the end of a \ diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs index bf5f2c0eec..671d947d1b 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(desc) = access_place_desc { item_msg = format!("`{}`", desc); reason = match error_access { - AccessKind::Mutate => format!(" which is behind {}", pointer_type), + AccessKind::Mutate => format!(", which is behind {}", pointer_type), AccessKind::MutableBorrow => { format!(", as it is behind {}", pointer_type) } @@ -897,16 +897,32 @@ fn suggest_ampmut<'tcx>( ) -> (Span, String) { if let Some(assignment_rhs_span) = opt_assignment_rhs_span { if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { + let is_mutbl = |ty: &str| -> bool { + if ty.starts_with("mut") { + let rest = &ty[3..]; + match rest.chars().next() { + // e.g. `&mut x` + Some(c) if c.is_whitespace() => true, + // e.g. `&mut(x)` + Some('(') => true, + // e.g. `&mutablevar` + _ => false, + } + } else { + false + } + }; if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() })) { let lt_name = &src[1..ws_pos]; - let ty = &src[ws_pos..]; - if !ty.trim_start().starts_with("mut") { + let ty = src[ws_pos..].trim_start(); + if !is_mutbl(ty) { return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty)); } } else if let Some(stripped) = src.strip_prefix('&') { - if !stripped.trim_start().starts_with("mut") { + let stripped = stripped.trim_start(); + if !is_mutbl(stripped) { return (assignment_rhs_span, format!("&mut {}", stripped)); } } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs index feb7672f65..1460c2378d 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym}; -use rustc_span::Span; +use rustc_span::{BytePos, Span}; use crate::util::borrowck_errors; @@ -641,12 +641,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { "'_".to_string() }; - let suggestion = if snippet.ends_with(';') { + let span = if snippet.ends_with(';') { // `type X = impl Trait;` - format!("{} + {};", &snippet[..snippet.len() - 1], suggestable_fr_name) + span.with_hi(span.hi() - BytePos(1)) } else { - format!("{} + {}", snippet, suggestable_fr_name) + span }; + let suggestion = format!(" + {}", suggestable_fr_name); + let span = span.shrink_to_hi(); diag.span_suggestion( span, &format!( diff --git a/compiler/rustc_mir/src/borrow_check/member_constraints.rs b/compiler/rustc_mir/src/borrow_check/member_constraints.rs index baaf6f27ee..2e2578df01 100644 --- a/compiler/rustc_mir/src/borrow_check/member_constraints.rs +++ b/compiler/rustc_mir/src/borrow_check/member_constraints.rs @@ -1,5 +1,4 @@ use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; use rustc_middle::infer::MemberConstraint; use rustc_middle::ty::{self, Ty}; @@ -32,9 +31,6 @@ where crate struct NllMemberConstraint<'tcx> { next_constraint: Option, - /// The opaque type whose hidden type is being inferred. (Used in error reporting.) - crate opaque_type_def_id: DefId, - /// The span where the hidden type was instantiated. crate definition_span: Span, @@ -91,7 +87,6 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> { let constraint_index = self.constraints.push(NllMemberConstraint { next_constraint, member_region_vid, - opaque_type_def_id: m_c.opaque_type_def_id, definition_span: m_c.definition_span, hidden_ty: m_c.hidden_ty, start_index, diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs index dded7a7e3c..c40e6bf1ec 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs @@ -551,7 +551,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { polonius_output: Option>, ) -> (Option>, RegionErrors<'tcx>) { let mir_def_id = body.source.def_id(); - self.propagate_constraints(body, infcx.tcx); + self.propagate_constraints(body); let mut errors_buffer = RegionErrors::new(); @@ -599,7 +599,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// for each region variable until all the constraints are /// satisfied. Note that some values may grow **too** large to be /// feasible, but we check this later. - fn propagate_constraints(&mut self, _body: &Body<'tcx>, tcx: TyCtxt<'tcx>) { + fn propagate_constraints(&mut self, _body: &Body<'tcx>) { debug!("propagate_constraints()"); debug!("propagate_constraints: constraints={:#?}", { @@ -617,7 +617,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // own. let constraint_sccs = self.constraint_sccs.clone(); for scc in constraint_sccs.all_sccs() { - self.compute_value_for_scc(scc, tcx); + self.compute_value_for_scc(scc); } // Sort the applied member constraints so we can binary search @@ -629,7 +629,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// computed, by unioning the values of its successors. /// Assumes that all successors have been computed already /// (which is assured by iterating over SCCs in dependency order). - fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex, tcx: TyCtxt<'tcx>) { + fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex) { let constraint_sccs = self.constraint_sccs.clone(); // Walk each SCC `B` such that `A: B`... @@ -652,12 +652,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Now take member constraints into account. let member_constraints = self.member_constraints.clone(); for m_c_i in member_constraints.indices(scc_a) { - self.apply_member_constraint( - tcx, - scc_a, - m_c_i, - member_constraints.choice_regions(m_c_i), - ); + self.apply_member_constraint(scc_a, m_c_i, member_constraints.choice_regions(m_c_i)); } debug!( @@ -680,31 +675,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// If we make any changes, returns true, else false. fn apply_member_constraint( &mut self, - tcx: TyCtxt<'tcx>, scc: ConstraintSccIndex, member_constraint_index: NllMemberConstraintIndex, choice_regions: &[ty::RegionVid], ) -> bool { debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,); - if let Some(uh_oh) = - choice_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r)) - { - // FIXME(#61773): This case can only occur with - // `impl_trait_in_bindings`, I believe, and we are just - // opting not to handle it for now. See #61773 for - // details. - tcx.sess.delay_span_bug( - self.member_constraints[member_constraint_index].definition_span, - &format!( - "member constraint for `{:?}` has an option region `{:?}` \ - that is not a universal region", - self.member_constraints[member_constraint_index].opaque_type_def_id, uh_oh, - ), - ); - return false; - } - // Create a mutable vector of the options. We'll try to winnow // them down. let mut choice_regions: Vec = choice_regions.to_vec(); @@ -1380,7 +1356,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`. /// /// More details can be found in this blog post by Niko: - /// + /// /// /// In the canonical example /// diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs index 3ec24156f2..12fceeff08 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs @@ -60,33 +60,17 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!(?concrete_type, ?substs); let mut subst_regions = vec![self.universal_regions.fr_static]; - let universal_substs = - infcx.tcx.fold_regions(substs, &mut false, |region, _| match *region { - ty::ReVar(vid) => { - subst_regions.push(vid); - self.definitions[vid].external_name.unwrap_or_else(|| { - infcx.tcx.sess.delay_span_bug( - span, - "opaque type with non-universal region substs", - ); - infcx.tcx.lifetimes.re_static - }) - } - // We don't fold regions in the predicates of opaque - // types to `ReVar`s. This means that in a case like - // - // fn f<'a: 'a>() -> impl Iterator - // - // The inner opaque type has `'static` in its substs. - ty::ReStatic => region, - _ => { - infcx.tcx.sess.delay_span_bug( - span, - &format!("unexpected concrete region in borrowck: {:?}", region), - ); - region - } - }); + let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| { + let vid = self.universal_regions.to_region_vid(region); + subst_regions.push(vid); + self.definitions[vid].external_name.unwrap_or_else(|| { + infcx + .tcx + .sess + .delay_span_bug(span, "opaque type with non-universal region substs"); + infcx.tcx.lifetimes.re_static + }) + }); subst_regions.sort(); subst_regions.dedup(); @@ -98,14 +82,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { .find(|ur_vid| self.eval_equal(vid, **ur_vid)) .and_then(|ur_vid| self.definitions[*ur_vid].external_name) .unwrap_or(infcx.tcx.lifetimes.re_root_empty), - ty::ReLateBound(..) => region, - _ => { - infcx.tcx.sess.delay_span_bug( - span, - &format!("unexpected concrete region in borrowck: {:?}", region), - ); - region - } + _ => region, }); debug!(?universal_concrete_type, ?universal_substs); diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs index 1bb447d105..37e0643228 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs @@ -122,7 +122,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(terr) = self.eq_opaque_type_and_type( mir_output_ty, normalized_output_ty, - mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { @@ -145,7 +144,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(err) = self.eq_opaque_type_and_type( mir_output_ty, user_provided_output_ty, - mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 09cafddeef..3fb06cd2f5 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -26,7 +26,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts}; +use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, @@ -60,7 +60,6 @@ use crate::borrow_check::{ LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements, }, region_infer::{ClosureRegionRequirementsExt, TypeTest}, - renumber, type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, universal_regions::{DefiningTy, UniversalRegions}, Upvar, @@ -180,7 +179,54 @@ pub(crate) fn type_check<'mir, 'tcx>( liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); translate_outlives_facts(&mut cx); - cx.opaque_type_values + let mut opaque_type_values = cx.opaque_type_values; + + for (_, revealed_ty) in &mut opaque_type_values { + *revealed_ty = infcx.resolve_vars_if_possible(*revealed_ty); + if revealed_ty.has_infer_types_or_consts() { + infcx.tcx.sess.delay_span_bug( + body.span, + &format!("could not resolve {:#?}", revealed_ty.kind()), + ); + *revealed_ty = infcx.tcx.ty_error(); + } + } + + opaque_type_values.retain(|(opaque_type_key, resolved_ty)| { + let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() { + *def_id == opaque_type_key.def_id + } else { + false + }; + + if concrete_is_opaque { + // We're using an opaque `impl Trait` type without + // 'revealing' it. For example, code like this: + // + // type Foo = impl Debug; + // fn foo1() -> Foo { ... } + // fn foo2() -> Foo { foo1() } + // + // In `foo2`, we're not revealing the type of `Foo` - we're + // just treating it as the opaque type. + // + // When this occurs, we do *not* want to try to equate + // the concrete type with the underlying defining type + // of the opaque type - this will always fail, since + // the defining type of an opaque type is always + // some other type (e.g. not itself) + // Essentially, none of the normal obligations apply here - + // we're just passing around some unknown opaque type, + // without actually looking at the underlying type it + // gets 'revealed' into + debug!( + "eq_opaque_type_and_type: non-defining use of {:?}", + opaque_type_key.def_id, + ); + } + !concrete_is_opaque + }); + opaque_type_values }, ); @@ -1119,6 +1165,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) } + /// Try to relate `sub <: sup` fn sub_types( &mut self, sub: Ty<'tcx>, @@ -1129,32 +1176,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.relate_types(sub, ty::Variance::Covariant, sup, locations, category) } - /// Try to relate `sub <: sup`; if this fails, instantiate opaque - /// variables in `sub` with their inferred definitions and try - /// again. This is used for opaque types in places (e.g., `let x: - /// impl Foo = ..`). - fn sub_types_or_anon( - &mut self, - sub: Ty<'tcx>, - sup: Ty<'tcx>, - locations: Locations, - category: ConstraintCategory, - ) -> Fallible<()> { - if let Err(terr) = self.sub_types(sub, sup, locations, category) { - if let ty::Opaque(..) = sup.kind() { - // When you have `let x: impl Foo = ...` in a closure, - // the resulting inferend values are stored with the - // def-id of the base function. - let parent_def_id = - self.tcx().closure_base_def_id(self.body.source.def_id()).expect_local(); - return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category); - } else { - return Err(terr); - } - } - Ok(()) - } - fn eq_types( &mut self, a: Ty<'tcx>, @@ -1206,11 +1227,39 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Ok(()) } + /// Equates a type `anon_ty` that may contain opaque types whose + /// values are to be inferred by the MIR. + /// + /// The type `revealed_ty` contains the same type as `anon_ty`, but with the + /// hidden types for impl traits revealed. + /// + /// # Example + /// + /// Consider a piece of code like + /// + /// ```rust + /// type Foo = impl Debug; + /// + /// fn foo(t: T) -> Box> { + /// Box::new((t, 22_u32)) + /// } + /// ``` + /// + /// Here, the function signature would be something like + /// `fn(T) -> Box`. The MIR return slot would have + /// the type with the opaque type revealed, so `Box<(T, u32)>`. + /// + /// In terms of our function parameters: + /// + /// * `anon_ty` would be `Box>` where `Foo` is an opaque type + /// scoped to this function (note that it is parameterized by the + /// generics of `foo`). Note that `anon_ty` is not just the opaque type, + /// but the entire return type (which may contain opaque types within it). + /// * `revealed_ty` would be `Box<(T, u32)>` fn eq_opaque_type_and_type( &mut self, revealed_ty: Ty<'tcx>, anon_ty: Ty<'tcx>, - anon_owner_def_id: LocalDefId, locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { @@ -1236,14 +1285,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return Ok(()); } - let infcx = self.infcx; - let tcx = infcx.tcx; let param_env = self.param_env; let body = self.body; - let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types; + let mir_def_id = body.source.def_id().expect_local(); + let mut opaque_type_values = VecMap::new(); - debug!("eq_opaque_type_and_type: mir_def_id={:?}", body.source.def_id()); + debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id); let opaque_type_map = self.fully_perform_op( locations, category, @@ -1252,9 +1300,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let mut obligations = ObligationAccumulator::default(); let dummy_body_id = hir::CRATE_HIR_ID; + + // Replace the opaque types defined by this function with + // inference variables, creating a map. In our example above, + // this would transform the type `Box>` (where `Foo` is an opaque type) + // to `Box`, returning an `opaque_type_map` mapping `{Foo -> ?T}`. + // (Note that the key of the map is both the def-id of `Foo` along with + // any generic parameters.) let (output_ty, opaque_type_map) = obligations.add(infcx.instantiate_opaque_types( - anon_owner_def_id, + mir_def_id, dummy_body_id, param_env, anon_ty, @@ -1267,6 +1322,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { revealed_ty={:?}", output_ty, opaque_type_map, revealed_ty ); + // Make sure that the inferred types are well-formed. I'm // not entirely sure this is needed (the HIR type check // didn't do this) but it seems sensible to prevent opaque @@ -1283,74 +1339,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); for &(opaque_type_key, opaque_decl) in &opaque_type_map { - let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty); - let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() { - *def_id == opaque_type_key.def_id - } else { - false - }; - - let concrete_ty = match concrete_opaque_types - .get_by(|(key, _)| key.def_id == opaque_type_key.def_id) - { - None => { - if !concrete_is_opaque { - tcx.sess.delay_span_bug( - body.span, - &format!( - "Non-defining use of {:?} with revealed type", - opaque_type_key.def_id, - ), - ); - } - continue; - } - Some(concrete_ty) => concrete_ty, - }; - debug!("concrete_ty = {:?}", concrete_ty); - let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs); - let renumbered_opaque_defn_ty = - renumber::renumber_regions(infcx, subst_opaque_defn_ty); - - debug!( - "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}", - concrete_ty, resolved_ty, renumbered_opaque_defn_ty, - ); - - if !concrete_is_opaque { - // Equate concrete_ty (an inference variable) with - // the renumbered type from typeck. - obligations.add( - infcx - .at(&ObligationCause::dummy(), param_env) - .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?, - ); - opaque_type_values.insert(opaque_type_key, renumbered_opaque_defn_ty); - } else { - // We're using an opaque `impl Trait` type without - // 'revealing' it. For example, code like this: - // - // type Foo = impl Debug; - // fn foo1() -> Foo { ... } - // fn foo2() -> Foo { foo1() } - // - // In `foo2`, we're not revealing the type of `Foo` - we're - // just treating it as the opaque type. - // - // When this occurs, we do *not* want to try to equate - // the concrete type with the underlying defining type - // of the opaque type - this will always fail, since - // the defining type of an opaque type is always - // some other type (e.g. not itself) - // Essentially, none of the normal obligations apply here - - // we're just passing around some unknown opaque type, - // without actually looking at the underlying type it - // gets 'revealed' into - debug!( - "eq_opaque_type_and_type: non-defining use of {:?}", - opaque_type_key.def_id, - ); - } + opaque_type_values.insert(opaque_type_key, opaque_decl.concrete_ty); } debug!("eq_opaque_type_and_type: equated"); @@ -1378,7 +1367,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations, ConstraintCategory::OpaqueType, CustomTypeOp::new( - |_cx| { + |infcx| { infcx.constrain_opaque_type( opaque_type_key, &opaque_decl, @@ -1436,7 +1425,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let rv_ty = rv.ty(body, tcx); let rv_ty = self.normalize(rv_ty, location); if let Err(terr) = - self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category) + self.sub_types(rv_ty, place_ty, location.to_locations(), category) { span_mirbug!( self, @@ -1723,9 +1712,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let locations = term_location.to_locations(); - if let Err(terr) = - self.sub_types_or_anon(sig.output(), dest_ty, locations, category) - { + if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) { span_mirbug!( self, term, @@ -2017,24 +2004,26 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!("check_rvalue: is_const_fn={:?}", is_const_fn); let def_id = body.source.def_id().expect_local(); - self.infcx.report_selection_error( - &traits::Obligation::new( - ObligationCause::new( - span, - self.tcx().hir().local_def_id_to_hir_id(def_id), - traits::ObligationCauseCode::RepeatVec(is_const_fn), - ), - self.param_env, - ty::Binder::dummy(ty::TraitRef::new( - self.tcx().require_lang_item( - LangItem::Copy, - Some(self.last_span), - ), - tcx.mk_substs_trait(ty, &[]), - )) - .without_const() - .to_predicate(self.tcx()), + let obligation = traits::Obligation::new( + ObligationCause::new( + span, + self.tcx().hir().local_def_id_to_hir_id(def_id), + traits::ObligationCauseCode::RepeatVec(is_const_fn), ), + self.param_env, + ty::Binder::dummy(ty::TraitRef::new( + self.tcx().require_lang_item( + LangItem::Copy, + Some(self.last_span), + ), + tcx.mk_substs_trait(ty, &[]), + )) + .without_const() + .to_predicate(self.tcx()), + ); + self.infcx.report_selection_error( + obligation.clone(), + &obligation, &traits::SelectionError::Unimplemented, false, false, diff --git a/compiler/rustc_mir/src/const_eval/error.rs b/compiler/rustc_mir/src/const_eval/error.rs index fc21047ab7..5da1681662 100644 --- a/compiler/rustc_mir/src/const_eval/error.rs +++ b/compiler/rustc_mir/src/const_eval/error.rs @@ -16,7 +16,6 @@ use crate::interpret::{ #[derive(Clone, Debug)] pub enum ConstEvalErrKind { NeedsRfc(String), - PtrToIntCast, ConstAccessesStatic, ModifiedGlobal, AssertFailure(AssertKind), @@ -49,12 +48,6 @@ impl fmt::Display for ConstEvalErrKind { NeedsRfc(ref msg) => { write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg) } - PtrToIntCast => { - write!( - f, - "cannot cast pointer to integer because it was not created by cast from integer" - ) - } ConstAccessesStatic => write!(f, "constant accesses static"), ModifiedGlobal => { write!(f, "modifying a static's initial value from another static's initializer") @@ -157,7 +150,7 @@ impl<'tcx> ConstEvalErr<'tcx> { tcx: TyCtxtAt<'tcx>, message: &str, emit: impl FnOnce(DiagnosticBuilder<'_>), - mut lint_root: Option, + lint_root: Option, ) -> ErrorHandled { let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option| { trace!("reporting const eval failure at {:?}", self.span); @@ -194,12 +187,6 @@ impl<'tcx> ConstEvalErr<'tcx> { _ => {} }; - // If we have a 'hard error', then set `lint_root` to `None` so that we don't - // emit a lint. - if matches!(&self.error, InterpError::MachineStop(err) if err.is_hard_err()) { - lint_root = None; - } - let err_msg = self.error.to_string(); // Regular case - emit a lint. diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index 460fea3746..dc6a6b0b9f 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -48,7 +48,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( ); let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); - let ret = ecx.allocate(layout, MemoryKind::Stack); + let ret = ecx.allocate(layout, MemoryKind::Stack)?; let name = with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))); @@ -98,7 +98,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( tcx, root_span, param_env, - CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), + CompileTimeInterpreter::new(tcx.const_eval_limit()), MemoryExtra { can_access_statics }, ) } @@ -136,19 +136,19 @@ pub(super) fn op_to_const<'tcx>( // by-val is if we are in destructure_const, i.e., if this is (a field of) something that we // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or // structs containing such. - op.try_as_mplace(ecx) + op.try_as_mplace() }; - let to_const_value = |mplace: &MPlaceTy<'_>| match mplace.ptr { - Scalar::Ptr(ptr) => { - let alloc = ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(); - ConstValue::ByRef { alloc, offset: ptr.offset } + // We know `offset` is relative to the allocation, so we can use `into_parts`. + let to_const_value = |mplace: &MPlaceTy<'_>| match mplace.ptr.into_parts() { + (Some(alloc_id), offset) => { + let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory(); + ConstValue::ByRef { alloc, offset } } - Scalar::Int(int) => { + (None, offset) => { assert!(mplace.layout.is_zst()); assert_eq!( - int.assert_bits(ecx.tcx.data_layout.pointer_size) - % u128::from(mplace.layout.align.abi.bytes()), + offset.bytes() % mplace.layout.align.abi.bytes(), 0, "this MPlaceTy must come from a validated constant, thus we can assume the \ alignment is correct", @@ -162,14 +162,15 @@ pub(super) fn op_to_const<'tcx>( Err(imm) => match *imm { Immediate::Scalar(x) => match x { ScalarMaybeUninit::Scalar(s) => ConstValue::Scalar(s), - ScalarMaybeUninit::Uninit => to_const_value(&op.assert_mem_place(ecx)), + ScalarMaybeUninit::Uninit => to_const_value(&op.assert_mem_place()), }, Immediate::ScalarPair(a, b) => { - let (data, start) = match a.check_init().unwrap() { - Scalar::Ptr(ptr) => { - (ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(), ptr.offset.bytes()) + // We know `offset` is relative to the allocation, so we can use `into_parts`. + let (data, start) = match ecx.scalar_to_ptr(a.check_init().unwrap()).into_parts() { + (Some(alloc_id), offset) => { + (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) } - Scalar::Int { .. } => ( + (None, _offset) => ( ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable( b"" as &[u8], )), @@ -300,7 +301,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx, tcx.def_span(def.did), key.param_env, - CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), + CompileTimeInterpreter::new(tcx.const_eval_limit()), // Statics (and promoteds inside statics) may access other statics, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. MemoryExtra { can_access_statics: is_static }, @@ -312,22 +313,17 @@ pub fn eval_to_allocation_raw_provider<'tcx>( let err = ConstEvalErr::new(&ecx, error, None); // Some CTFE errors raise just a lint, not a hard error; see // . - let emit_as_lint = if let Some(def) = def.as_local() { + 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) + !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() } else { // use of broken constant from other crate: always an error - false + true }; - if emit_as_lint { - 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), - )) - } else { + + if is_hard_err { let msg = if is_static { Cow::from("could not evaluate static initializer") } else { @@ -345,6 +341,14 @@ pub fn eval_to_allocation_raw_provider<'tcx>( }; Err(err.report_as_error(ecx.tcx.at(ecx.cur_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), + )) } } Ok(mplace) => { @@ -366,6 +370,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( inner = true; } }; + let alloc_id = mplace.ptr.provenance.unwrap(); if let Err(error) = validation { // Validation failed, report an error. This is always a hard error. let err = ConstEvalErr::new(&ecx, error, None); @@ -378,9 +383,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( "the raw bytes of the constant ({}", display_allocation( *ecx.tcx, - ecx.tcx - .global_alloc(mplace.ptr.assert_ptr().alloc_id) - .unwrap_memory() + ecx.tcx.global_alloc(alloc_id).unwrap_memory() ) )); diag.emit(); @@ -388,7 +391,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( )) } else { // Convert to raw constant - Ok(ConstAlloc { alloc_id: mplace.ptr.assert_ptr().alloc_id, ty: mplace.layout.ty }) + Ok(ConstAlloc { alloc_id, ty: mplace.layout.ty }) } } } diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs index 773df7d7b6..c809f4f273 100644 --- a/compiler/rustc_mir/src/const_eval/machine.rs +++ b/compiler/rustc_mir/src/const_eval/machine.rs @@ -16,8 +16,8 @@ use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi; use crate::interpret::{ - self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, Memory, - OpTy, PlaceTy, Pointer, Scalar, StackPopUnwind, + self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, OpTy, + PlaceTy, Scalar, StackPopUnwind, }; use super::error::*; @@ -59,7 +59,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { pub steps_remaining: usize, /// The virtual call stack. - pub(crate) stack: Vec>, + pub(crate) stack: Vec>, } #[derive(Copy, Clone, Debug)] @@ -168,11 +168,11 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // Comparisons between integers are always known. (Scalar::Int { .. }, Scalar::Int { .. }) => a == b, // Equality with integers can never be known for sure. - (Scalar::Int { .. }, Scalar::Ptr(_)) | (Scalar::Ptr(_), Scalar::Int { .. }) => false, + (Scalar::Int { .. }, Scalar::Ptr(..)) | (Scalar::Ptr(..), Scalar::Int { .. }) => false, // FIXME: return `true` for when both sides are the same pointer, *except* that // some things (like functions and vtables) do not have stable addresses // so we need to be careful around them (see e.g. #73722). - (Scalar::Ptr(_), Scalar::Ptr(_)) => false, + (Scalar::Ptr(..), Scalar::Ptr(..)) => false, } } @@ -183,13 +183,13 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // Comparisons of abstract pointers with null pointers are known if the pointer // is in bounds, because if they are in bounds, the pointer can't be null. // Inequality with integers other than null can never be known for sure. - (Scalar::Int(int), Scalar::Ptr(ptr)) | (Scalar::Ptr(ptr), Scalar::Int(int)) => { - int.is_null() && !self.memory.ptr_may_be_null(ptr) + (Scalar::Int(int), Scalar::Ptr(ptr, _)) | (Scalar::Ptr(ptr, _), Scalar::Int(int)) => { + int.is_null() && !self.memory.ptr_may_be_null(ptr.into()) } // FIXME: return `true` for at least some comparisons where we can reliably // determine the result of runtime inequality tests at compile-time. // Examples include comparison of addresses in different static items. - (Scalar::Ptr(_), Scalar::Ptr(_)) => false, + (Scalar::Ptr(..), Scalar::Ptr(..)) => false, } } } @@ -201,6 +201,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, type MemoryExtra = MemoryExtra; + const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error + fn load_mir( ecx: &InterpCx<'mir, 'tcx, Self>, instance: ty::InstanceDef<'tcx>, @@ -233,12 +235,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // sensitive check here. But we can at least rule out functions that are not const // at all. if !ecx.tcx.is_const_fn_raw(def.did) { - // Some functions we support even if they are non-const -- but avoid testing - // that for const fn! - ecx.hook_panic_fn(instance, args)?; - // We certainly do *not* want to actually call the fn - // though, so be sure we return here. - throw_unsup_format!("calling non-const function `{}`", instance) + // allow calling functions marked with #[default_method_body_is_const]. + if !ecx.tcx.has_attr(def.did, sym::default_method_body_is_const) { + // Some functions we support even if they are non-const -- but avoid testing + // that for const fn! + ecx.hook_panic_fn(instance, args)?; + // We certainly do *not* want to actually call the fn + // though, so be sure we return here. + throw_unsup_format!("calling non-const function `{}`", instance) + } } } // This is a const fn. Call it. @@ -306,8 +311,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Size::from_bytes(size as u64), align, interpret::MemoryKind::Machine(MemoryKind::Heap), - ); - ecx.write_scalar(Scalar::Ptr(ptr), dest)?; + )?; + ecx.write_pointer(ptr, dest)?; } _ => { return Err(ConstEvalErrKind::NeedsRfc(format!( @@ -351,10 +356,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Err(ConstEvalErrKind::Abort(msg).into()) } - fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { - Err(ConstEvalErrKind::PtrToIntCast.into()) - } - fn binary_ptr_op( _ecx: &InterpCx<'mir, 'tcx, Self>, _bin_op: mir::BinOp, @@ -391,7 +392,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, frame: Frame<'mir, 'tcx>, ) -> InterpResult<'tcx, Frame<'mir, 'tcx>> { // Enforce stack size limit. Add 1 because this is run before the new frame is pushed. - if !ecx.tcx.sess.recursion_limit().value_within_limit(ecx.stack().len() + 1) { + if !ecx.recursion_limit.value_within_limit(ecx.stack().len() + 1) { throw_exhaust!(StackFrameLimitReached) } else { Ok(frame) diff --git a/compiler/rustc_mir/src/const_eval/mod.rs b/compiler/rustc_mir/src/const_eval/mod.rs index 6a514e9f62..a334165df4 100644 --- a/compiler/rustc_mir/src/const_eval/mod.rs +++ b/compiler/rustc_mir/src/const_eval/mod.rs @@ -35,7 +35,7 @@ pub(crate) fn const_caller_location( if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() { bug!("intern_const_alloc_recursive should not error in this case") } - ConstValue::Scalar(loc_place.ptr) + ConstValue::Scalar(Scalar::from_pointer(loc_place.ptr.into_pointer_or_addr().unwrap(), &tcx)) } /// Convert an evaluated constant to a type level constant @@ -179,9 +179,9 @@ pub(crate) fn deref_const<'tcx>( let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); let op = ecx.const_to_op(val, None).unwrap(); let mplace = ecx.deref_operand(&op).unwrap(); - if let Scalar::Ptr(ptr) = mplace.ptr { + if let Some(alloc_id) = mplace.ptr.provenance { assert_eq!( - tcx.get_global_alloc(ptr.alloc_id).unwrap().unwrap_memory().mutability, + tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().mutability, Mutability::Not, "deref_const cannot be used with mutable allocations as \ that could allow pattern matching to observe mutable statics", diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs index 5575a97982..03531a6b00 100644 --- a/compiler/rustc_mir/src/dataflow/mod.rs +++ b/compiler/rustc_mir/src/dataflow/mod.rs @@ -7,7 +7,7 @@ pub(crate) use self::drop_flag_effects::*; pub use self::framework::{ fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState, BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, - ResultsCursor, ResultsRefCursor, ResultsVisitor, + ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_mir/src/interpret/cast.rs index 848b44d13a..514c1aa964 100644 --- a/compiler/rustc_mir/src/interpret/cast.rs +++ b/compiler/rustc_mir/src/interpret/cast.rs @@ -57,7 +57,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .ok_or_else(|| err_inval!(TooGeneric))?; let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); - self.write_scalar(fn_ptr, dest)?; + self.write_pointer(fn_ptr, dest)?; } _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty), } @@ -88,7 +88,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::ClosureKind::FnOnce, ); let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); - self.write_scalar(fn_ptr, dest)?; + self.write_pointer(fn_ptr, dest)?; } _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty), } @@ -175,7 +175,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // (a) cast a raw ptr to usize, or // (b) cast from an integer-like (including bool, char, enums). // In both cases we want the bits. - let bits = self.force_bits(src.to_scalar()?, src.layout.size)?; + let bits = src.to_scalar()?.to_bits(src.layout.size)?; Ok(self.cast_from_scalar(bits, src.layout, cast_ty).into()) } @@ -280,7 +280,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Initial cast from sized to dyn trait let vtable = self.get_vtable(src_pointee_ty, data.principal())?; let ptr = self.read_immediate(src)?.to_scalar()?; - let val = Immediate::new_dyn_trait(ptr, vtable); + let val = Immediate::new_dyn_trait(ptr, vtable, &*self.tcx); self.write_immediate(val, dest) } diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 6f7519e615..516ef4f4e5 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -2,24 +2,24 @@ use std::cell::Cell; use std::fmt; use std::mem; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_middle::ich::StableHashingContext; use rustc_middle::mir; -use rustc_middle::mir::interpret::{GlobalId, InterpResult, Pointer, Scalar}; use rustc_middle::ty::layout::{self, TyAndLayout}; use rustc_middle::ty::{ self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, }; +use rustc_session::Limit; use rustc_span::{Pos, Span}; use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout}; use super::{ - Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, Operand, Place, PlaceTy, - ScalarMaybeUninit, StackPopJump, + AllocId, GlobalId, Immediate, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, + MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, ScalarMaybeUninit, + StackPopJump, }; use crate::transform::validate::equal_up_to_regions; use crate::util::storage::AlwaysLiveLocals; @@ -41,9 +41,8 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// The virtual memory system. pub memory: Memory<'mir, 'tcx, M>, - /// A cache for deduplicating vtables - pub(super) vtables: - FxHashMap<(Ty<'tcx>, Option>), Pointer>, + /// The recursion limit (cached from `tcx.recursion_limit(())`) + pub recursion_limit: Limit, } // The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread @@ -81,7 +80,7 @@ impl Drop for SpanGuard { } /// A stack frame. -pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> { +pub struct Frame<'mir, 'tcx, Tag: Provenance = AllocId, Extra = ()> { //////////////////////////////////////////////////////////////////////////////// // Function and callsite information //////////////////////////////////////////////////////////////////////////////// @@ -162,7 +161,7 @@ pub enum StackPopCleanup { /// State of a local variable including a memoized layout #[derive(Clone, PartialEq, Eq, HashStable)] -pub struct LocalState<'tcx, Tag = ()> { +pub struct LocalState<'tcx, Tag: Provenance = AllocId> { pub value: LocalValue, /// Don't modify if `Some`, this is only used to prevent computing the layout twice #[stable_hasher(ignore)] @@ -170,8 +169,8 @@ pub struct LocalState<'tcx, Tag = ()> { } /// Current value of a local variable -#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable)] // Miri debug-prints these -pub enum LocalValue { +#[derive(Copy, Clone, PartialEq, Eq, HashStable, Debug)] // Miri debug-prints these +pub enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, /// This local is alive but not yet initialized. It can be written to @@ -187,7 +186,7 @@ pub enum LocalValue { Live(Operand), } -impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> { +impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> { /// Read the local's value or error if the local is not yet live or not live anymore. /// /// Note: This may only be invoked from the `Machine::access_local` hook and not from @@ -221,7 +220,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> { } } -impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> { +impl<'mir, 'tcx, Tag: Provenance> Frame<'mir, 'tcx, Tag> { pub fn with_extra(self, extra: Extra) -> Frame<'mir, 'tcx, Tag, Extra> { Frame { body: self.body, @@ -236,7 +235,7 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> { } } -impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> { +impl<'mir, 'tcx, Tag: Provenance, Extra> Frame<'mir, 'tcx, Tag, Extra> { /// Get the current location within the Frame. /// /// If this is `Err`, we are not currently executing any particular statement in @@ -393,30 +392,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { tcx: tcx.at(root_span), param_env, memory: Memory::new(tcx, memory_extra), - vtables: FxHashMap::default(), + recursion_limit: tcx.recursion_limit(), } } #[inline(always)] pub fn cur_span(&self) -> Span { - self.stack().last().map_or(self.tcx.span, |f| f.current_span()) + self.stack() + .iter() + .rev() + .find(|frame| !frame.instance.def.requires_caller_location(*self.tcx)) + .map_or(self.tcx.span, |f| f.current_span()) } #[inline(always)] - pub fn force_ptr( - &self, - scalar: Scalar, - ) -> InterpResult<'tcx, Pointer> { - self.memory.force_ptr(scalar) - } - - #[inline(always)] - pub fn force_bits( - &self, - scalar: Scalar, - size: Size, - ) -> InterpResult<'tcx, u128> { - self.memory.force_bits(scalar, size) + pub fn scalar_to_ptr(&self, scalar: Scalar) -> Pointer> { + self.memory.scalar_to_ptr(scalar) } /// Call this to turn untagged "global" pointers (obtained via `tcx`) into @@ -647,7 +638,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Some((size, align))) } ty::Dynamic(..) => { - let vtable = metadata.unwrap_meta(); + let vtable = self.scalar_to_ptr(metadata.unwrap_meta()); // Read size and align from vtable (already checks size). Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) } @@ -894,10 +885,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn deallocate_local(&mut self, local: LocalValue) -> InterpResult<'tcx> { if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local { // All locals have a backing allocation, even if the allocation is empty - // due to the local having ZST type. - let ptr = ptr.assert_ptr(); - trace!("deallocating local: {:?}", self.memory.dump_alloc(ptr.alloc_id)); - self.memory.deallocate_local(ptr)?; + // due to the local having ZST type. Hence we can `unwrap`. + trace!( + "deallocating local {:?}: {:?}", + local, + self.memory.dump_alloc(ptr.provenance.unwrap().get_alloc_id()) + ); + self.memory.deallocate(ptr, None, MemoryKind::Stack)?; }; Ok(()) } @@ -928,7 +922,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { #[must_use] pub fn generate_stacktrace(&self) -> Vec> { let mut frames = Vec::new(); - for frame in self.stack().iter().rev() { + for frame in self + .stack() + .iter() + .rev() + .skip_while(|frame| frame.instance.def.requires_caller_location(*self.tcx)) + { 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), @@ -967,46 +966,45 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug match self.ecx.stack()[frame].locals[local].value { LocalValue::Dead => write!(fmt, " is dead")?, LocalValue::Uninitialized => write!(fmt, " is uninitialized")?, - LocalValue::Live(Operand::Indirect(mplace)) => match mplace.ptr { - Scalar::Ptr(ptr) => { - write!( - fmt, - " by align({}){} ref:", - mplace.align.bytes(), - match mplace.meta { - MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta), - MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(), - } - )?; - allocs.push(ptr.alloc_id); - } - ptr => write!(fmt, " by integral ref: {:?}", ptr)?, - }, + LocalValue::Live(Operand::Indirect(mplace)) => { + write!( + fmt, + " by align({}){} ref {:?}:", + mplace.align.bytes(), + match mplace.meta { + MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta), + MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(), + }, + mplace.ptr, + )?; + allocs.extend(mplace.ptr.provenance.map(Provenance::get_alloc_id)); + } LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => { write!(fmt, " {:?}", val)?; - if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val { - allocs.push(ptr.alloc_id); + if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val { + allocs.push(ptr.provenance.get_alloc_id()); } } LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => { write!(fmt, " ({:?}, {:?})", val1, val2)?; - if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val1 { - allocs.push(ptr.alloc_id); + if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val1 { + allocs.push(ptr.provenance.get_alloc_id()); } - if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr)) = val2 { - allocs.push(ptr.alloc_id); + if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val2 { + allocs.push(ptr.provenance.get_alloc_id()); } } } write!(fmt, ": {:?}", self.ecx.memory.dump_allocs(allocs)) } - Place::Ptr(mplace) => match mplace.ptr { - Scalar::Ptr(ptr) => write!( + Place::Ptr(mplace) => match mplace.ptr.provenance.map(Provenance::get_alloc_id) { + Some(alloc_id) => write!( fmt, - "by align({}) ref: {:?}", + "by align({}) ref {:?}: {:?}", mplace.align.bytes(), - self.ecx.memory.dump_alloc(ptr.alloc_id) + mplace.ptr, + self.ecx.memory.dump_alloc(alloc_id) ), ptr => write!(fmt, " integral by ref: {:?}", ptr), }, @@ -1014,7 +1012,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug } } -impl<'ctx, 'mir, 'tcx, Tag, Extra> HashStable> +impl<'ctx, 'mir, 'tcx, Tag: Provenance, Extra> HashStable> for Frame<'mir, 'tcx, Tag, Extra> where Extra: HashStable>, diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_mir/src/interpret/intern.rs index 23c0fe97c5..f2457d11d9 100644 --- a/compiler/rustc_mir/src/interpret/intern.rs +++ b/compiler/rustc_mir/src/interpret/intern.rs @@ -20,18 +20,17 @@ use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::{self, layout::TyAndLayout, Ty}; -use rustc_target::abi::Size; use rustc_ast::Mutability; -use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor}; +use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, ValueVisitor}; use crate::const_eval; pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine< 'mir, 'tcx, MemoryKind = T, - PointerTag = (), + PointerTag = AllocId, ExtraFnVal = !, FrameExtra = (), AllocExtra = (), @@ -107,7 +106,6 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: match kind { MemoryKind::Stack | MemoryKind::Machine(const_eval::MemoryKind::Heap) - | MemoryKind::Vtable | MemoryKind::CallerLocation => {} } // Set allocation mutability as appropriate. This is used by LLVM to put things into @@ -137,7 +135,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: }; // link the alloc id to the actual allocation let alloc = tcx.intern_const_alloc(alloc); - leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc)); + leftover_allocations.extend(alloc.relocations().iter().map(|&(_, alloc_id)| alloc_id)); tcx.set_alloc_id_memory(alloc_id, alloc); None } @@ -204,10 +202,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory if let ty::Dynamic(..) = tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind() { - if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() { + let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta()); + if let Some(alloc_id) = ptr.provenance { // Explicitly choose const mode here, since vtables are immutable, even // if the reference of the fat pointer is mutable. - self.intern_shallow(vtable.alloc_id, InternMode::Const, None); + self.intern_shallow(alloc_id, InternMode::Const, None); } else { // Validation will error (with a better message) on an invalid vtable pointer. // Let validation show the error message, but make sure it *does* error. @@ -217,7 +216,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory } // Check if we have encountered this pointer+layout combination before. // Only recurse for allocation-backed pointers. - if let Scalar::Ptr(ptr) = mplace.ptr { + if let Some(alloc_id) = mplace.ptr.provenance { // Compute the mode with which we intern this. Our goal here is to make as many // statics as we can immutable so they can be placed in read-only memory by LLVM. let ref_mode = match self.mode { @@ -260,7 +259,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory InternMode::Const } }; - match self.intern_shallow(ptr.alloc_id, ref_mode, Some(referenced_ty)) { + match self.intern_shallow(alloc_id, ref_mode, Some(referenced_ty)) { // No need to recurse, these are interned already and statics may have // cycles, so we don't want to recurse there Some(IsStaticOrFn) => {} @@ -322,7 +321,7 @@ where leftover_allocations, // The outermost allocation must exist, because we allocated it with // `Memory::allocate`. - ret.ptr.assert_ptr().alloc_id, + ret.ptr.provenance.unwrap(), base_intern_mode, Some(ret.layout.ty), ); @@ -396,9 +395,9 @@ where } let alloc = tcx.intern_const_alloc(alloc); tcx.set_alloc_id_memory(alloc_id, alloc); - for &(_, ((), reloc)) in alloc.relocations().iter() { - if leftover_allocations.insert(reloc) { - todo.push(reloc); + for &(_, alloc_id) in alloc.relocations().iter() { + if leftover_allocations.insert(alloc_id) { + todo.push(alloc_id); } } } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { @@ -426,14 +425,12 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> layout: TyAndLayout<'tcx>, f: impl FnOnce( &mut InterpCx<'mir, 'tcx, M>, - &MPlaceTy<'tcx, M::PointerTag>, + &PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, ()>, ) -> InterpResult<'tcx, &'tcx Allocation> { - let dest = self.allocate(layout, MemoryKind::Stack); - f(self, &dest)?; - let ptr = dest.ptr.assert_ptr(); - assert_eq!(ptr.offset, Size::ZERO); - let mut alloc = self.memory.alloc_map.remove(&ptr.alloc_id).unwrap().1; + let dest = self.allocate(layout, MemoryKind::Stack)?; + f(self, &dest.into())?; + let mut alloc = self.memory.alloc_map.remove(&dest.ptr.provenance.unwrap()).unwrap().1; alloc.mutability = Mutability::Not; Ok(self.tcx.intern_const_alloc(alloc)) } diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index 4e4166dad5..dc1f9053b6 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -18,6 +18,7 @@ use rustc_target::abi::{Abi, Align, LayoutOf as _, Primitive, Size}; use super::{ util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy, + Pointer, }; mod caller_location; @@ -138,7 +139,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::caller_location => { let span = self.find_closest_untracked_caller_location(); let location = self.alloc_caller_location_for_span(span); - self.write_scalar(location.ptr, dest)?; + self.write_immediate(location.to_ref(self), dest)?; } sym::min_align_of_val | sym::size_of_val => { @@ -190,7 +191,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ty = substs.type_at(0); let layout_of = self.layout_of(ty)?; let val = self.read_scalar(&args[0])?.check_init()?; - let bits = self.force_bits(val, layout_of.size)?; + let bits = val.to_bits(layout_of.size)?; let kind = match layout_of.abi { Abi::Scalar(ref scalar) => scalar.value, _ => span_bug!( @@ -238,7 +239,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // term since the sign of the second term can be inferred from this and // the fact that the operation has overflowed (if either is 0 no // overflow can occur) - let first_term: u128 = self.force_bits(l.to_scalar()?, l.layout.size)?; + let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?; let first_term_positive = first_term & (1 << (num_bits - 1)) == 0; if first_term_positive { // Negative overflow not possible since the positive first term @@ -298,7 +299,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, &l, &r)?; if overflowed { let layout = self.layout_of(substs.type_at(0))?; - let r_val = self.force_bits(r.to_scalar()?, layout.size)?; + let r_val = r.to_scalar()?.to_bits(layout.size)?; if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name { throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name); } else { @@ -312,9 +313,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW)) let layout = self.layout_of(substs.type_at(0))?; let val = self.read_scalar(&args[0])?.check_init()?; - let val_bits = self.force_bits(val, layout.size)?; + let val_bits = val.to_bits(layout.size)?; let raw_shift = self.read_scalar(&args[1])?.check_init()?; - let raw_shift_bits = self.force_bits(raw_shift, layout.size)?; + let raw_shift_bits = raw_shift.to_bits(layout.size)?; let width_bits = u128::from(layout.size.bits()); let shift_bits = raw_shift_bits % width_bits; let inv_shift_bits = (width_bits - shift_bits) % width_bits; @@ -331,22 +332,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?; } sym::offset => { - let ptr = self.read_scalar(&args[0])?.check_init()?; + let ptr = self.read_pointer(&args[0])?; let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?; let pointee_ty = substs.type_at(0); let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; - self.write_scalar(offset_ptr, dest)?; + self.write_pointer(offset_ptr, dest)?; } sym::arith_offset => { - let ptr = self.read_scalar(&args[0])?.check_init()?; + let ptr = self.read_pointer(&args[0])?; let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?; let pointee_ty = substs.type_at(0); let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap(); let offset_bytes = offset_count.wrapping_mul(pointee_size); - let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self); - self.write_scalar(offset_ptr, dest)?; + let offset_ptr = ptr.wrapping_signed_offset(offset_bytes, self); + self.write_pointer(offset_ptr, dest)?; } sym::ptr_offset_from => { let a = self.read_immediate(&args[0])?.to_scalar()?; @@ -361,9 +362,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // // Control flow is weird because we cannot early-return (to reach the // `go_to_block` at the end). - let done = if a.is_bits() && b.is_bits() { - let a = a.to_machine_usize(self)?; - let b = b.to_machine_usize(self)?; + let done = if let (Ok(a), Ok(b)) = (a.try_to_int(), b.try_to_int()) { + let a = a.try_to_machine_usize(*self.tcx).unwrap(); + let b = b.try_to_machine_usize(*self.tcx).unwrap(); if a == b && a != 0 { self.write_scalar(Scalar::from_machine_isize(0, self), dest)?; true @@ -376,9 +377,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if !done { // General case: we need two pointers. - let a = self.force_ptr(a)?; - let b = self.force_ptr(b)?; - if a.alloc_id != b.alloc_id { + let a = self.scalar_to_ptr(a); + let b = self.scalar_to_ptr(b); + let (a_alloc_id, a_offset, _) = self.memory.ptr_get_alloc(a)?; + let (b_alloc_id, b_offset, _) = self.memory.ptr_get_alloc(b)?; + if a_alloc_id != b_alloc_id { throw_ub_format!( "ptr_offset_from cannot compute offset of pointers into different \ allocations.", @@ -386,8 +389,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } let usize_layout = self.layout_of(self.tcx.types.usize)?; let isize_layout = self.layout_of(self.tcx.types.isize)?; - let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout); - let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout); + let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout); + let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout); let (val, _overflowed, _ty) = self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?; let pointee_layout = self.layout_of(substs.type_at(0))?; @@ -472,6 +475,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_format!("`assume` intrinsic called with `false`"); } } + sym::raw_eq => { + let result = self.raw_eq_intrinsic(&args[0], &args[1])?; + self.write_scalar(result, dest)?; + } _ => return Ok(false), } @@ -509,10 +516,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value. pub fn ptr_offset_inbounds( &self, - ptr: Scalar, + ptr: Pointer>, pointee_ty: Ty<'tcx>, offset_count: i64, - ) -> InterpResult<'tcx, Scalar> { + ) -> InterpResult<'tcx, Pointer>> { // We cannot overflow i64 as a type's size must be <= isize::MAX. let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap(); // The computed offset, in bytes, cannot overflow an isize. @@ -520,7 +527,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?; // The offset being in bounds cannot rely on "wrapping around" the address space. // So, first rule out overflows in the pointer arithmetic. - let offset_ptr = ptr.ptr_signed_offset(offset_bytes, self)?; + let offset_ptr = ptr.signed_offset(offset_bytes, self)?; // ptr and offset_ptr must be in bounds of the same allocated object. This means all of the // memory between these pointers must be accessible. Note that we do not require the // pointers to be properly aligned (unlike a read/write operation). @@ -554,9 +561,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) })?; - let src = self.read_scalar(&src)?.check_init()?; - let dst = self.read_scalar(&dst)?.check_init()?; + let src = self.read_pointer(&src)?; + let dst = self.read_pointer(&dst)?; self.memory.copy(src, align, dst, align, size, nonoverlapping) } + + pub(crate) fn raw_eq_intrinsic( + &mut self, + lhs: &OpTy<'tcx, >::PointerTag>, + rhs: &OpTy<'tcx, >::PointerTag>, + ) -> InterpResult<'tcx, Scalar> { + let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap().ty)?; + assert!(!layout.is_unsized()); + + let lhs = self.read_pointer(lhs)?; + let rhs = self.read_pointer(rhs)?; + let lhs_bytes = self.memory.read_bytes(lhs, layout.size)?; + let rhs_bytes = self.memory.read_bytes(rhs, layout.size)?; + Ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) + } } diff --git a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs index 792a474910..022129b2a2 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs @@ -91,10 +91,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None)) .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter())); let loc_layout = self.layout_of(loc_ty).unwrap(); - let location = self.allocate(loc_layout, MemoryKind::CallerLocation); + // This can fail if rustc runs out of memory right here. Trying to emit an error would be + // pointless, since that would require allocating more memory than a Location. + let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap(); // Initialize fields. - self.write_immediate(file.to_ref(), &self.mplace_field(&location, 0).unwrap().into()) + self.write_immediate(file.to_ref(self), &self.mplace_field(&location, 0).unwrap().into()) .expect("writing to memory we just allocated cannot fail"); self.write_scalar(line, &self.mplace_field(&location, 1).unwrap().into()) .expect("writing to memory we just allocated cannot fail"); diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs index 0d01dc3c21..323e102b87 100644 --- a/compiler/rustc_mir/src/interpret/machine.rs +++ b/compiler/rustc_mir/src/interpret/machine.rs @@ -13,8 +13,8 @@ use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use super::{ - AllocId, Allocation, CheckInAllocMsg, Frame, ImmTy, InterpCx, InterpResult, LocalValue, - MemPlace, Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar, StackPopUnwind, + AllocId, AllocRange, Allocation, Frame, ImmTy, InterpCx, InterpResult, LocalValue, MemPlace, + Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, }; /// Data returned by Machine::stack_pop, @@ -84,12 +84,8 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Additional memory kinds a machine wishes to distinguish from the builtin ones type MemoryKind: Debug + std::fmt::Display + MayLeak + Eq + 'static; - /// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows" - /// . - /// The `default()` is used for pointers to consts, statics, vtables and functions. - /// The `Debug` formatting is used for displaying pointers; we cannot use `Display` - /// as `()` does not implement that, but it should be "nice" output. - type PointerTag: Debug + Copy + Eq + Hash + 'static; + /// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to. + type PointerTag: Provenance + Eq + Hash + 'static; /// Machines can define extra (non-instance) things that represent values of function pointers. /// For example, Miri uses this to return a function pointer from `dlsym` @@ -122,6 +118,9 @@ pub trait Machine<'mir, 'tcx>: Sized { /// that is added to the memory so that the work is not done twice. const GLOBAL_KIND: Option; + /// Should the machine panic on allocation failures? + const PANIC_ON_ALLOC_FAIL: bool; + /// Whether memory accesses should be alignment-checked. fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool; @@ -263,28 +262,39 @@ pub trait Machine<'mir, 'tcx>: Sized { } /// Return the `AllocId` for the given thread-local static in the current thread. - fn thread_local_static_alloc_id( + fn thread_local_static_base_pointer( _ecx: &mut InterpCx<'mir, 'tcx, Self>, def_id: DefId, - ) -> InterpResult<'tcx, AllocId> { + ) -> InterpResult<'tcx, Pointer> { throw_unsup!(ThreadLocalStatic(def_id)) } - /// Return the `AllocId` backing the given `extern static`. - fn extern_static_alloc_id( + /// Return the root pointer for the given `extern static`. + fn extern_static_base_pointer( mem: &Memory<'mir, 'tcx, Self>, def_id: DefId, - ) -> InterpResult<'tcx, AllocId> { - // Use the `AllocId` associated with the `DefId`. Any actual *access* will fail. - Ok(mem.tcx.create_static_alloc(def_id)) - } + ) -> InterpResult<'tcx, Pointer>; - /// Return the "base" tag for the given *global* allocation: the one that is used for direct - /// accesses to this static/const/fn allocation. If `id` is not a global allocation, - /// this will return an unusable tag (i.e., accesses will be UB)! + /// Return a "base" pointer for the given allocation: the one that is used for direct + /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. /// - /// Called on the id returned by `thread_local_static_alloc_id` and `extern_static_alloc_id`, if needed. - fn tag_global_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag; + /// Not called on `extern` or thread-local statics (those use the methods above). + fn tag_alloc_base_pointer( + mem: &Memory<'mir, 'tcx, Self>, + ptr: Pointer, + ) -> Pointer; + + /// "Int-to-pointer cast" + fn ptr_from_addr( + mem: &Memory<'mir, 'tcx, Self>, + addr: u64, + ) -> Pointer>; + + /// Convert a pointer with provenance into an allocation-offset pair. + fn ptr_get_alloc( + mem: &Memory<'mir, 'tcx, Self>, + ptr: Pointer, + ) -> (AllocId, Size); /// Called to initialize the "extra" state of an allocation and make the pointers /// it contains (in relocations) tagged. The way we construct allocations is @@ -299,16 +309,12 @@ pub trait Machine<'mir, 'tcx>: Sized { /// allocation (because a copy had to be done to add tags or metadata), machine memory will /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) - /// - /// Also return the "base" tag to use for this allocation: the one that is used for direct - /// accesses to this allocation. If `kind == STATIC_KIND`, this tag must be consistent - /// with `tag_global_base_pointer`. fn init_allocation_extra<'b>( - memory_extra: &Self::MemoryExtra, + mem: &Memory<'mir, 'tcx, Self>, id: AllocId, alloc: Cow<'b, Allocation>, kind: Option>, - ) -> (Cow<'b, Allocation>, Self::PointerTag); + ) -> Cow<'b, Allocation>; /// Hook for performing extra checks on a memory read access. /// @@ -319,8 +325,8 @@ pub trait Machine<'mir, 'tcx>: Sized { fn memory_read( _memory_extra: &Self::MemoryExtra, _alloc_extra: &Self::AllocExtra, - _ptr: Pointer, - _size: Size, + _tag: Self::PointerTag, + _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) } @@ -330,8 +336,8 @@ pub trait Machine<'mir, 'tcx>: Sized { fn memory_written( _memory_extra: &mut Self::MemoryExtra, _alloc_extra: &mut Self::AllocExtra, - _ptr: Pointer, - _size: Size, + _tag: Self::PointerTag, + _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) } @@ -341,17 +347,8 @@ pub trait Machine<'mir, 'tcx>: Sized { fn memory_deallocated( _memory_extra: &mut Self::MemoryExtra, _alloc_extra: &mut Self::AllocExtra, - _ptr: Pointer, - _size: Size, - ) -> InterpResult<'tcx> { - Ok(()) - } - - /// Called after initializing static memory using the interpreter. - fn after_static_mem_initialized( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _ptr: Pointer, - _size: Size, + _tag: Self::PointerTag, + _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) } @@ -396,32 +393,12 @@ pub trait Machine<'mir, 'tcx>: Sized { // By default, we do not support unwinding from panics Ok(StackPopJump::Normal) } - - fn int_to_ptr( - _mem: &Memory<'mir, 'tcx, Self>, - int: u64, - ) -> InterpResult<'tcx, Pointer> { - Err((if int == 0 { - // This is UB, seriously. - // (`DanglingIntPointer` with these exact arguments has special printing code.) - err_ub!(DanglingIntPointer(0, CheckInAllocMsg::InboundsTest)) - } else { - // This is just something we cannot support during const-eval. - err_unsup!(ReadBytesAsPointer) - }) - .into()) - } - - fn ptr_to_int( - _mem: &Memory<'mir, 'tcx, Self>, - _ptr: Pointer, - ) -> InterpResult<'tcx, u64>; } // A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines // (CTFE and ConstProp) use the same instance. Here, we share that code. pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { - type PointerTag = (); + type PointerTag = AllocId; type ExtraFnVal = !; type MemoryMap = @@ -463,20 +440,40 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { #[inline(always)] fn init_allocation_extra<'b>( - _memory_extra: &Self::MemoryExtra, + _mem: &Memory<$mir, $tcx, Self>, _id: AllocId, alloc: Cow<'b, Allocation>, _kind: Option>, - ) -> (Cow<'b, Allocation>, Self::PointerTag) { + ) -> Cow<'b, Allocation> { // We do not use a tag so we can just cheaply forward the allocation - (alloc, ()) + alloc + } + + fn extern_static_base_pointer( + mem: &Memory<$mir, $tcx, Self>, + def_id: DefId, + ) -> InterpResult<$tcx, Pointer> { + // Use the `AllocId` associated with the `DefId`. Any actual *access* will fail. + Ok(Pointer::new(mem.tcx.create_static_alloc(def_id), Size::ZERO)) } #[inline(always)] - fn tag_global_base_pointer( - _memory_extra: &Self::MemoryExtra, - _id: AllocId, - ) -> Self::PointerTag { - () + fn tag_alloc_base_pointer( + _mem: &Memory<$mir, $tcx, Self>, + ptr: Pointer, + ) -> Pointer { + ptr + } + + #[inline(always)] + fn ptr_from_addr(_mem: &Memory<$mir, $tcx, Self>, addr: u64) -> Pointer> { + Pointer::new(None, Size::from_bytes(addr)) + } + + #[inline(always)] + fn ptr_get_alloc(_mem: &Memory<$mir, $tcx, Self>, ptr: Pointer) -> (AllocId, Size) { + // We know `offset` is relative to the allocation, so we can use `into_parts`. + let (alloc_id, offset) = ptr.into_parts(); + (alloc_id, offset) } } diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 76073599e2..6dcd944a1c 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -9,7 +9,7 @@ use std::assert_matches::assert_matches; use std::borrow::Cow; use std::collections::VecDeque; -use std::convert::{TryFrom, TryInto}; +use std::convert::TryFrom; use std::fmt; use std::ptr; @@ -20,7 +20,8 @@ use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; use super::{ alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, - InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Scalar, ScalarMaybeUninit, + InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, + ScalarMaybeUninit, }; use crate::util::pretty; @@ -28,8 +29,6 @@ use crate::util::pretty; pub enum MemoryKind { /// Stack memory. Error if deallocated except during a stack pop. Stack, - /// Memory backing vtables. Error if ever deallocated. - Vtable, /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated. CallerLocation, /// Additional memory kinds a machine wishes to distinguish from the builtin ones. @@ -41,7 +40,6 @@ impl MayLeak for MemoryKind { fn may_leak(self) -> bool { match self { MemoryKind::Stack => false, - MemoryKind::Vtable => true, MemoryKind::CallerLocation => true, MemoryKind::Machine(k) => k.may_leak(), } @@ -52,7 +50,6 @@ impl fmt::Display for MemoryKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MemoryKind::Stack => write!(f, "stack variable"), - MemoryKind::Vtable => write!(f, "vtable"), MemoryKind::CallerLocation => write!(f, "caller location"), MemoryKind::Machine(m) => write!(f, "{}", m), } @@ -167,25 +164,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { #[inline] pub fn global_base_pointer( &self, - mut ptr: Pointer, + ptr: Pointer, ) -> InterpResult<'tcx, Pointer> { + // We know `offset` is relative to the allocation, so we can use `into_parts`. + let (alloc_id, offset) = ptr.into_parts(); // We need to handle `extern static`. - let ptr = match self.tcx.get_global_alloc(ptr.alloc_id) { + match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => { bug!("global memory cannot point to thread-local static") } Some(GlobalAlloc::Static(def_id)) if self.tcx.is_foreign_item(def_id) => { - ptr.alloc_id = M::extern_static_alloc_id(self, def_id)?; - ptr - } - _ => { - // No need to change the `AllocId`. - ptr + return M::extern_static_base_pointer(self, def_id); } - }; + _ => {} + } // And we need to get the tag. - let tag = M::tag_global_base_pointer(&self.extra, ptr.alloc_id); - Ok(ptr.with_tag(tag)) + Ok(M::tag_alloc_base_pointer(self, Pointer::new(alloc_id, offset))) } pub fn create_fn_alloc( @@ -212,9 +206,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { size: Size, align: Align, kind: MemoryKind, - ) -> Pointer { - let alloc = Allocation::uninit(size, align); - self.allocate_with(alloc, kind) + ) -> InterpResult<'static, Pointer> { + let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?; + Ok(self.allocate_with(alloc, kind)) } pub fn allocate_bytes( @@ -239,21 +233,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { M::GLOBAL_KIND.map(MemoryKind::Machine), "dynamically allocating global memory" ); - // This is a new allocation, not a new global one, so no `global_base_ptr`. - let (alloc, tag) = M::init_allocation_extra(&self.extra, id, Cow::Owned(alloc), Some(kind)); + let alloc = M::init_allocation_extra(self, id, Cow::Owned(alloc), Some(kind)); self.alloc_map.insert(id, (kind, alloc.into_owned())); - Pointer::from(id).with_tag(tag) + M::tag_alloc_base_pointer(self, Pointer::from(id)) } pub fn reallocate( &mut self, - ptr: Pointer, + ptr: Pointer>, old_size_and_align: Option<(Size, Align)>, new_size: Size, new_align: Align, kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { - if ptr.offset.bytes() != 0 { + let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?; + if offset.bytes() != 0 { throw_ub_format!( "reallocating {:?} which does not point to the beginning of an object", ptr @@ -262,10 +256,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // This happens so rarely, the perf advantage is outweighed by the maintenance cost. - let new_ptr = self.allocate(new_size, new_align, kind); + let new_ptr = self.allocate(new_size, new_align, kind)?; let old_size = match old_size_and_align { Some((size, _align)) => size, - None => self.get_raw(ptr.alloc_id)?.size(), + None => self.get_raw(alloc_id)?.size(), }; // This will also call the access hooks. self.copy( @@ -276,61 +270,51 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { old_size.min(new_size), /*nonoverlapping*/ true, )?; - self.deallocate(ptr, old_size_and_align, kind)?; + self.deallocate(ptr.into(), old_size_and_align, kind)?; Ok(new_ptr) } - /// Deallocate a local, or do nothing if that local has been made into a global. - pub fn deallocate_local(&mut self, ptr: Pointer) -> InterpResult<'tcx> { - // The allocation might be already removed by global interning. - // This can only really happen in the CTFE instance, not in miri. - if self.alloc_map.contains_key(&ptr.alloc_id) { - self.deallocate(ptr, None, MemoryKind::Stack) - } else { - Ok(()) - } - } - pub fn deallocate( &mut self, - ptr: Pointer, + ptr: Pointer>, old_size_and_align: Option<(Size, Align)>, kind: MemoryKind, ) -> InterpResult<'tcx> { - trace!("deallocating: {}", ptr.alloc_id); + let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?; + trace!("deallocating: {}", alloc_id); - if ptr.offset.bytes() != 0 { + if offset.bytes() != 0 { throw_ub_format!( "deallocating {:?} which does not point to the beginning of an object", ptr ); } - let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) { + let (alloc_kind, mut alloc) = match self.alloc_map.remove(&alloc_id) { Some(alloc) => alloc, None => { // Deallocating global memory -- always an error - return Err(match self.tcx.get_global_alloc(ptr.alloc_id) { + return Err(match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Function(..)) => { - err_ub_format!("deallocating {}, which is a function", ptr.alloc_id) + err_ub_format!("deallocating {}, which is a function", alloc_id) } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { - err_ub_format!("deallocating {}, which is static memory", ptr.alloc_id) + err_ub_format!("deallocating {}, which is static memory", alloc_id) } - None => err_ub!(PointerUseAfterFree(ptr.alloc_id)), + None => err_ub!(PointerUseAfterFree(alloc_id)), } .into()); } }; if alloc.mutability == Mutability::Not { - throw_ub_format!("deallocating immutable allocation {}", ptr.alloc_id); + throw_ub_format!("deallocating immutable allocation {}", alloc_id); } if alloc_kind != kind { throw_ub_format!( "deallocating {}, which is {} memory, using {} deallocation operation", - ptr.alloc_id, + alloc_id, alloc_kind, kind ); @@ -339,7 +323,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if size != alloc.size() || align != alloc.align { throw_ub_format!( "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}", - ptr.alloc_id, + alloc_id, alloc.size().bytes(), alloc.align.bytes(), size.bytes(), @@ -350,10 +334,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Let the machine take some extra action let size = alloc.size(); - M::memory_deallocated(&mut self.extra, &mut alloc.extra, ptr, size)?; + M::memory_deallocated( + &mut self.extra, + &mut alloc.extra, + ptr.provenance, + alloc_range(Size::ZERO, size), + )?; // Don't forget to remember size and align of this now-dead allocation - let old = self.dead_alloc_map.insert(ptr.alloc_id, (size, alloc.align)); + let old = self.dead_alloc_map.insert(alloc_id, (size, alloc.align)); if old.is_some() { bug!("Nothing can be deallocated twice"); } @@ -361,52 +350,69 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Ok(()) } - /// Internal helper function for APIs that offer memory access based on `Scalar` pointers. + /// Internal helper function to determine the allocation and offset of a pointer (if any). #[inline(always)] - pub(super) fn check_ptr_access( + fn get_ptr_access( &self, - sptr: Scalar, + ptr: Pointer>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer)>> { let align = M::enforce_alignment(&self.extra).then_some(align); - self.check_and_deref_ptr(sptr, size, align, CheckInAllocMsg::MemoryAccessTest, |ptr| { - let (size, align) = - self.get_size_and_align(ptr.alloc_id, AllocCheck::Dereferenceable)?; - Ok((size, align, ptr)) - }) + self.check_and_deref_ptr( + ptr, + size, + align, + CheckInAllocMsg::MemoryAccessTest, + |alloc_id, offset, ptr| { + let (size, align) = + self.get_size_and_align(alloc_id, AllocCheck::Dereferenceable)?; + Ok((size, align, (alloc_id, offset, ptr))) + }, + ) } - /// Check if the given scalar is allowed to do a memory access of given `size` and `align` + /// Check if the given pointer points to live memory of given `size` and `align` /// (ignoring `M::enforce_alignment`). The caller can control the error message for the /// out-of-bounds case. #[inline(always)] pub fn check_ptr_access_align( &self, - sptr: Scalar, + ptr: Pointer>, size: Size, align: Align, msg: CheckInAllocMsg, ) -> InterpResult<'tcx> { - self.check_and_deref_ptr(sptr, size, Some(align), msg, |ptr| { - let (size, align) = - self.get_size_and_align(ptr.alloc_id, AllocCheck::Dereferenceable)?; + self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| { + let check = match msg { + CheckInAllocMsg::DerefTest | CheckInAllocMsg::MemoryAccessTest => { + AllocCheck::Dereferenceable + } + CheckInAllocMsg::PointerArithmeticTest | CheckInAllocMsg::InboundsTest => { + AllocCheck::Live + } + }; + let (size, align) = self.get_size_and_align(alloc_id, check)?; Ok((size, align, ())) })?; Ok(()) } /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference - /// to the allocation it points to. Supports both shared and mutable references, to the actual + /// to the allocation it points to. Supports both shared and mutable references, as the actual /// checking is offloaded to a helper closure. `align` defines whether and which alignment check /// is done. Returns `None` for size 0, and otherwise `Some` of what `alloc_size` returned. fn check_and_deref_ptr( &self, - sptr: Scalar, + ptr: Pointer>, size: Size, align: Option, msg: CheckInAllocMsg, - alloc_size: impl FnOnce(Pointer) -> InterpResult<'tcx, (Size, Align, T)>, + alloc_size: impl FnOnce( + AllocId, + Size, + Pointer, + ) -> InterpResult<'tcx, (Size, Align, T)>, ) -> InterpResult<'tcx, Option> { fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> { if offset % align.bytes() == 0 { @@ -421,53 +427,56 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } } - // Normalize to a `Pointer` if we definitely need one. - let normalized = if size.bytes() == 0 { - // Can be an integer, just take what we got. We do NOT `force_bits` here; - // if this is already a `Pointer` we want to do the bounds checks! - sptr + // Extract from the pointer an `Option` and an offset, which is relative to the + // allocation or (if that is `None`) an absolute address. + let ptr_or_addr = if size.bytes() == 0 { + // Let's see what we can do, but don't throw errors if there's nothing there. + self.ptr_try_get_alloc(ptr) } else { - // A "real" access, we must get a pointer to be able to check the bounds. - Scalar::from(self.force_ptr(sptr)?) + // A "real" access, we insist on getting an `AllocId`. + Ok(self.ptr_get_alloc(ptr)?) }; - Ok(match normalized.to_bits_or_ptr(self.pointer_size(), self) { - Ok(bits) => { - let bits = u64::try_from(bits).unwrap(); // it's ptr-sized - assert!(size.bytes() == 0); + Ok(match ptr_or_addr { + Err(addr) => { + // No memory is actually being accessed. + debug_assert!(size.bytes() == 0); // Must be non-null. - if bits == 0 { + if addr == 0 { throw_ub!(DanglingIntPointer(0, msg)) } // Must be aligned. if let Some(align) = align { - check_offset_align(bits, align)?; + check_offset_align(addr, align)?; } None } - Err(ptr) => { - let (allocation_size, alloc_align, ret_val) = alloc_size(ptr)?; + Ok((alloc_id, offset, ptr)) => { + let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, ptr)?; // Test bounds. This also ensures non-null. - // It is sufficient to check this for the end pointer. The addition - // checks for overflow. - let end_ptr = ptr.offset(size, self)?; - if end_ptr.offset > allocation_size { - // equal is okay! - throw_ub!(PointerOutOfBounds { ptr: end_ptr.erase_tag(), msg, allocation_size }) + // It is sufficient to check this for the end pointer. Also check for overflow! + if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) { + throw_ub!(PointerOutOfBounds { + alloc_id, + alloc_size, + ptr_offset: self.machine_usize_to_isize(offset.bytes()), + ptr_size: size, + msg, + }) } // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { if M::force_int_for_alignment_check(&self.extra) { - let bits = self - .force_bits(ptr.into(), self.pointer_size()) + let addr = Scalar::from_pointer(ptr, &self.tcx) + .to_machine_usize(&self.tcx) .expect("ptr-to-int cast for align check should never fail"); - check_offset_align(bits.try_into().unwrap(), align)?; + check_offset_align(addr, align)?; } else { // Check allocation alignment and offset alignment. if alloc_align.bytes() < align.bytes() { throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align }); } - check_offset_align(ptr.offset.bytes(), align)?; + check_offset_align(offset.bytes(), align)?; } } @@ -479,13 +488,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } /// Test if the pointer might be null. - pub fn ptr_may_be_null(&self, ptr: Pointer) -> bool { - let (size, _align) = self - .get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead) - .expect("alloc info with MaybeDead cannot fail"); - // If the pointer is out-of-bounds, it may be null. - // Note that one-past-the-end (offset == size) is still inbounds, and never null. - ptr.offset > size + pub fn ptr_may_be_null(&self, ptr: Pointer>) -> bool { + match self.ptr_try_get_alloc(ptr) { + Ok((alloc_id, offset, _)) => { + let (size, _align) = self + .get_size_and_align(alloc_id, AllocCheck::MaybeDead) + .expect("alloc info with MaybeDead cannot fail"); + // If the pointer is out-of-bounds, it may be null. + // Note that one-past-the-end (offset == size) is still inbounds, and never null. + offset > size + } + Err(offset) => offset == 0, + } } } @@ -497,12 +511,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// this machine use the same pointer tag, so it is indirected through /// `M::tag_allocation`. fn get_global_alloc( - memory_extra: &M::MemoryExtra, - tcx: TyCtxt<'tcx>, + &self, id: AllocId, is_write: bool, ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { - let (alloc, def_id) = match tcx.get_global_alloc(id) { + let (alloc, def_id) = match self.tcx.get_global_alloc(id) { Some(GlobalAlloc::Memory(mem)) => { // Memory of a constant or promoted or anonymous memory referenced by a static. (mem, None) @@ -510,8 +523,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)), None => throw_ub!(PointerUseAfterFree(id)), Some(GlobalAlloc::Static(def_id)) => { - assert!(tcx.is_static(def_id)); - assert!(!tcx.is_thread_local_static(def_id)); + assert!(self.tcx.is_static(def_id)); + assert!(!self.tcx.is_thread_local_static(def_id)); // Notice that every static has two `AllocId` that will resolve to the same // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID, // and the other one is maps to `GlobalAlloc::Memory`, this is returned by @@ -522,24 +535,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // The `GlobalAlloc::Memory` branch here is still reachable though; when a static // contains a reference to memory that was created during its evaluation (i.e., not // to another static), those inner references only exist in "resolved" form. - if tcx.is_foreign_item(def_id) { + if self.tcx.is_foreign_item(def_id) { throw_unsup!(ReadExternStatic(def_id)); } - (tcx.eval_static_initializer(def_id)?, Some(def_id)) + (self.tcx.eval_static_initializer(def_id)?, Some(def_id)) } }; - M::before_access_global(memory_extra, id, alloc, def_id, is_write)?; + M::before_access_global(&self.extra, id, alloc, def_id, is_write)?; let alloc = Cow::Borrowed(alloc); // We got tcx memory. Let the machine initialize its "extra" stuff. - let (alloc, tag) = M::init_allocation_extra( - memory_extra, + let alloc = M::init_allocation_extra( + self, id, // always use the ID we got as input, not the "hidden" one. alloc, M::GLOBAL_KIND.map(MemoryKind::Machine), ); - // Sanity check that this is the same pointer we would have gotten via `global_base_pointer`. - debug_assert_eq!(tag, M::tag_global_base_pointer(memory_extra, id)); Ok(alloc) } @@ -554,8 +565,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // `get_global_alloc` that we can actually use directly without inserting anything anywhere. // So the error type is `InterpResult<'tcx, &Allocation>`. let a = self.alloc_map.get_or(id, || { - let alloc = Self::get_global_alloc(&self.extra, self.tcx, id, /*is_write*/ false) - .map_err(Err)?; + let alloc = self.get_global_alloc(id, /*is_write*/ false).map_err(Err)?; match alloc { Cow::Borrowed(alloc) => { // We got a ref, cheaply return that as an "error" so that the @@ -582,30 +592,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// "Safe" (bounds and align-checked) allocation access. pub fn get<'a>( &'a self, - sptr: Scalar, + ptr: Pointer>, size: Size, align: Align, ) -> InterpResult<'tcx, Option>> { let align = M::enforce_alignment(&self.extra).then_some(align); let ptr_and_alloc = self.check_and_deref_ptr( - sptr, + ptr, size, align, CheckInAllocMsg::MemoryAccessTest, - |ptr| { - let alloc = self.get_raw(ptr.alloc_id)?; - Ok((alloc.size(), alloc.align, (ptr, alloc))) + |alloc_id, offset, ptr| { + let alloc = self.get_raw(alloc_id)?; + Ok((alloc.size(), alloc.align, (alloc_id, offset, ptr, alloc))) }, )?; - if let Some((ptr, alloc)) = ptr_and_alloc { - M::memory_read(&self.extra, &alloc.extra, ptr, size)?; - let range = alloc_range(ptr.offset, size); - Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id: ptr.alloc_id })) + if let Some((alloc_id, offset, ptr, alloc)) = ptr_and_alloc { + let range = alloc_range(offset, size); + M::memory_read(&self.extra, &alloc.extra, ptr.provenance, range)?; + Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id })) } else { // Even in this branch we have to be sure that we actually access the allocation, in // order to ensure that `static FOO: Type = FOO;` causes a cycle error instead of // magically pulling *any* ZST value from the ether. However, the `get_raw` above is - // always called when `sptr` is truly a `Pointer`, so we are good. + // always called when `ptr` has an `AllocId`. Ok(None) } } @@ -625,48 +635,44 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { id: AllocId, ) -> InterpResult<'tcx, (&mut Allocation, &mut M::MemoryExtra)> { - let tcx = self.tcx; - let memory_extra = &mut self.extra; - let a = self.alloc_map.get_mut_or(id, || { - // Need to make a copy, even if `get_global_alloc` is able - // to give us a cheap reference. - let alloc = Self::get_global_alloc(memory_extra, tcx, id, /*is_write*/ true)?; + // We have "NLL problem case #3" here, which cannot be worked around without loss of + // efficiency even for the common case where the key is in the map. + // + // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`.) + if self.alloc_map.get_mut(id).is_none() { + // Slow path. + // Allocation not found locally, go look global. + let alloc = self.get_global_alloc(id, /*is_write*/ true)?; let kind = M::GLOBAL_KIND.expect( "I got a global allocation that I have to copy but the machine does \ not expect that to happen", ); - Ok((MemoryKind::Machine(kind), alloc.into_owned())) - }); - // Unpack the error type manually because type inference doesn't - // work otherwise (and we cannot help it because `impl Trait`) - match a { - Err(e) => Err(e), - Ok(a) => { - let a = &mut a.1; - if a.mutability == Mutability::Not { - throw_ub!(WriteToReadOnly(id)) - } - Ok((a, memory_extra)) - } + self.alloc_map.insert(id, (MemoryKind::Machine(kind), alloc.into_owned())); + } + + let (_kind, alloc) = self.alloc_map.get_mut(id).unwrap(); + if alloc.mutability == Mutability::Not { + throw_ub!(WriteToReadOnly(id)) } + Ok((alloc, &mut self.extra)) } /// "Safe" (bounds and align-checked) allocation access. pub fn get_mut<'a>( &'a mut self, - sptr: Scalar, + ptr: Pointer>, size: Size, align: Align, ) -> InterpResult<'tcx, Option>> { - let ptr = self.check_ptr_access(sptr, size, align)?; - if let Some(ptr) = ptr { + let parts = self.get_ptr_access(ptr, size, align)?; + if let Some((alloc_id, offset, ptr)) = parts { let tcx = self.tcx; // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. - let (alloc, extra) = self.get_raw_mut(ptr.alloc_id)?; - M::memory_written(extra, &mut alloc.extra, ptr, size)?; - let range = alloc_range(ptr.offset, size); - Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id: ptr.alloc_id })) + let (alloc, extra) = self.get_raw_mut(alloc_id)?; + let range = alloc_range(offset, size); + M::memory_written(extra, &mut alloc.extra, ptr.provenance, range)?; + Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id })) } else { Ok(None) } @@ -743,7 +749,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } fn get_fn_alloc(&self, id: AllocId) -> Option> { - trace!("reading fn ptr: {}", id); if let Some(extra) = self.extra_fn_ptr_map.get(&id) { Some(FnVal::Other(*extra)) } else { @@ -756,14 +761,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn get_fn( &self, - ptr: Scalar, + ptr: Pointer>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { - let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value. - if ptr.offset.bytes() != 0 { - throw_ub!(InvalidFunctionPointer(ptr.erase_tag())) + trace!("get_fn({:?})", ptr); + let (alloc_id, offset, _ptr) = self.ptr_get_alloc(ptr)?; + if offset.bytes() != 0 { + throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))) } - self.get_fn_alloc(ptr.alloc_id) - .ok_or_else(|| err_ub!(InvalidFunctionPointer(ptr.erase_tag())).into()) + self.get_fn_alloc(alloc_id) + .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))).into()) } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { @@ -802,7 +808,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if reachable.insert(id) { // This is a new allocation, add its relocations to `todo`. if let Some((_, alloc)) = self.alloc_map.get(id) { - todo.extend(alloc.relocations().values().map(|&(_, target_id)| target_id)); + todo.extend(alloc.relocations().values().map(|tag| tag.get_alloc_id())); } } } @@ -836,14 +842,14 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Cannot be a closure because it is generic in `Tag`, `Extra`. - fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>( + fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>( fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'tcx>, allocs_to_print: &mut VecDeque, alloc: &Allocation, ) -> std::fmt::Result { - for &(_, target_id) in alloc.relocations().values() { - allocs_to_print.push_back(target_id); + for alloc_id in alloc.relocations().values().map(|tag| tag.get_alloc_id()) { + allocs_to_print.push_back(alloc_id); } write!(fmt, "{}", pretty::display_allocation(tcx, alloc)) } @@ -946,8 +952,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// Reads the given number of bytes from memory. Returns them as a slice. /// /// Performs appropriate bounds checks. - pub fn read_bytes(&self, sptr: Scalar, size: Size) -> InterpResult<'tcx, &[u8]> { - let alloc_ref = match self.get(sptr, size, Align::ONE)? { + pub fn read_bytes( + &self, + ptr: Pointer>, + size: Size, + ) -> InterpResult<'tcx, &[u8]> { + let alloc_ref = match self.get(ptr, size, Align::ONE)? { Some(a) => a, None => return Ok(&[]), // zero-sized access }; @@ -964,7 +974,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// Performs appropriate bounds checks. pub fn write_bytes( &mut self, - sptr: Scalar, + ptr: Pointer>, src: impl IntoIterator, ) -> InterpResult<'tcx> { let mut src = src.into_iter(); @@ -973,7 +983,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { assert_eq!(lower, len, "can only write iterators with a precise length"); let size = Size::from_bytes(len); - let alloc_ref = match self.get_mut(sptr, size, Align::ONE)? { + let alloc_ref = match self.get_mut(ptr, size, Align::ONE)? { Some(alloc_ref) => alloc_ref, None => { // zero-sized access @@ -1000,9 +1010,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn copy( &mut self, - src: Scalar, + src: Pointer>, src_align: Align, - dest: Scalar, + dest: Pointer>, dest_align: Align, size: Size, nonoverlapping: bool, @@ -1012,9 +1022,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn copy_repeatedly( &mut self, - src: Scalar, + src: Pointer>, src_align: Align, - dest: Scalar, + dest: Pointer>, dest_align: Align, size: Size, num_copies: u64, @@ -1022,22 +1032,23 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> InterpResult<'tcx> { let tcx = self.tcx; // We need to do our own bounds-checks. - let src = self.check_ptr_access(src, size, src_align)?; - let dest = self.check_ptr_access(dest, size * num_copies, dest_align)?; // `Size` multiplication + let src_parts = self.get_ptr_access(src, size, src_align)?; + let dest_parts = self.get_ptr_access(dest, size * num_copies, dest_align)?; // `Size` multiplication // FIXME: we look up both allocations twice here, once ebfore for the `check_ptr_access` // and once below to get the underlying `&[mut] Allocation`. // Source alloc preparations and access hooks. - let src = match src { + let (src_alloc_id, src_offset, src) = match src_parts { None => return Ok(()), // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do. Some(src_ptr) => src_ptr, }; - let src_alloc = self.get_raw(src.alloc_id)?; - M::memory_read(&self.extra, &src_alloc.extra, src, size)?; + let src_alloc = self.get_raw(src_alloc_id)?; + let src_range = alloc_range(src_offset, size); + M::memory_read(&self.extra, &src_alloc.extra, src.provenance, src_range)?; // We need the `dest` ptr for the next operation, so we get it now. // We already did the source checks and called the hooks so we are good to return early. - let dest = match dest { + let (dest_alloc_id, dest_offset, dest) = match dest_parts { None => return Ok(()), // Zero-sized *destiantion*. Some(dest_ptr) => dest_ptr, }; @@ -1047,26 +1058,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // since we don't want to keep any relocations at the target. // (`get_bytes_with_uninit_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). - let relocations = src_alloc.prepare_relocation_copy( - self, - alloc_range(src.offset, size), - dest.offset, - num_copies, - ); + let relocations = + src_alloc.prepare_relocation_copy(self, src_range, dest_offset, num_copies); // Prepare a copy of the initialization mask. - let compressed = src_alloc.compress_uninit_range(src, size); + let compressed = src_alloc.compress_uninit_range(src_range); // This checks relocation edges on the src. let src_bytes = src_alloc - .get_bytes_with_uninit_and_ptr(&tcx, alloc_range(src.offset, size)) - .map_err(|e| e.to_interp_error(src.alloc_id))? + .get_bytes_with_uninit_and_ptr(&tcx, src_range) + .map_err(|e| e.to_interp_error(src_alloc_id))? .as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation // Destination alloc preparations and access hooks. - let (dest_alloc, extra) = self.get_raw_mut(dest.alloc_id)?; - M::memory_written(extra, &mut dest_alloc.extra, dest, size * num_copies)?; - let dest_bytes = dest_alloc - .get_bytes_mut_ptr(&tcx, alloc_range(dest.offset, size * num_copies)) - .as_mut_ptr(); + let (dest_alloc, extra) = self.get_raw_mut(dest_alloc_id)?; + let dest_range = alloc_range(dest_offset, size * num_copies); + M::memory_written(extra, &mut dest_alloc.extra, dest.provenance, dest_range)?; + let dest_bytes = dest_alloc.get_bytes_mut_ptr(&tcx, dest_range).as_mut_ptr(); if compressed.no_bytes_init() { // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range @@ -1075,7 +1081,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // This also avoids writing to the target bytes so that the backing allocation is never // touched if the bytes stay uninitialized for the whole interpreter execution. On contemporary // operating system this can avoid physically allocating the page. - dest_alloc.mark_init(alloc_range(dest.offset, size * num_copies), false); // `Size` multiplication + dest_alloc.mark_init(dest_range, false); // `Size` multiplication dest_alloc.mark_relocation_range(relocations); return Ok(()); } @@ -1086,11 +1092,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // The pointers above remain valid even if the `HashMap` table is moved around because they // point into the `Vec` storing the bytes. unsafe { - if src.alloc_id == dest.alloc_id { + if src_alloc_id == dest_alloc_id { if nonoverlapping { // `Size` additions - if (src.offset <= dest.offset && src.offset + size > dest.offset) - || (dest.offset <= src.offset && dest.offset + size > src.offset) + if (src_offset <= dest_offset && src_offset + size > dest_offset) + || (dest_offset <= src_offset && dest_offset + size > src_offset) { throw_ub_format!("copy_nonoverlapping called on overlapping ranges") } @@ -1115,7 +1121,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } // now fill in all the "init" data - dest_alloc.mark_compressed_init_range(&compressed, dest, size, num_copies); + dest_alloc.mark_compressed_init_range( + &compressed, + alloc_range(dest_offset, size), // just a single copy (i.e., not full `dest_range`) + num_copies, + ); // copy the relocations to the destination dest_alloc.mark_relocation_range(relocations); @@ -1125,24 +1135,41 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// Machine pointer introspection. impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { - pub fn force_ptr( - &self, - scalar: Scalar, - ) -> InterpResult<'tcx, Pointer> { - match scalar { - Scalar::Ptr(ptr) => Ok(ptr), - _ => M::int_to_ptr(&self, scalar.to_machine_usize(self)?), + pub fn scalar_to_ptr(&self, scalar: Scalar) -> Pointer> { + // We use `to_bits_or_ptr_internal` since we are just implementing the method people need to + // call to force getting out a pointer. + match scalar.to_bits_or_ptr_internal(self.pointer_size()) { + Err(ptr) => ptr.into(), + Ok(bits) => { + let addr = u64::try_from(bits).unwrap(); + M::ptr_from_addr(&self, addr) + } } } - pub fn force_bits( + /// Turning a "maybe pointer" into a proper pointer (and some information + /// about where it points), or an absolute address. + pub fn ptr_try_get_alloc( &self, - scalar: Scalar, - size: Size, - ) -> InterpResult<'tcx, u128> { - match scalar.to_bits_or_ptr(size, self) { - Ok(bits) => Ok(bits), - Err(ptr) => Ok(M::ptr_to_int(&self, ptr)?.into()), + ptr: Pointer>, + ) -> Result<(AllocId, Size, Pointer), u64> { + match ptr.into_pointer_or_addr() { + Ok(ptr) => { + let (alloc_id, offset) = M::ptr_get_alloc(self, ptr); + Ok((alloc_id, offset, ptr)) + } + Err(addr) => Err(addr.bytes()), } } + + /// Turning a "maybe pointer" into a proper pointer (and some information about where it points). + #[inline(always)] + pub fn ptr_get_alloc( + &self, + ptr: Pointer>, + ) -> InterpResult<'tcx, (AllocId, Size, Pointer)> { + self.ptr_try_get_alloc(ptr).map_err(|offset| { + err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into() + }) + } } diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 06432a8b90..aba7db7816 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -15,8 +15,9 @@ use rustc_target::abi::{Abi, HasDataLayout, LayoutOf, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ - alloc_range, from_known_layout, mir_assign_valid_types, ConstValue, GlobalId, InterpCx, - InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, + alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, GlobalId, + InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Provenance, + Scalar, ScalarMaybeUninit, }; /// An `Immediate` represents a single immediate self-contained Rust value. @@ -26,8 +27,8 @@ use super::{ /// operations and wide pointers. This idea was taken from rustc's codegen. /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely /// defined on `Immediate`, and do not have to work with a `Place`. -#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)] -pub enum Immediate { +#[derive(Copy, Clone, PartialEq, Eq, HashStable, Hash, Debug)] +pub enum Immediate { Scalar(ScalarMaybeUninit), ScalarPair(ScalarMaybeUninit, ScalarMaybeUninit), } @@ -35,34 +36,35 @@ pub enum Immediate { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Immediate, 56); -impl From> for Immediate { +impl From> for Immediate { #[inline(always)] fn from(val: ScalarMaybeUninit) -> Self { Immediate::Scalar(val) } } -impl From> for Immediate { +impl From> for Immediate { #[inline(always)] fn from(val: Scalar) -> Self { Immediate::Scalar(val.into()) } } -impl From> for Immediate { - #[inline(always)] - fn from(val: Pointer) -> Self { - Immediate::Scalar(Scalar::from(val).into()) +impl<'tcx, Tag: Provenance> Immediate { + pub fn from_pointer(p: Pointer, cx: &impl HasDataLayout) -> Self { + Immediate::Scalar(ScalarMaybeUninit::from_pointer(p, cx)) + } + + pub fn from_maybe_pointer(p: Pointer>, cx: &impl HasDataLayout) -> Self { + Immediate::Scalar(ScalarMaybeUninit::from_maybe_pointer(p, cx)) } -} -impl<'tcx, Tag> Immediate { pub fn new_slice(val: Scalar, len: u64, cx: &impl HasDataLayout) -> Self { Immediate::ScalarPair(val.into(), Scalar::from_machine_usize(len, cx).into()) } - pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self { - Immediate::ScalarPair(val.into(), vtable.into()) + pub fn new_dyn_trait(val: Scalar, vtable: Pointer, cx: &impl HasDataLayout) -> Self { + Immediate::ScalarPair(val.into(), ScalarMaybeUninit::from_pointer(vtable, cx)) } #[inline] @@ -82,7 +84,7 @@ impl<'tcx, Tag> Immediate { // ScalarPair needs a type to interpret, so we often have an immediate and a type together // as input for binary and cast operations. #[derive(Copy, Clone, Debug)] -pub struct ImmTy<'tcx, Tag = ()> { +pub struct ImmTy<'tcx, Tag: Provenance = AllocId> { imm: Immediate, pub layout: TyAndLayout<'tcx>, } @@ -90,17 +92,23 @@ pub struct ImmTy<'tcx, Tag = ()> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(ImmTy<'_>, 72); -impl std::fmt::Display for ImmTy<'tcx, Tag> { +impl std::fmt::Display for ImmTy<'tcx, Tag> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// Helper function for printing a scalar to a FmtPrinter - fn p<'a, 'tcx, F: std::fmt::Write, Tag>( + fn p<'a, 'tcx, F: std::fmt::Write, Tag: Provenance>( cx: FmtPrinter<'a, 'tcx, F>, s: ScalarMaybeUninit, ty: Ty<'tcx>, ) -> Result, std::fmt::Error> { match s { - ScalarMaybeUninit::Scalar(s) => { - cx.pretty_print_const_scalar(s.erase_tag(), ty, true) + ScalarMaybeUninit::Scalar(Scalar::Int(int)) => { + cx.pretty_print_const_scalar_int(int, ty, true) + } + ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _sz)) => { + // Just print the ptr value. `pretty_print_const_scalar_ptr` would also try to + // print what is points to, which would fail since it has no access to the local + // memory. + cx.pretty_print_const_pointer(ptr, ty, true) } ScalarMaybeUninit::Uninit => cx.typed_value( |mut this| { @@ -120,18 +128,18 @@ impl std::fmt::Display for ImmTy<'tcx, Tag> { p(cx, s, ty)?; return Ok(()); } - write!(f, "{}: {}", s.erase_tag(), self.layout.ty) + write!(f, "{}: {}", s, self.layout.ty) } Immediate::ScalarPair(a, b) => { // FIXME(oli-obk): at least print tuples and slices nicely - write!(f, "({}, {}): {}", a.erase_tag(), b.erase_tag(), self.layout.ty,) + write!(f, "({}, {}): {}", a, b, self.layout.ty,) } } }) } } -impl<'tcx, Tag> std::ops::Deref for ImmTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> std::ops::Deref for ImmTy<'tcx, Tag> { type Target = Immediate; #[inline(always)] fn deref(&self) -> &Immediate { @@ -142,22 +150,22 @@ impl<'tcx, Tag> std::ops::Deref for ImmTy<'tcx, Tag> { /// An `Operand` is the result of computing a `mir::Operand`. It can be immediate, /// or still in memory. The latter is an optimization, to delay reading that chunk of /// memory and to avoid having to store arbitrary-sized data here. -#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)] -pub enum Operand { +#[derive(Copy, Clone, PartialEq, Eq, HashStable, Hash, Debug)] +pub enum Operand { Immediate(Immediate), Indirect(MemPlace), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct OpTy<'tcx, Tag = ()> { +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct OpTy<'tcx, Tag: Provenance = AllocId> { op: Operand, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(OpTy<'_, ()>, 80); +rustc_data_structures::static_assert_size!(OpTy<'_>, 80); -impl<'tcx, Tag> std::ops::Deref for OpTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> { type Target = Operand; #[inline(always)] fn deref(&self) -> &Operand { @@ -165,28 +173,28 @@ impl<'tcx, Tag> std::ops::Deref for OpTy<'tcx, Tag> { } } -impl<'tcx, Tag: Copy> From> for OpTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> From> for OpTy<'tcx, Tag> { #[inline(always)] fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout } } } -impl<'tcx, Tag: Copy> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> { #[inline(always)] fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self { OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout } } } -impl<'tcx, Tag> From> for OpTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> From> for OpTy<'tcx, Tag> { #[inline(always)] fn from(val: ImmTy<'tcx, Tag>) -> Self { OpTy { op: Operand::Immediate(val.imm), layout: val.layout } } } -impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> ImmTy<'tcx, Tag> { #[inline] pub fn from_scalar(val: Scalar, layout: TyAndLayout<'tcx>) -> Self { ImmTy { imm: val.into(), layout } @@ -225,19 +233,6 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - /// Normalize `place.ptr` to a `Pointer` if this is a place and not a ZST. - /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. - #[inline] - pub fn force_op_ptr( - &self, - op: &OpTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { - match op.try_as_mplace(self) { - Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()), - Err(imm) => Ok(imm.into()), // Nothing to cast/force - } - } - /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`. /// Returns `None` if the layout does not permit loading this as a value. fn try_read_immediate_from_mplace( @@ -291,7 +286,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, src: &OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Result, MPlaceTy<'tcx, M::PointerTag>>> { - Ok(match src.try_as_mplace(self) { + Ok(match src.try_as_mplace() { Ok(ref mplace) => { if let Some(val) = self.try_read_immediate_from_mplace(mplace)? { Ok(val) @@ -324,6 +319,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(self.read_immediate(op)?.to_scalar_or_uninit()) } + /// Read a pointer from a place. + pub fn read_pointer( + &self, + op: &OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, Pointer>> { + Ok(self.scalar_to_ptr(self.read_scalar(op)?.check_init()?)) + } + // Turn the wide MPlace into a string (must already be dereferenced!) pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, &str> { let len = mplace.len(self)?; @@ -338,7 +341,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { op: &OpTy<'tcx, M::PointerTag>, field: usize, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { - let base = match op.try_as_mplace(self) { + let base = match op.try_as_mplace() { Ok(ref mplace) => { // We can reuse the mplace field computation logic for indirect operands. let field = self.mplace_field(mplace, field)?; @@ -381,7 +384,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.operand_field(op, index) } else { // Indexing into a big array. This must be an mplace. - let mplace = op.assert_mem_place(self); + let mplace = op.assert_mem_place(); Ok(self.mplace_index(&mplace, index)?.into()) } } @@ -392,7 +395,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { variant: VariantIdx, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { // Downcasts only change the layout - Ok(match op.try_as_mplace(self) { + Ok(match op.try_as_mplace() { Ok(ref mplace) => self.mplace_downcast(mplace, variant)?.into(), Err(..) => { let layout = op.layout.for_variant(self, variant); @@ -414,7 +417,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Subslice { .. } | ConstantIndex { .. } | Index(_) => { // The rest should only occur as mplace, we do not use Immediates for types // allowing such operations. This matches place_projection forcing an allocation. - let mplace = base.assert_mem_place(self); + let mplace = base.assert_mem_place(); self.mplace_projection(&mplace, proj_elem)?.into() } }) @@ -569,7 +572,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Other cases need layout. let tag_scalar = |scalar| -> InterpResult<'tcx, _> { Ok(match scalar { - Scalar::Ptr(ptr) => Scalar::Ptr(self.global_base_pointer(ptr)?), + Scalar::Ptr(ptr, size) => Scalar::Ptr(self.global_base_pointer(ptr)?, size), Scalar::Int(int) => Scalar::Int(int), }) }; @@ -580,9 +583,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We rely on mutability being set correctly in that allocation to prevent writes // where none should happen. let ptr = self.global_base_pointer(Pointer::new(id, offset))?; - Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi)) + Operand::Indirect(MemPlace::from_ptr(ptr.into(), layout.align.abi)) } - ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x)?.into()), + ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x.into())?.into()), ConstValue::Slice { data, start, end } => { // We rely on mutability being set correctly in `data` to prevent writes // where none should happen. @@ -591,7 +594,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Size::from_bytes(start), // offset: `start` ); Operand::Immediate(Immediate::new_slice( - self.global_base_pointer(ptr)?.into(), + Scalar::from_pointer(self.global_base_pointer(ptr)?, &*self.tcx), u64::try_from(end.checked_sub(start).unwrap()).unwrap(), // len: `end - start` self, )) @@ -658,9 +661,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Figure out which discriminant and variant this corresponds to. Ok(match *tag_encoding { TagEncoding::Direct => { - let tag_bits = self - .force_bits(tag_val, tag_layout.size) - .map_err(|_| err_ub!(InvalidTag(tag_val.erase_tag())))?; + let tag_bits = tag_val + .try_to_int() + .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))? + .assert_bits(tag_layout.size); // Cast bits from tag layout to discriminant layout. let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty); let discr_bits = discr_val.assert_bits(discr_layout.size); @@ -677,7 +681,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"), } - .ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_tag())))?; + .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?; // Return the cast value, and the index. (discr_val, index.0) } @@ -686,18 +690,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // discriminant (encoded in niche/tag) and variant index are the same. let variants_start = niche_variants.start().as_u32(); let variants_end = niche_variants.end().as_u32(); - let variant = match tag_val.to_bits_or_ptr(tag_layout.size, self) { - Err(ptr) => { - // The niche must be just 0 (which an inbounds pointer value never is) + let variant = match tag_val.try_to_int() { + Err(dbg_val) => { + // So this is a pointer then, and casting to an int failed. + // Can only happen during CTFE. + let ptr = self.scalar_to_ptr(tag_val); + // The niche must be just 0, and the ptr not null, then we know this is + // okay. Everything else, we conservatively reject. let ptr_valid = niche_start == 0 && variants_start == variants_end && !self.memory.ptr_may_be_null(ptr); if !ptr_valid { - throw_ub!(InvalidTag(tag_val.erase_tag())) + throw_ub!(InvalidTag(dbg_val)) } dataful_variant } Ok(tag_bits) => { + let tag_bits = tag_bits.assert_bits(tag_layout.size); // We need to use machine arithmetic to get the relative variant idx: // variant_index_relative = tag_val - niche_start_val let tag_val = ImmTy::from_uint(tag_bits, tag_layout); diff --git a/compiler/rustc_mir/src/interpret/operator.rs b/compiler/rustc_mir/src/interpret/operator.rs index 3737f8781c..79b493d74e 100644 --- a/compiler/rustc_mir/src/interpret/operator.rs +++ b/compiler/rustc_mir/src/interpret/operator.rs @@ -318,8 +318,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right.layout.ty ); - let l = self.force_bits(left.to_scalar()?, left.layout.size)?; - let r = self.force_bits(right.to_scalar()?, right.layout.size)?; + let l = left.to_scalar()?.to_bits(left.layout.size)?; + let r = right.to_scalar()?.to_bits(right.layout.size)?; self.binary_int_op(bin_op, l, left.layout, r, right.layout) } _ if left.layout.ty.is_any_ptr() => { @@ -386,7 +386,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => { assert!(layout.ty.is_integral()); - let val = self.force_bits(val, layout.size)?; + let val = val.to_bits(layout.size)?; let (res, overflow) = match un_op { Not => (self.truncate(!val, layout), false), // bitwise negation, then truncate Neg => { diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs index 4c53510ed0..91fcc3495b 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_mir/src/interpret/place.rs @@ -3,7 +3,6 @@ //! All high-level functions to write to memory work on places as destinations. use std::convert::TryFrom; -use std::fmt::Debug; use std::hash::Hash; use rustc_ast::Mutability; @@ -15,14 +14,14 @@ use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding}; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants}; use super::{ - alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, ConstAlloc, ImmTy, Immediate, - InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, Operand, Pointer, - PointerArithmetic, Scalar, ScalarMaybeUninit, + alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, + ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, LocalValue, Machine, MemoryKind, OpTy, + Operand, Pointer, PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, }; -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)] +#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] /// Information required for the sound usage of a `MemPlace`. -pub enum MemPlaceMeta { +pub enum MemPlaceMeta { /// The unsized payload (e.g. length for slices or vtable pointer for trait objects). Meta(Scalar), /// `Sized` types or unsized `extern type` @@ -37,7 +36,7 @@ pub enum MemPlaceMeta { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(MemPlaceMeta, 24); -impl MemPlaceMeta { +impl MemPlaceMeta { pub fn unwrap_meta(self) -> Scalar { match self { Self::Meta(s) => s, @@ -52,22 +51,12 @@ impl MemPlaceMeta { Self::None | Self::Poison => false, } } - - pub fn erase_tag(self) -> MemPlaceMeta<()> { - match self { - Self::Meta(s) => MemPlaceMeta::Meta(s.erase_tag()), - Self::None => MemPlaceMeta::None, - Self::Poison => MemPlaceMeta::Poison, - } - } } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)] -pub struct MemPlace { - /// A place may have an integral pointer for ZSTs, and since it might - /// be turned back into a reference before ever being dereferenced. - /// However, it may never be uninit. - pub ptr: Scalar, +#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] +pub struct MemPlace { + /// The pointer can be a pure integer, with the `None` tag. + pub ptr: Pointer>, pub align: Align, /// Metadata for unsized places. Interpretation is up to the type. /// Must not be present for sized types, but can be missing for unsized types @@ -76,10 +65,10 @@ pub struct MemPlace { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MemPlace, 56); +rustc_data_structures::static_assert_size!(MemPlace, 48); -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)] -pub enum Place { +#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)] +pub enum Place { /// A place referring to a value allocated in the `Memory` system. Ptr(MemPlace), @@ -89,18 +78,18 @@ pub enum Place { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Place, 64); +rustc_data_structures::static_assert_size!(Place, 56); #[derive(Copy, Clone, Debug)] -pub struct PlaceTy<'tcx, Tag = ()> { +pub struct PlaceTy<'tcx, Tag: Provenance = AllocId> { place: Place, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(PlaceTy<'_>, 80); +rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72); -impl<'tcx, Tag> std::ops::Deref for PlaceTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> std::ops::Deref for PlaceTy<'tcx, Tag> { type Target = Place; #[inline(always)] fn deref(&self) -> &Place { @@ -109,16 +98,16 @@ impl<'tcx, Tag> std::ops::Deref for PlaceTy<'tcx, Tag> { } /// A MemPlace with its layout. Constructing it is only possible in this module. -#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] -pub struct MPlaceTy<'tcx, Tag = ()> { +#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] +pub struct MPlaceTy<'tcx, Tag: Provenance = AllocId> { mplace: MemPlace, pub layout: TyAndLayout<'tcx>, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 72); +rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64); -impl<'tcx, Tag> std::ops::Deref for MPlaceTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> std::ops::Deref for MPlaceTy<'tcx, Tag> { type Target = MemPlace; #[inline(always)] fn deref(&self) -> &MemPlace { @@ -126,42 +115,33 @@ impl<'tcx, Tag> std::ops::Deref for MPlaceTy<'tcx, Tag> { } } -impl<'tcx, Tag> From> for PlaceTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> From> for PlaceTy<'tcx, Tag> { #[inline(always)] fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self { PlaceTy { place: Place::Ptr(mplace.mplace), layout: mplace.layout } } } -impl MemPlace { - /// Replace ptr tag, maintain vtable tag (if any) - #[inline] - pub fn replace_tag(self, new_tag: Tag) -> Self { - MemPlace { ptr: self.ptr.erase_tag().with_tag(new_tag), align: self.align, meta: self.meta } - } - - #[inline] - pub fn erase_tag(self) -> MemPlace { - MemPlace { ptr: self.ptr.erase_tag(), align: self.align, meta: self.meta.erase_tag() } - } - +impl MemPlace { #[inline(always)] - fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { + pub fn from_ptr(ptr: Pointer>, align: Align) -> Self { MemPlace { ptr, align, meta: MemPlaceMeta::None } } - #[inline(always)] - pub fn from_ptr(ptr: Pointer, align: Align) -> Self { - Self::from_scalar_ptr(ptr.into(), align) + /// Adjust the provenance of the main pointer (metadata is unaffected). + pub fn map_provenance(self, f: impl FnOnce(Option) -> Option) -> Self { + MemPlace { ptr: self.ptr.map_provenance(f), ..self } } /// Turn a mplace into a (thin or wide) pointer, as a reference, pointing to the same space. /// This is the inverse of `ref_to_mplace`. #[inline(always)] - pub fn to_ref(self) -> Immediate { + pub fn to_ref(self, cx: &impl HasDataLayout) -> Immediate { match self.meta { - MemPlaceMeta::None => Immediate::Scalar(self.ptr.into()), - MemPlaceMeta::Meta(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()), + MemPlaceMeta::None => Immediate::from(Scalar::from_maybe_pointer(self.ptr, cx)), + MemPlaceMeta::Meta(meta) => { + Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx).into(), meta.into()) + } MemPlaceMeta::Poison => bug!( "MPlaceTy::dangling may never be used to produce a \ place that will have the address of its pointee taken" @@ -177,29 +157,23 @@ impl MemPlace { cx: &impl HasDataLayout, ) -> InterpResult<'tcx, Self> { Ok(MemPlace { - ptr: self.ptr.ptr_offset(offset, cx)?, + ptr: self.ptr.offset(offset, cx)?, align: self.align.restrict_for_offset(offset), meta, }) } } -impl<'tcx, Tag: Copy> MPlaceTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> { /// Produces a MemPlace that works for ZST but nothing else #[inline] - pub fn dangling(layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout) -> Self { + pub fn dangling(layout: TyAndLayout<'tcx>) -> Self { let align = layout.align.abi; - let ptr = Scalar::from_machine_usize(align.bytes(), cx); + let ptr = Pointer::new(None, Size::from_bytes(align.bytes())); // no provenance, absolute address // `Poison` this to make sure that the pointer value `ptr` is never observable by the program. MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout } } - /// Replace ptr tag, maintain vtable tag (if any) - #[inline] - pub fn replace_tag(&self, new_tag: Tag) -> Self { - MPlaceTy { mplace: self.mplace.replace_tag(new_tag), layout: self.layout } - } - #[inline] pub fn offset( &self, @@ -212,7 +186,7 @@ impl<'tcx, Tag: Copy> MPlaceTy<'tcx, Tag> { } #[inline] - fn from_aligned_ptr(ptr: Pointer, layout: TyAndLayout<'tcx>) -> Self { + pub fn from_aligned_ptr(ptr: Pointer>, layout: TyAndLayout<'tcx>) -> Self { MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout } } @@ -244,19 +218,14 @@ impl<'tcx, Tag: Copy> MPlaceTy<'tcx, Tag> { } // These are defined here because they produce a place. -impl<'tcx, Tag: Debug + Copy> OpTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> { #[inline(always)] /// Note: do not call `as_ref` on the resulting place. This function should only be used to /// read from the resulting mplace, not to get its address back. - pub fn try_as_mplace( - &self, - cx: &impl HasDataLayout, - ) -> Result, ImmTy<'tcx, Tag>> { + pub fn try_as_mplace(&self) -> Result, ImmTy<'tcx, Tag>> { match **self { Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }), - Operand::Immediate(_) if self.layout.is_zst() => { - Ok(MPlaceTy::dangling(self.layout, cx)) - } + Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout)), Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)), } } @@ -264,12 +233,12 @@ impl<'tcx, Tag: Debug + Copy> OpTy<'tcx, Tag> { #[inline(always)] /// Note: do not call `as_ref` on the resulting place. This function should only be used to /// read from the resulting mplace, not to get its address back. - pub fn assert_mem_place(&self, cx: &impl HasDataLayout) -> MPlaceTy<'tcx, Tag> { - self.try_as_mplace(cx).unwrap() + pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Tag> { + self.try_as_mplace().unwrap() } } -impl Place { +impl Place { #[inline] pub fn assert_mem_place(self) -> MemPlace { match self { @@ -279,7 +248,7 @@ impl Place { } } -impl<'tcx, Tag: Debug> PlaceTy<'tcx, Tag> { +impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> { #[inline] pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> { MPlaceTy { mplace: self.place.assert_mem_place(), layout: self.layout } @@ -290,7 +259,7 @@ impl<'tcx, Tag: Debug> PlaceTy<'tcx, Tag> { impl<'mir, 'tcx: 'mir, Tag, M> InterpCx<'mir, 'tcx, M> where // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 - Tag: Debug + Copy + Eq + Hash + 'static, + Tag: Provenance + Eq + Hash + 'static, M: Machine<'mir, 'tcx, PointerTag = Tag>, { /// Take a value, which represents a (thin or wide) reference, and make it a place. @@ -307,14 +276,12 @@ where val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty; let layout = self.layout_of(pointee_type)?; let (ptr, meta) = match **val { - Immediate::Scalar(ptr) => (ptr.check_init()?, MemPlaceMeta::None), - Immediate::ScalarPair(ptr, meta) => { - (ptr.check_init()?, MemPlaceMeta::Meta(meta.check_init()?)) - } + Immediate::Scalar(ptr) => (ptr, MemPlaceMeta::None), + Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta.check_init()?)), }; let mplace = MemPlace { - ptr, + ptr: self.scalar_to_ptr(ptr.check_init()?), // We could use the run-time alignment here. For now, we do not, because // the point of tracking the alignment here is to make sure that the *static* // alignment information emitted with the loads is correct. The run-time @@ -333,8 +300,9 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let val = self.read_immediate(src)?; trace!("deref to {} on {:?}", val.layout.ty, *val); - let place = self.ref_to_mplace(&val)?; - self.mplace_access_checked(place, None) + let mplace = self.ref_to_mplace(&val)?; + self.check_mplace_access(mplace, CheckInAllocMsg::DerefTest)?; + Ok(mplace) } #[inline] @@ -359,38 +327,19 @@ where self.memory.get_mut(place.ptr, size, place.align) } - /// Return the "access-checked" version of this `MPlace`, where for non-ZST - /// this is definitely a `Pointer`. - /// - /// `force_align` must only be used when correct alignment does not matter, - /// like in Stacked Borrows. - pub fn mplace_access_checked( + /// Check if this mplace is dereferencable and sufficiently aligned. + fn check_mplace_access( &self, - mut place: MPlaceTy<'tcx, M::PointerTag>, - force_align: Option, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + mplace: MPlaceTy<'tcx, M::PointerTag>, + msg: CheckInAllocMsg, + ) -> InterpResult<'tcx> { let (size, align) = self - .size_and_align_of_mplace(&place)? - .unwrap_or((place.layout.size, place.layout.align.abi)); - assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?"); - let align = force_align.unwrap_or(align); - // Record new (stricter, unless forced) alignment requirement in place. - place.mplace.align = align; - // When dereferencing a pointer, it must be non-null, aligned, and live. - if let Some(ptr) = self.memory.check_ptr_access(place.ptr, size, align)? { - place.mplace.ptr = ptr.into(); - } - Ok(place) - } - - /// Force `place.ptr` to a `Pointer`. - /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. - pub(super) fn force_mplace_ptr( - &self, - mut place: MPlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { - place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into(); - Ok(place) + .size_and_align_of_mplace(&mplace)? + .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?"); + let align = M::enforce_alignment(&self.memory.extra).then_some(align); + self.memory.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; + Ok(()) } /// Offset a pointer to project to a field of a struct/union. Unlike `place_field`, this is @@ -558,10 +507,7 @@ where let layout = self.layout_of(self.tcx.types.usize)?; let n = self.access_local(self.frame(), local, Some(layout))?; let n = self.read_scalar(&n)?; - let n = u64::try_from( - self.force_bits(n.check_init()?, self.tcx.data_layout.pointer_size)?, - ) - .unwrap(); + let n = n.to_machine_usize(self)?; self.mplace_index(base, n)? } @@ -677,16 +623,6 @@ where Ok(place_ty) } - /// Write a scalar to a place - #[inline(always)] - pub fn write_scalar( - &mut self, - val: impl Into>, - dest: &PlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - self.write_immediate(Immediate::Scalar(val.into()), dest) - } - /// Write an immediate to a place #[inline(always)] pub fn write_immediate( @@ -704,21 +640,24 @@ where Ok(()) } - /// Write an `Immediate` to memory. + /// Write a scalar to a place #[inline(always)] - pub fn write_immediate_to_mplace( + pub fn write_scalar( &mut self, - src: Immediate, - dest: &MPlaceTy<'tcx, M::PointerTag>, + val: impl Into>, + dest: &PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { - self.write_immediate_to_mplace_no_validate(src, dest)?; - - if M::enforce_validity(self) { - // Data got changed, better make sure it matches the type! - self.validate_operand(&dest.into())?; - } + self.write_immediate(Immediate::Scalar(val.into()), dest) + } - Ok(()) + /// Write a pointer to a place + #[inline(always)] + pub fn write_pointer( + &mut self, + ptr: impl Into>>, + dest: &PlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx> { + self.write_scalar(Scalar::from_maybe_pointer(ptr.into(), self), dest) } /// Write an immediate to a place. @@ -733,7 +672,7 @@ where // This is a very common path, avoid some checks in release mode assert!(!dest.layout.is_unsized(), "Cannot write unsized data"); match src { - Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::Ptr(_))) => assert_eq!( + Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::Ptr(..))) => assert_eq!( self.pointer_size(), dest.layout.size, "Size mismatch when writing pointer" @@ -982,7 +921,7 @@ where let (size, align) = self .size_and_align_of(&meta, &local_layout)? .expect("Cannot allocate for non-dyn-sized type"); - let ptr = self.memory.allocate(size, align, MemoryKind::Stack); + let ptr = self.memory.allocate(size, align, MemoryKind::Stack)?; let mplace = MemPlace { ptr: ptr.into(), align, meta }; if let LocalValue::Live(Operand::Immediate(value)) = local_val { // Preserve old value. @@ -1018,9 +957,9 @@ where &mut self, layout: TyAndLayout<'tcx>, kind: MemoryKind, - ) -> MPlaceTy<'tcx, M::PointerTag> { - let ptr = self.memory.allocate(layout.size, layout.align.abi, kind); - MPlaceTy::from_aligned_ptr(ptr, layout) + ) -> InterpResult<'static, MPlaceTy<'tcx, M::PointerTag>> { + let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; + Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout)) } /// Returns a wide MPlace of type `&'static [mut] str` to a new 1-aligned allocation. @@ -1125,7 +1064,7 @@ where let _ = self.tcx.global_alloc(raw.alloc_id); let ptr = self.global_base_pointer(Pointer::from(raw.alloc_id))?; let layout = self.layout_of(raw.ty)?; - Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) + Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout)) } /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type. @@ -1134,7 +1073,7 @@ where &self, mplace: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> { - let vtable = mplace.vtable(); // also sanity checks the type + let vtable = self.scalar_to_ptr(mplace.vtable()); // also sanity checks the type let (instance, ty) = self.read_drop_type_from_vtable(vtable)?; let layout = self.layout_of(ty)?; diff --git a/compiler/rustc_mir/src/interpret/step.rs b/compiler/rustc_mir/src/interpret/step.rs index 129dd8f8e0..f2a8a067df 100644 --- a/compiler/rustc_mir/src/interpret/step.rs +++ b/compiler/rustc_mir/src/interpret/step.rs @@ -162,9 +162,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { use rustc_middle::mir::Rvalue::*; match *rvalue { ThreadLocalRef(did) => { - let id = M::thread_local_static_alloc_id(self, did)?; - let val = self.global_base_pointer(id.into())?; - self.write_scalar(val, &dest)?; + let ptr = M::thread_local_static_base_pointer(self, did)?; + self.write_pointer(ptr, &dest)?; } Use(ref operand) => { @@ -240,7 +239,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // of the first element. let elem_size = first.layout.size; let first_ptr = first.ptr; - let rest_ptr = first_ptr.ptr_offset(elem_size, self)?; + let rest_ptr = first_ptr.offset(elem_size, self)?; self.memory.copy_repeatedly( first_ptr, first.align, @@ -264,11 +263,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { AddressOf(_, place) | Ref(_, _, place) => { let src = self.eval_place(place)?; let place = self.force_allocation(&src)?; - if place.layout.size.bytes() > 0 { - // definitely not a ZST - assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`"); - } - self.write_immediate(place.to_ref(), &dest)?; + self.write_immediate(place.to_ref(self), &dest)?; } NullaryOp(mir::NullOp::Box, _) => { diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs index a5bdeb55e7..f369480d95 100644 --- a/compiler/rustc_mir/src/interpret/terminator.rs +++ b/compiler/rustc_mir/src/interpret/terminator.rs @@ -12,8 +12,8 @@ use rustc_target::abi::{self, LayoutOf as _}; use rustc_target::spec::abi::Abi; use super::{ - FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, StackPopCleanup, - StackPopUnwind, + FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Scalar, + StackPopCleanup, StackPopUnwind, }; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { @@ -72,8 +72,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (fn_val, abi, caller_can_unwind) = match *func.layout.ty.kind() { ty::FnPtr(sig) => { let caller_abi = sig.abi(); - let fn_ptr = self.read_scalar(&func)?.check_init()?; - let fn_val = self.memory.get_fn(fn_ptr)?; + let fn_ptr = self.read_pointer(&func)?; + let fn_val = self.memory.get_fn(fn_ptr.into())?; ( fn_val, caller_abi, @@ -454,12 +454,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } None => { // Unsized self. - args[0].assert_mem_place(self) + args[0].assert_mem_place() } }; // Find and consult vtable - let vtable = receiver_place.vtable(); - let drop_fn = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; + let vtable = self.scalar_to_ptr(receiver_place.vtable()); + let fn_val = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; // `*mut receiver_place.layout.ty` is almost the layout that we // want for args[0]: We have to project to field 0 because we want @@ -468,11 +468,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty); let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?; // Adjust receiver argument. - args[0] = - OpTy::from(ImmTy::from_immediate(receiver_place.ptr.into(), this_receiver_ptr)); + args[0] = OpTy::from(ImmTy::from_immediate( + Scalar::from_maybe_pointer(receiver_place.ptr, self).into(), + this_receiver_ptr, + )); trace!("Patched self operand to {:#?}", args[0]); // recurse with concrete function - self.eval_fn_call(drop_fn, caller_abi, &args, ret, unwind) + self.eval_fn_call(fn_val, caller_abi, &args, ret, unwind) } } } @@ -499,12 +501,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; let arg = ImmTy::from_immediate( - place.to_ref(), + place.to_ref(self), self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?, ); let ty = self.tcx.mk_unit(); // return type is () - let dest = MPlaceTy::dangling(self.layout_of(ty)?, self); + let dest = MPlaceTy::dangling(self.layout_of(ty)?); self.eval_fn_call( FnVal::Instance(instance), diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_mir/src/interpret/traits.rs index d0c04b5b41..7a93fcee78 100644 --- a/compiler/rustc_mir/src/interpret/traits.rs +++ b/compiler/rustc_mir/src/interpret/traits.rs @@ -1,11 +1,14 @@ use std::convert::TryFrom; -use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar}; -use rustc_middle::ty::{self, Instance, Ty}; -use rustc_target::abi::{Align, LayoutOf, Size}; +use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic}; +use rustc_middle::ty::{ + self, Ty, COMMON_VTABLE_ENTRIES, COMMON_VTABLE_ENTRIES_ALIGN, + COMMON_VTABLE_ENTRIES_DROPINPLACE, COMMON_VTABLE_ENTRIES_SIZE, +}; +use rustc_target::abi::{Align, Size}; use super::util::ensure_monomorphic_enough; -use super::{FnVal, InterpCx, Machine, MemoryKind}; +use super::{FnVal, InterpCx, Machine}; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Creates a dynamic vtable for the given type and vtable origin. This is used only for @@ -27,145 +30,94 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ensure_monomorphic_enough(*self.tcx, ty)?; ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?; - if let Some(&vtable) = self.vtables.get(&(ty, poly_trait_ref)) { - // This means we guarantee that there are no duplicate vtables, we will - // always use the same vtable for the same (Type, Trait) combination. - // That's not what happens in rustc, but emulating per-crate deduplication - // does not sound like it actually makes anything any better. - return Ok(vtable); - } - - let methods = if let Some(poly_trait_ref) = poly_trait_ref { - let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); - let trait_ref = self.tcx.erase_regions(trait_ref); - - self.tcx.vtable_methods(trait_ref) - } else { - &[] - }; - - let layout = self.layout_of(ty)?; - assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); - let size = layout.size.bytes(); - let align = layout.align.abi.bytes(); - - let tcx = *self.tcx; - let ptr_size = self.pointer_size(); - let ptr_align = tcx.data_layout.pointer_align.abi; - // ///////////////////////////////////////////////////////////////////////////////////////// - // If you touch this code, be sure to also make the corresponding changes to - // `get_vtable` in `rust_codegen_llvm/meth.rs`. - // ///////////////////////////////////////////////////////////////////////////////////////// - let vtable_size = ptr_size * u64::try_from(methods.len()).unwrap().checked_add(3).unwrap(); - let vtable = self.memory.allocate(vtable_size, ptr_align, MemoryKind::Vtable); - - let drop = Instance::resolve_drop_in_place(tcx, ty); - let drop = self.memory.create_fn_alloc(FnVal::Instance(drop)); + let vtable_allocation = self.tcx.vtable_allocation(ty, poly_trait_ref); - // Prepare the fn ptrs we will write into the vtable later. - let fn_ptrs = methods - .iter() - .enumerate() // remember the original position - .filter_map(|(i, method)| { - if let Some((def_id, substs)) = method { Some((i, def_id, substs)) } else { None } - }) - .map(|(i, def_id, substs)| { - let instance = - ty::Instance::resolve_for_vtable(tcx, self.param_env, *def_id, substs) - .ok_or_else(|| err_inval!(TooGeneric))?; - Ok((i, self.memory.create_fn_alloc(FnVal::Instance(instance)))) - }) - .collect::)>>>()?; + let vtable_ptr = self.memory.global_base_pointer(Pointer::from(vtable_allocation))?; - // No need to do any alignment checks on the memory accesses below, because we know the - // allocation is correctly aligned as we created it above. Also we're only offsetting by - // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. - let mut vtable_alloc = - self.memory.get_mut(vtable.into(), vtable_size, ptr_align)?.expect("not a ZST"); - vtable_alloc.write_ptr_sized(ptr_size * 0, drop.into())?; - vtable_alloc.write_ptr_sized(ptr_size * 1, Scalar::from_uint(size, ptr_size).into())?; - vtable_alloc.write_ptr_sized(ptr_size * 2, Scalar::from_uint(align, ptr_size).into())?; - - for (i, fn_ptr) in fn_ptrs.into_iter() { - vtable_alloc.write_ptr_sized(ptr_size * (3 + i as u64), fn_ptr.into())?; - } - - M::after_static_mem_initialized(self, vtable, vtable_size)?; - - self.memory.mark_immutable(vtable.alloc_id)?; - assert!(self.vtables.insert((ty, poly_trait_ref), vtable).is_none()); - - Ok(vtable) + Ok(vtable_ptr) } /// Resolves the function at the specified slot in the provided - /// vtable. An index of '0' corresponds to the first method - /// declared in the trait of the provided vtable. + /// vtable. Currently an index of '3' (`COMMON_VTABLE_ENTRIES.len()`) + /// corresponds to the first method declared in the trait of the provided vtable. pub fn get_vtable_slot( &self, - vtable: Scalar, + vtable: Pointer>, idx: u64, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { let ptr_size = self.pointer_size(); - // Skip over the 'drop_ptr', 'size', and 'align' fields. - let vtable_slot = vtable.ptr_offset(ptr_size * idx.checked_add(3).unwrap(), self)?; + let vtable_slot = vtable.offset(ptr_size * idx, self)?; let vtable_slot = self .memory .get(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); - let fn_ptr = vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?; + let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?); self.memory.get_fn(fn_ptr) } /// Returns the drop fn instance as well as the actual dynamic type. pub fn read_drop_type_from_vtable( &self, - vtable: Scalar, + vtable: Pointer>, ) -> InterpResult<'tcx, (ty::Instance<'tcx>, Ty<'tcx>)> { + let pointer_size = self.pointer_size(); // We don't care about the pointee type; we just want a pointer. let vtable = self .memory - .get(vtable, self.tcx.data_layout.pointer_size, self.tcx.data_layout.pointer_align.abi)? + .get( + vtable, + pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(), + self.tcx.data_layout.pointer_align.abi, + )? .expect("cannot be a ZST"); - let drop_fn = vtable.read_ptr_sized(Size::ZERO)?.check_init()?; + let drop_fn = vtable + .read_ptr_sized( + pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_DROPINPLACE).unwrap(), + )? + .check_init()?; // We *need* an instance here, no other kind of function value, to be able // to determine the type. - let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?; + let drop_instance = self.memory.get_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; trace!("Found drop fn: {:?}", drop_instance); let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig); // The drop function takes `*mut T` where `T` is the type being dropped, so get that. let args = fn_sig.inputs(); if args.len() != 1 { - throw_ub!(InvalidDropFn(fn_sig)); + throw_ub!(InvalidVtableDropFn(fn_sig)); } - let ty = args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?.ty; + let ty = + args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidVtableDropFn(fn_sig)))?.ty; Ok((drop_instance, ty)) } pub fn read_size_and_align_from_vtable( &self, - vtable: Scalar, + vtable: Pointer>, ) -> InterpResult<'tcx, (Size, Align)> { let pointer_size = self.pointer_size(); // We check for `size = 3 * ptr_size`, which covers the drop fn (unused here), // the size, and the align (which we read below). let vtable = self .memory - .get(vtable, 3 * pointer_size, self.tcx.data_layout.pointer_align.abi)? + .get( + vtable, + pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(), + self.tcx.data_layout.pointer_align.abi, + )? .expect("cannot be a ZST"); - let size = vtable.read_ptr_sized(pointer_size)?.check_init()?; - let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap(); - let align = vtable.read_ptr_sized(pointer_size * 2)?.check_init()?; - let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap(); - let align = Align::from_bytes(align) - .map_err(|e| err_ub_format!("invalid vtable: alignment {}", e))?; + let size = vtable + .read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap())? + .check_init()?; + let size = size.to_machine_usize(self)?; + let align = vtable + .read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap())? + .check_init()?; + let align = align.to_machine_usize(self)?; + let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?; if size >= self.tcx.data_layout.obj_size_bound() { - throw_ub_format!( - "invalid vtable: \ - size is bigger than largest supported object" - ); + throw_ub!(InvalidVtableSize); } Ok((Size::from_bytes(size), align)) } diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs index fb165a991b..0c7f89c1a3 100644 --- a/compiler/rustc_mir/src/interpret/validity.rs +++ b/compiler/rustc_mir/src/interpret/validity.rs @@ -21,28 +21,29 @@ use std::hash::Hash; use super::{ alloc_range, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, - MemPlaceMeta, OpTy, Scalar, ScalarMaybeUninit, ValueVisitor, + MemPlaceMeta, OpTy, ScalarMaybeUninit, ValueVisitor, }; macro_rules! throw_validation_failure { ($where:expr, { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )?) => {{ - let msg = rustc_middle::ty::print::with_no_trimmed_paths(|| { - let mut msg = String::new(); - msg.push_str("encountered "); - write!(&mut msg, $($what_fmt),+).unwrap(); + let mut msg = String::new(); + msg.push_str("encountered "); + write!(&mut msg, $($what_fmt),+).unwrap(); + $( + msg.push_str(", but expected "); + write!(&mut msg, $($expected_fmt),+).unwrap(); + )? + let path = rustc_middle::ty::print::with_no_trimmed_paths(|| { let where_ = &$where; if !where_.is_empty() { - msg.push_str(" at "); - write_path(&mut msg, where_); + let mut path = String::new(); + write_path(&mut path, where_); + Some(path) + } else { + None } - $( - msg.push_str(", but expected "); - write!(&mut msg, $($expected_fmt),+).unwrap(); - )? - - msg }); - throw_ub!(ValidationFailure(msg)) + throw_ub!(ValidationFailure { path, msg }) }}; } @@ -323,7 +324,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); match tail.kind() { ty::Dynamic(..) => { - let vtable = meta.unwrap_meta(); + let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta()); // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( self.ecx.memory.check_ptr_access_align( @@ -334,8 +335,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' ), self.path, err_ub!(DanglingIntPointer(..)) | - err_ub!(PointerUseAfterFree(..)) | - err_unsup!(ReadBytesAsPointer) => + err_ub!(PointerUseAfterFree(..)) => { "dangling vtable pointer in wide pointer" }, err_ub!(AlignmentCheckFailed { .. }) => { "unaligned vtable pointer in wide pointer" }, @@ -346,15 +346,18 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' self.ecx.read_drop_type_from_vtable(vtable), self.path, err_ub!(DanglingIntPointer(..)) | - err_ub!(InvalidFunctionPointer(..)) | - err_unsup!(ReadBytesAsPointer) => + err_ub!(InvalidFunctionPointer(..)) => { "invalid drop function pointer in vtable (not pointing to a function)" }, - err_ub!(InvalidDropFn(..)) => + err_ub!(InvalidVtableDropFn(..)) => { "invalid drop function pointer in vtable (function has incompatible signature)" }, ); try_validation!( self.ecx.read_size_and_align_from_vtable(vtable), self.path, + err_ub!(InvalidVtableSize) => + { "invalid vtable: size is bigger than largest supported object" }, + err_ub!(InvalidVtableAlignment(msg)) => + { "invalid vtable: alignment {}", msg }, err_unsup!(ReadPointerAsBytes) => { "invalid size or align in vtable" }, ); // FIXME: More checks for the vtable. @@ -432,8 +435,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' { "a dangling {} (address 0x{:x} is unallocated)", kind, i }, err_ub!(PointerOutOfBounds { .. }) => { "a dangling {} (going beyond the bounds of its allocation)", kind }, - err_unsup!(ReadBytesAsPointer) => - { "a dangling {} (created from integer)", kind }, // This cannot happen during const-eval (because interning already detects // dangling pointers), but it can happen in Miri. err_ub!(PointerUseAfterFree(..)) => @@ -443,17 +444,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' if let Some(ref mut ref_tracking) = self.ref_tracking { // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. - // Normalize before handing `place` to tracking because that will - // check for duplicates. - let place = if size.bytes() > 0 { - self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") - } else { - place - }; // Skip validation entirely for some external statics - if let Scalar::Ptr(ptr) = place.ptr { + if let Ok((alloc_id, _offset, _ptr)) = self.ecx.memory.ptr_try_get_alloc(place.ptr) { // not a ZST - let alloc_kind = self.ecx.tcx.get_global_alloc(ptr.alloc_id); + let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id); if let Some(GlobalAlloc::Static(did)) = alloc_kind { assert!(!self.ecx.tcx.is_thread_local_static(did)); assert!(self.ecx.tcx.is_static(did)); @@ -541,7 +535,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // types below! if self.ctfe_mode.is_some() { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous - let is_bits = value.check_init().map_or(false, |v| v.is_bits()); + let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok()); if !is_bits { throw_validation_failure!(self.path, { "{}", value } expected { "initialized plain (non-pointer) bytes" } @@ -596,12 +590,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // message below. let value = value.to_scalar_or_uninit(); let _fn = try_validation!( - value.check_init().and_then(|ptr| self.ecx.memory.get_fn(ptr)), + value.check_init().and_then(|ptr| self.ecx.memory.get_fn(self.ecx.scalar_to_ptr(ptr))), self.path, err_ub!(DanglingIntPointer(..)) | err_ub!(InvalidFunctionPointer(..)) | - err_ub!(InvalidUninitBytes(None)) | - err_unsup!(ReadBytesAsPointer) => + err_ub!(InvalidUninitBytes(None)) => { "{}", value } expected { "a function pointer" }, ); // FIXME: Check if the signature matches @@ -659,8 +652,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' err_ub!(InvalidUninitBytes(None)) => { "{}", value } expected { "something {}", wrapping_range_format(valid_range, max_hi) }, ); - let bits = match value.to_bits_or_ptr(op.layout.size, self.ecx) { - Err(ptr) => { + let bits = match value.try_to_int() { + Err(_) => { + // So this is a pointer then, and casting to an int failed. + // Can only happen during CTFE. + let ptr = self.ecx.scalar_to_ptr(value); if lo == 1 && hi == max_hi { // Only null is the niche. So make sure the ptr is NOT null. if self.ecx.memory.ptr_may_be_null(ptr) { @@ -685,7 +681,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' ) } } - Ok(data) => data, + Ok(int) => int.assert_bits(op.layout.size), }; // Now compare. This is slightly subtle because this is a special "wrap-around" range. if wrapping_range_contains(&valid_range, bits) { @@ -827,7 +823,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ) -> InterpResult<'tcx> { match op.layout.ty.kind() { ty::Str => { - let mplace = op.assert_mem_place(self.ecx); // strings are never immediate + let mplace = op.assert_mem_place(); // strings are never immediate let len = mplace.len(self.ecx)?; try_validation!( self.ecx.memory.read_bytes(mplace.ptr, Size::from_bytes(len)), @@ -848,7 +844,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // Optimized handling for arrays of integer/float type. // Arrays cannot be immediate, slices are never immediate. - let mplace = op.assert_mem_place(self.ecx); + let mplace = op.assert_mem_place(); // This is the length of the array/slice. let len = mplace.len(self.ecx)?; // This is the element type size. @@ -935,9 +931,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Construct a visitor let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self }; - // Try to cast to ptr *once* instead of all the time. - let op = self.force_op_ptr(&op).unwrap_or(*op); - // Run it. match visitor.visit_value(&op) { Ok(()) => Ok(()), diff --git a/compiler/rustc_mir/src/interpret/visitor.rs b/compiler/rustc_mir/src/interpret/visitor.rs index 32edca6f3d..679d30227f 100644 --- a/compiler/rustc_mir/src/interpret/visitor.rs +++ b/compiler/rustc_mir/src/interpret/visitor.rs @@ -211,7 +211,8 @@ macro_rules! make_value_visitor { // If it is a trait object, switch to the real type that was used to create it. ty::Dynamic(..) => { // immediate trait objects are not a thing - let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx()); + let op = v.to_op(self.ecx())?; + let dest = op.assert_mem_place(); let inner = self.ecx().unpack_dyn_trait(&dest)?.1; trace!("walk_value: dyn object layout: {:#?}", inner.layout); // recurse with the inner type @@ -241,7 +242,8 @@ macro_rules! make_value_visitor { }, FieldsShape::Array { .. } => { // Let's get an mplace first. - let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx()); + let op = v.to_op(self.ecx())?; + let mplace = op.assert_mem_place(); // Now we can go over all the fields. // This uses the *run-time length*, i.e., if we are a slice, // the dynamic info from the metadata is used. diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index 1da17bddcb..a58ded9cfd 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -29,6 +29,7 @@ Rust MIR: a lowered representation of Rust. #![feature(option_get_or_insert_default)] #![feature(once_cell)] #![feature(control_flow_enum)] +#![feature(try_reserve)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 31cb5484bc..2ce7cf7111 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -196,10 +196,11 @@ use rustc_middle::mir::{self, Local, Location}; use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; -use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, VtblEntry}; use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext}; use rustc_session::config::EntryFnType; use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; +use rustc_session::Limit; use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; use rustc_target::abi::Size; use smallvec::SmallVec; @@ -294,6 +295,7 @@ pub fn collect_crate_mono_items( let mut visited = MTLock::new(FxHashSet::default()); let mut inlining_map = MTLock::new(InliningMap::new()); + let recursion_limit = tcx.recursion_limit(); { let visited: MTRef<'_, _> = &mut visited; @@ -307,6 +309,7 @@ pub fn collect_crate_mono_items( dummy_spanned(root), visited, &mut recursion_depths, + recursion_limit, inlining_map, ); }); @@ -350,6 +353,7 @@ fn collect_items_rec<'tcx>( starting_point: Spanned>, visited: MTRef<'_, MTLock>>>, recursion_depths: &mut DefIdMap, + recursion_limit: Limit, inlining_map: MTRef<'_, MTLock>>, ) { if !visited.lock_mut().insert(starting_point.node) { @@ -399,7 +403,7 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; if let Ok(alloc) = tcx.eval_static_initializer(def_id) { - for &((), id) in alloc.relocations().values() { + for &id in alloc.relocations().values() { collect_miri(tcx, id, &mut neighbors); } } @@ -409,8 +413,13 @@ fn collect_items_rec<'tcx>( debug_assert!(should_codegen_locally(tcx, &instance)); // Keep track of the monomorphization recursion depth - recursion_depth_reset = - Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths)); + recursion_depth_reset = Some(check_recursion_limit( + tcx, + instance, + starting_point.span, + recursion_depths, + recursion_limit, + )); check_type_length_limit(tcx, instance); rustc_data_structures::stack::ensure_sufficient_stack(|| { @@ -455,7 +464,7 @@ fn collect_items_rec<'tcx>( record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map); for neighbour in neighbors { - collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map); + collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map); } if let Some((def_id, depth)) = recursion_depth_reset { @@ -523,6 +532,7 @@ fn check_recursion_limit<'tcx>( instance: Instance<'tcx>, span: Span, recursion_depths: &mut DefIdMap, + recursion_limit: Limit, ) -> (DefId, usize) { let def_id = instance.def_id(); let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0); @@ -539,7 +549,7 @@ fn check_recursion_limit<'tcx>( // Code that needs to instantiate the same function recursively // more than the recursion limit is assumed to be causing an // infinite expansion. - if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) { + if !recursion_limit.value_within_limit(adjusted_recursion_depth) { let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32); let error = format!("reached the recursion limit while instantiating `{}`", shrunk); let mut err = tcx.sess.struct_span_fatal(span, &error); @@ -577,7 +587,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // which means that rustc basically hangs. // // Bail out in these cases to avoid that bad user experience. - if !tcx.sess.type_length_limit().value_within_limit(type_length) { + if !tcx.type_length_limit().value_within_limit(type_length) { let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32); let msg = format!("reached the type-length limit while instantiating `{}`", shrunk); let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg); @@ -814,7 +824,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) { self.super_operand(operand, location); - let limit = self.tcx.sess.move_size_limit(); + let limit = self.tcx.move_size_limit().0; if limit == 0 { return; } @@ -1071,6 +1081,13 @@ fn create_fn_mono_item<'tcx>( source: Span, ) -> Spanned> { debug!("create_fn_mono_item(instance={})", instance); + + let def_id = instance.def_id(); + if tcx.sess.opts.debugging_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id) + { + monomorphize::util::dump_closure_profile(tcx, instance); + } + respan(source, MonoItem::Fn(instance.polymorphize(tcx))) } @@ -1091,21 +1108,22 @@ fn create_mono_items_for_vtable_methods<'tcx>( assert!(!poly_trait_ref.has_escaping_bound_vars()); // Walk all methods of the trait, including those of its supertraits - let methods = tcx.vtable_methods(poly_trait_ref); - let methods = methods + let entries = tcx.vtable_entries(poly_trait_ref); + let methods = entries .iter() - .cloned() - .filter_map(|method| method) - .map(|(def_id, substs)| { - ty::Instance::resolve_for_vtable( + .filter_map(|entry| match entry { + VtblEntry::MetadataDropInPlace + | VtblEntry::MetadataSize + | VtblEntry::MetadataAlign + | VtblEntry::Vacant => None, + VtblEntry::Method(def_id, substs) => ty::Instance::resolve_for_vtable( tcx, ty::ParamEnv::reveal_all(), - def_id, + *def_id, substs, ) - .unwrap() + .filter(|instance| should_codegen_locally(tcx, instance)), }) - .filter(|&instance| should_codegen_locally(tcx, &instance)) .map(|item| create_fn_mono_item(tcx, item, source)); output.extend(methods); } @@ -1351,7 +1369,7 @@ fn collect_miri<'tcx>( } GlobalAlloc::Memory(alloc) => { trace!("collecting {:?} with {:#?}", alloc_id, alloc); - for &((), inner) in alloc.relocations().values() { + for &inner in alloc.relocations().values() { rustc_data_structures::stack::ensure_sufficient_stack(|| { collect_miri(tcx, inner, output); }); @@ -1384,9 +1402,9 @@ fn collect_const_value<'tcx>( output: &mut Vec>>, ) { match value { - ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), + ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output), ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => { - for &((), id) in alloc.relocations().values() { + for &id in alloc.relocations().values() { collect_miri(tcx, id, output); } } diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs index 9ca4b6687f..57d2723cf9 100644 --- a/compiler/rustc_mir/src/monomorphize/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/mod.rs @@ -7,6 +7,7 @@ use rustc_hir::lang_items::LangItem; pub mod collector; pub mod partitioning; pub mod polymorphize; +pub mod util; fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir/src/monomorphize/util.rs b/compiler/rustc_mir/src/monomorphize/util.rs new file mode 100644 index 0000000000..799b4e18c2 --- /dev/null +++ b/compiler/rustc_mir/src/monomorphize/util.rs @@ -0,0 +1,73 @@ +use rustc_middle::ty::{self, ClosureSizeProfileData, Instance, TyCtxt}; +use std::fs::OpenOptions; +use std::io::prelude::*; + +/// For a given closure, writes out the data for the profiling the impact of RFC 2229 on +/// closure size into a CSV. +/// +/// During the same compile all closures dump the information in the same file +/// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked. +crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) { + let mut file = if let Ok(file) = OpenOptions::new() + .create(true) + .append(true) + .open(&format!("closure_profile_{}.csv", std::process::id())) + { + file + } else { + eprintln!("Cound't open file for writing closure profile"); + return; + }; + + let closure_def_id = closure_instance.def_id(); + let typeck_results = tcx.typeck(closure_def_id.expect_local()); + + if typeck_results.closure_size_eval.contains_key(&closure_def_id) { + let param_env = ty::ParamEnv::reveal_all(); + + let ClosureSizeProfileData { before_feature_tys, after_feature_tys } = + typeck_results.closure_size_eval[&closure_def_id]; + + let before_feature_tys = tcx.subst_and_normalize_erasing_regions( + closure_instance.substs, + param_env, + before_feature_tys, + ); + let after_feature_tys = tcx.subst_and_normalize_erasing_regions( + closure_instance.substs, + param_env, + after_feature_tys, + ); + + let new_size = tcx + .layout_of(param_env.and(after_feature_tys)) + .map(|l| format!("{:?}", l.size.bytes())) + .unwrap_or_else(|e| format!("Failed {:?}", e)); + + let old_size = tcx + .layout_of(param_env.and(before_feature_tys)) + .map(|l| format!("{:?}", l.size.bytes())) + .unwrap_or_else(|e| format!("Failed {:?}", e)); + + let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let closure_span = tcx.hir().span(closure_hir_id); + let src_file = tcx.sess.source_map().span_to_filename(closure_span); + let line_nos = tcx + .sess + .source_map() + .span_to_lines(closure_span) + .map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last())) + .unwrap_or_else(|e| format!("{:?}", e)); + + if let Err(e) = writeln!( + file, + "{}, {}, {}, {:?}", + old_size, + new_size, + src_file.prefer_local(), + line_nos + ) { + eprintln!("Error writting to file {}", e.to_string()) + } + } +} diff --git a/compiler/rustc_mir/src/transform/add_call_guards.rs b/compiler/rustc_mir/src/transform/add_call_guards.rs index 1dddaeb89e..12ee6bb4c6 100644 --- a/compiler/rustc_mir/src/transform/add_call_guards.rs +++ b/compiler/rustc_mir/src/transform/add_call_guards.rs @@ -38,7 +38,9 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards { impl AddCallGuards { pub fn add_call_guards(&self, body: &mut Body<'_>) { - let pred_count: IndexVec<_, _> = body.predecessors().iter().map(|ps| ps.len()).collect(); + let mut pred_count: IndexVec<_, _> = + body.predecessors().iter().map(|ps| ps.len()).collect(); + pred_count[START_BLOCK] += 1; // We need a place to store the new blocks generated let mut new_blocks = Vec::new(); diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index dcbc9c523d..fd72ec4340 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -397,6 +397,9 @@ impl NonConstOp for PanicNonStr { } } +/// Comparing raw pointers for equality. +/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on +/// allocation base addresses that are not known at compile-time. #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { @@ -430,20 +433,22 @@ impl NonConstOp for RawPtrDeref { } } +/// Casting raw pointer or function pointer to an integer. +/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on +/// allocation base addresses that are not known at compile-time. #[derive(Debug)] pub struct RawPtrToIntCast; impl NonConstOp for RawPtrToIntCast { - fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { - Status::Unstable(sym::const_raw_ptr_to_usize_cast) - } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_raw_ptr_to_usize_cast, - span, - &format!("casting pointers to integers in {}s is unstable", ccx.const_kind(),), - ) + let mut err = ccx + .tcx + .sess + .struct_span_err(span, "pointers cannot be cast to integers during const eval."); + err.note("at compile-time, pointers do not have an integer value"); + err.note( + "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior", + ); + err } } diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 4fbd27c89d..cfc538ef50 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -822,12 +822,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { let obligation = Obligation::new( ObligationCause::dummy(), param_env, - Binder::bind( - TraitPredicate { - trait_ref: TraitRef::from_method(tcx, trait_id, substs), - }, - tcx, - ), + Binder::dummy(TraitPredicate { trait_ref }), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { @@ -891,8 +886,37 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { } if !tcx.is_const_fn_raw(callee) { - self.check_op(ops::FnCallNonConst); - return; + let mut permitted = false; + + let callee_trait = tcx.trait_of_item(callee); + if let Some(trait_id) = callee_trait { + if tcx.has_attr(caller, sym::default_method_body_is_const) { + // permit call to non-const fn when caller has default_method_body_is_const.. + if tcx.trait_of_item(caller) == callee_trait { + // ..and caller and callee are in the same trait. + permitted = true; + } + } + if !permitted { + // if trait's impls are all const, permit the call. + let mut const_impls = true; + tcx.for_each_relevant_impl(trait_id, substs.type_at(0), |imp| { + if const_impls { + if let hir::Constness::NotConst = tcx.impl_constness(imp) { + const_impls = false; + } + } + }); + if const_impls { + permitted = true; + } + } + } + + if !permitted { + self.check_op(ops::FnCallNonConst); + return; + } } // If the `const fn` we are trying to call is not const-stable, ensure that we have diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs index 103ddda1a1..1ff9bd1572 100644 --- a/compiler/rustc_mir/src/transform/check_unsafety.rs +++ b/compiler/rustc_mir/src/transform/check_unsafety.rs @@ -7,7 +7,6 @@ use rustc_hir::intravisit; use rustc_hir::Node; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; @@ -18,7 +17,6 @@ use std::ops::Bound; pub struct UnsafetyChecker<'a, 'tcx> { body: &'a Body<'tcx>, body_did: LocalDefId, - const_context: bool, violations: Vec, source_info: SourceInfo, tcx: TyCtxt<'tcx>, @@ -30,7 +28,6 @@ pub struct UnsafetyChecker<'a, 'tcx> { impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { fn new( - const_context: bool, body: &'a Body<'tcx>, body_did: LocalDefId, tcx: TyCtxt<'tcx>, @@ -39,7 +36,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { Self { body, body_did, - const_context, violations: vec![], source_info: SourceInfo::outermost(body.span), tcx, @@ -136,25 +132,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.register_violations(&violations, &unsafe_blocks); } }, - // casting pointers to ints is unsafe in const fn because the const evaluator cannot - // possibly know what the result of various operations like `address / 2` would be - // pointers during const evaluation have no integral address, only an abstract one - Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) - if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast => - { - let operand_ty = operand.ty(self.body, self.tcx); - let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); - let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); - match (cast_in, cast_out) { - (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => { - self.require_unsafe( - UnsafetyViolationKind::General, - UnsafetyViolationDetails::CastOfPointerToInt, - ); - } - _ => {} - } - } _ => {} } self.super_rvalue(rvalue, location); @@ -469,13 +446,7 @@ fn unsafety_check_result<'tcx>( let param_env = tcx.param_env(def.did); - let id = tcx.hir().local_def_id_to_hir_id(def.did); - let const_context = match tcx.hir().body_owner_kind(id) { - hir::BodyOwnerKind::Closure => false, - hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()), - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true, - }; - let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env); + let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env); checker.visit_body(&body); check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks); diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 681d63c6fc..e02e41d620 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -31,9 +31,8 @@ use rustc_trait_selection::traits; use crate::const_eval::ConstEvalErr; use crate::interpret::{ self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy, - Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, - Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup, - StackPopUnwind, + Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy, + Operand as InterpOperand, PlaceTy, Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind, }; use crate::transform::MirPass; @@ -157,7 +156,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { struct ConstPropMachine<'mir, 'tcx> { /// The virtual call stack. - stack: Vec>, + stack: Vec>, /// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end. written_only_inside_own_block_locals: FxHashSet, /// Locals that need to be cleared after every block terminates. @@ -181,6 +180,7 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> { impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> { compile_time_machine!(<'mir, 'tcx>); + const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`) type MemoryKind = !; @@ -222,10 +222,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> bug!("panics terminators are not evaluated in ConstProp") } - fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { - throw_unsup!(ReadPointerAsBytes) - } - fn binary_ptr_op( _ecx: &InterpCx<'mir, 'tcx, Self>, _bin_op: BinOp, @@ -393,7 +389,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { .filter(|ret_layout| { !ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) }) - .map(|ret_layout| ecx.allocate(ret_layout, MemoryKind::Stack).into()); + .map(|ret_layout| { + ecx.allocate(ret_layout, MemoryKind::Stack) + .expect("couldn't perform small allocation") + .into() + }); ecx.push_stack_frame( Instance::new(def_id, substs), @@ -528,14 +528,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_info: SourceInfo, message: &'static str, panic: AssertKind, - ) -> Option<()> { - let 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() - }); - None + ) { + 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() + }); + } } fn check_unary_op( @@ -557,7 +557,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_info, "this arithmetic operation will overflow", AssertKind::OverflowNeg(val.to_const_int()), - )?; + ); + return None; } Some(()) @@ -581,8 +582,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let left_size = self.ecx.layout_of(left_ty).ok()?.size; let right_size = r.layout.size; let r_bits = r.to_scalar().ok(); - // This is basically `force_bits`. - let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok()); + let r_bits = r_bits.and_then(|r| r.to_bits(right_size).ok()); if r_bits.map_or(false, |b| b >= left_size.bits() as u128) { debug!("check_binary_op: reporting assert for {:?}", source_info); self.report_assert_as_lint( @@ -602,7 +602,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { }, r.to_const_int(), ), - )?; + ); + return None; } } @@ -617,7 +618,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_info, "this arithmetic operation will overflow", AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()), - )?; + ); + return None; } } Some(()) @@ -751,8 +753,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } }; - let arg_value = - this.ecx.force_bits(const_arg.to_scalar()?, const_arg.layout.size)?; + let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?; let dest = this.ecx.eval_place(place)?; match op { @@ -868,7 +869,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let alloc = this .ecx .intern_with_temp_alloc(value.layout, |ecx, dest| { - ecx.write_immediate_to_mplace(*imm, dest) + ecx.write_immediate(*imm, dest) }) .unwrap(); Ok(Some(alloc)) @@ -920,12 +921,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { match **op { interpret::Operand::Immediate(Immediate::Scalar(ScalarMaybeUninit::Scalar(s))) => { - s.is_bits() + s.try_to_int().is_ok() } interpret::Operand::Immediate(Immediate::ScalarPair( ScalarMaybeUninit::Scalar(l), ScalarMaybeUninit::Scalar(r), - )) => l.is_bits() && r.is_bits(), + )) => l.try_to_int().is_ok() && r.try_to_int().is_ok(), _ => false, } } @@ -1202,12 +1203,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { let mut eval_to_int = |op| { // This can be `None` if the lhs wasn't const propagated and we just // triggered the assert on the value of the rhs. - match self.eval_operand(op, source_info) { - Some(op) => DbgVal::Val( - self.ecx.read_immediate(&op).unwrap().to_const_int(), - ), - None => DbgVal::Underscore, - } + self.eval_operand(op, source_info).map_or(DbgVal::Underscore, |op| { + DbgVal::Val(self.ecx.read_immediate(&op).unwrap().to_const_int()) + }) }; let msg = match msg { AssertKind::DivisionByZero(op) => { diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs index f62171b3c5..08cc87ccc3 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir/src/transform/coverage/spans.rs @@ -184,11 +184,8 @@ impl CoverageSpan { self.current_macro_or_none .borrow_mut() .get_or_insert_with(|| { - if let ExpnKind::Macro { - kind: MacroKind::Bang, - name: current_macro, - proc_macro: _, - } = self.expn_span.ctxt().outer_expn_data().kind + if let ExpnKind::Macro(MacroKind::Bang, current_macro) = + self.expn_span.ctxt().outer_expn_data().kind { return Some(current_macro); } diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir/src/transform/coverage/tests.rs index b04c2d542d..e5b3059a59 100644 --- a/compiler/rustc_mir/src/transform/coverage/tests.rs +++ b/compiler/rustc_mir/src/transform/coverage/tests.rs @@ -22,7 +22,7 @@ //! are unrelated to the `TyCtxt` global. Without initializing the `Span` session globals, some //! basic, coverage-specific features would be impossible to test, but thankfully initializing these //! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument -//! to: `rustc_span::with_default_session_globals(|| { test_here(); })`. +//! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`. use super::counters; use super::debug; @@ -677,7 +677,7 @@ fn synthesize_body_span_from_terminators(mir_body: &Body<'_>) -> Span { #[test] fn test_make_bcb_counters() { - rustc_span::with_default_session_globals(|| { + rustc_span::create_default_session_globals_then(|| { let mir_body = goto_switchint(); let body_span = synthesize_body_span_from_terminators(&mir_body); let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index f1c95a84ad..7d765cec57 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -284,7 +284,7 @@ impl Inliner<'tcx> { &self, callsite: &CallSite<'tcx>, callee_attrs: &CodegenFnAttrs, - ) -> Result<(), &'satic str> { + ) -> Result<(), &'static str> { if let InlineAttr::Never = callee_attrs.inline { return Err("never inline hint"); } @@ -836,10 +836,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { fn visit_span(&mut self, span: &mut Span) { let mut expn_data = - ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None); + ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None, None); expn_data.def_site = self.body_span; // Make sure that all spans track the fact that they were inlined. - *span = self.callsite_span.fresh_expansion(expn_data); + *span = + self.callsite_span.fresh_expansion(expn_data, self.tcx.create_stable_hashing_context()); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir/src/transform/inline/cycle.rs index 295f3ec70d..c9eafafff5 100644 --- a/compiler/rustc_mir/src/transform/inline/cycle.rs +++ b/compiler/rustc_mir/src/transform/inline/cycle.rs @@ -5,6 +5,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir::TerminatorKind; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt}; +use rustc_session::Limit; // FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking // this query riddiculously often. @@ -30,7 +31,7 @@ crate fn mir_callgraph_reachable( ); #[instrument( level = "debug", - skip(tcx, param_env, target, stack, seen, recursion_limiter, caller) + skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit) )] fn process( tcx: TyCtxt<'tcx>, @@ -40,6 +41,7 @@ crate fn mir_callgraph_reachable( stack: &mut Vec>, seen: &mut FxHashSet>, recursion_limiter: &mut FxHashMap, + recursion_limit: Limit, ) -> bool { trace!(%caller); for &(callee, substs) in tcx.mir_inliner_callees(caller.def) { @@ -96,11 +98,20 @@ crate fn mir_callgraph_reachable( if seen.insert(callee) { let recursion = recursion_limiter.entry(callee.def_id()).or_default(); trace!(?callee, recursion = *recursion); - if tcx.sess.recursion_limit().value_within_limit(*recursion) { + if recursion_limit.value_within_limit(*recursion) { *recursion += 1; stack.push(callee); let found_recursion = ensure_sufficient_stack(|| { - process(tcx, param_env, callee, target, stack, seen, recursion_limiter) + process( + tcx, + param_env, + callee, + target, + stack, + seen, + recursion_limiter, + recursion_limit, + ) }); if found_recursion { return true; @@ -122,6 +133,7 @@ crate fn mir_callgraph_reachable( &mut Vec::new(), &mut FxHashSet::default(), &mut FxHashMap::default(), + tcx.recursion_limit(), ) } diff --git a/compiler/rustc_mir/src/transform/lower_slice_len.rs b/compiler/rustc_mir/src/transform/lower_slice_len.rs new file mode 100644 index 0000000000..c3eb2d9f92 --- /dev/null +++ b/compiler/rustc_mir/src/transform/lower_slice_len.rs @@ -0,0 +1,100 @@ +//! This pass lowers calls to core::slice::len to just Len op. +//! It should run before inlining! + +use crate::transform::MirPass; +use rustc_hir::def_id::DefId; +use rustc_index::vec::IndexVec; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, TyCtxt}; + +pub struct LowerSliceLenCalls; + +impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + lower_slice_len_calls(tcx, body) + } +} + +pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let language_items = tcx.lang_items(); + let slice_len_fn_item_def_id = if let Some(slice_len_fn_item) = language_items.slice_len_fn() { + slice_len_fn_item + } else { + // there is no language item to compare to :) + return; + }; + + let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + + for block in basic_blocks { + // lower `<[_]>::len` calls + lower_slice_len_call(tcx, block, &*local_decls, slice_len_fn_item_def_id); + } +} + +struct SliceLenPatchInformation<'tcx> { + add_statement: Statement<'tcx>, + new_terminator_kind: TerminatorKind<'tcx>, +} + +fn lower_slice_len_call<'tcx>( + tcx: TyCtxt<'tcx>, + block: &mut BasicBlockData<'tcx>, + local_decls: &IndexVec>, + slice_len_fn_item_def_id: DefId, +) { + let mut patch_found: Option> = None; + + let terminator = block.terminator(); + match &terminator.kind { + TerminatorKind::Call { + func, + args, + destination: Some((dest, bb)), + cleanup: None, + from_hir_call: true, + .. + } => { + // some heuristics for fast rejection + if args.len() != 1 { + return; + } + let arg = match args[0].place() { + Some(arg) => arg, + None => return, + }; + let func_ty = func.ty(local_decls, tcx); + match func_ty.kind() { + ty::FnDef(fn_def_id, _) if fn_def_id == &slice_len_fn_item_def_id => { + // perform modifications + // from something like `_5 = core::slice::::len(move _6) -> bb1` + // into `_5 = Len(*_6) + // goto bb1 + + // make new RValue for Len + let deref_arg = tcx.mk_place_deref(arg); + let r_value = Rvalue::Len(deref_arg); + let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value))); + let add_statement = Statement { + kind: len_statement_kind, + source_info: terminator.source_info.clone(), + }; + + // modify terminator into simple Goto + let new_terminator_kind = TerminatorKind::Goto { target: bb.clone() }; + + let patch = SliceLenPatchInformation { add_statement, new_terminator_kind }; + + patch_found = Some(patch); + } + _ => {} + } + } + _ => {} + } + + if let Some(SliceLenPatchInformation { add_statement, new_terminator_kind }) = patch_found { + block.statements.push(add_statement); + block.terminator_mut().kind = new_terminator_kind; + } +} diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 2201223e13..5c201594dd 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -36,6 +36,7 @@ pub mod generator; pub mod inline; pub mod instcombine; pub mod lower_intrinsics; +pub mod lower_slice_len; pub mod match_branches; pub mod multiple_return_terminators; pub mod no_landing_pads; @@ -479,6 +480,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // to them. We run some optimizations before that, because they may be harder to do on the state // machine than on MIR with async primitives. let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[ + &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first &unreachable_prop::UnreachablePropagation, &uninhabited_enum_branching::UninhabitedEnumBranching, &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"), diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs index 9f473f3bae..1ddf7c9cd0 100644 --- a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs +++ b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs @@ -46,7 +46,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { .expect("if we have an evaluated constant we must know the layout"); int.assert_bits(layout.size) } - Scalar::Ptr(_) => continue, + Scalar::Ptr(..) => continue, }; const FALSE: u128 = 0; @@ -211,7 +211,7 @@ fn find_branch_value_info<'tcx>( return None; }; let branch_value_scalar = branch_value.literal.try_to_scalar()?; - Some((branch_value_scalar, branch_value_ty, *to_switch_on)) + Some((branch_value_scalar.into(), branch_value_ty, *to_switch_on)) } _ => None, } diff --git a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs index 465832c89f..5c6c158d46 100644 --- a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs @@ -24,6 +24,7 @@ fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option { /// discriminant is read from. Otherwise, returns None. fn get_switched_on_type<'tcx>( block_data: &BasicBlockData<'tcx>, + tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ) -> Option> { let terminator = block_data.terminator(); @@ -36,12 +37,9 @@ fn get_switched_on_type<'tcx>( if let Some(StatementKind::Assign(box (l, Rvalue::Discriminant(place)))) = stmt_before_term { if l.as_local() == Some(local) { - if let Some(r_local) = place.as_local() { - let ty = body.local_decls[r_local].ty; - - if ty.is_enum() { - return Some(ty); - } + let ty = place.ty(body, tcx).ty; + if ty.is_enum() { + return Some(ty); } } } @@ -86,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { trace!("processing block {:?}", bb); let discriminant_ty = - if let Some(ty) = get_switched_on_type(&body.basic_blocks()[bb], body) { + if let Some(ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) { ty } else { continue; diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index c4e1e184ac..d0b1bc47ea 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -1,6 +1,6 @@ use std::collections::BTreeSet; +use std::fmt::Display; use std::fmt::Write as _; -use std::fmt::{Debug, Display}; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; use rustc_middle::mir::interpret::{ - read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, + read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, Provenance, }; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -99,7 +99,10 @@ pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> }); filters.split('|').any(|or_filter| { or_filter.split('&').all(|and_filter| { - and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter) + let and_filter_trimmed = and_filter.trim(); + and_filter_trimmed == "all" + || pass_name.contains(and_filter_trimmed) + || node_path.contains(and_filter_trimmed) }) }) } @@ -423,14 +426,14 @@ impl ExtraComments<'tcx> { } } -fn use_verbose(ty: &&TyS<'tcx>) -> bool { +fn use_verbose(ty: &&TyS<'tcx>, fn_def: bool) -> bool { match ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false, // Unit type ty::Tuple(g_args) if g_args.is_empty() => false, - ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty())), - ty::Array(ty, _) => use_verbose(ty), - ty::FnDef(..) => false, + ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty(), fn_def)), + ty::Array(ty, _) => use_verbose(ty, fn_def), + ty::FnDef(..) => fn_def, _ => true, } } @@ -439,28 +442,20 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); let Constant { span, user_ty, literal } = constant; - match literal.ty().kind() { - ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char => {} - // Unit type - ty::Tuple(tys) if tys.is_empty() => {} - _ => { - self.push("mir::Constant"); - self.push(&format!( - "+ span: {}", - self.tcx.sess.source_map().span_to_embeddable_string(*span) - )); - if let Some(user_ty) = user_ty { - self.push(&format!("+ user_ty: {:?}", user_ty)); - } - match literal { - ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)), - ConstantKind::Val(val, ty) => { - // To keep the diffs small, we render this almost like we render ty::Const - self.push(&format!( - "+ literal: Const {{ ty: {}, val: Value({:?}) }}", - ty, val - )) - } + if use_verbose(&literal.ty(), true) { + self.push("mir::Constant"); + self.push(&format!( + "+ span: {}", + self.tcx.sess.source_map().span_to_embeddable_string(*span) + )); + if let Some(user_ty) = user_ty { + self.push(&format!("+ user_ty: {:?}", user_ty)); + } + match literal { + ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)), + ConstantKind::Val(val, ty) => { + // To keep the diffs small, we render this almost like we render ty::Const + self.push(&format!("+ literal: Const {{ ty: {}, val: Value({:?}) }}", ty, val)) } } } @@ -469,7 +464,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) { self.super_const(constant); let ty::Const { ty, val, .. } = constant; - if use_verbose(ty) { + if use_verbose(ty, false) { self.push("ty::Const"); self.push(&format!("+ ty: {:?}", ty)); let val = match val { @@ -670,12 +665,12 @@ pub fn write_allocations<'tcx>( w: &mut dyn Write, ) -> io::Result<()> { fn alloc_ids_from_alloc(alloc: &Allocation) -> impl DoubleEndedIterator + '_ { - alloc.relocations().values().map(|(_, id)| *id) + alloc.relocations().values().map(|id| *id) } fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator + '_ { match val { - ConstValue::Scalar(interpret::Scalar::Ptr(ptr)) => { - Either::Left(Either::Left(std::iter::once(ptr.alloc_id))) + ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _size)) => { + Either::Left(Either::Left(std::iter::once(ptr.provenance))) } ConstValue::Scalar(interpret::Scalar::Int { .. }) => { Either::Left(Either::Right(std::iter::empty())) @@ -760,7 +755,7 @@ pub fn write_allocations<'tcx>( /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control /// characters or characters whose value is larger than 127) with a `.` /// This also prints relocations adequately. -pub fn display_allocation( +pub fn display_allocation( tcx: TyCtxt<'tcx>, alloc: &'a Allocation, ) -> RenderAllocation<'a, 'tcx, Tag, Extra> { @@ -773,7 +768,7 @@ pub struct RenderAllocation<'a, 'tcx, Tag, Extra> { alloc: &'a Allocation, } -impl std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> { +impl std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> { fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let RenderAllocation { tcx, alloc } = *self; write!(w, "size: {}, align: {})", alloc.size().bytes(), alloc.align.bytes())?; @@ -816,7 +811,7 @@ fn write_allocation_newline( /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there /// is only one line). Note that your prefix should contain a trailing space as the lines are /// printed directly after it. -fn write_allocation_bytes( +fn write_allocation_bytes( tcx: TyCtxt<'tcx>, alloc: &Allocation, w: &mut dyn std::fmt::Write, @@ -824,7 +819,7 @@ fn write_allocation_bytes( ) -> std::fmt::Result { let num_lines = alloc.size().bytes_usize().saturating_sub(BYTES_PER_LINE); // Number of chars needed to represent all line numbers. - let pos_width = format!("{:x}", alloc.size().bytes()).len(); + let pos_width = hex_number_length(alloc.size().bytes()); if num_lines > 0 { write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?; @@ -852,7 +847,7 @@ fn write_allocation_bytes( if i != line_start { write!(w, " ")?; } - if let Some(&(tag, target_id)) = alloc.relocations().get(&i) { + if let Some(&tag) = alloc.relocations().get(&i) { // Memory with a relocation must be defined let j = i.bytes_usize(); let offset = alloc @@ -860,7 +855,7 @@ fn write_allocation_bytes( let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap(); let offset = Size::from_bytes(offset); let relocation_width = |bytes| bytes * 3; - let ptr = Pointer::new_with_tag(target_id, offset, tag); + let ptr = Pointer::new(tag, offset); let mut target = format!("{:?}", ptr); if target.len() > relocation_width(ptr_size.bytes_usize() - 1) { // This is too long, try to save some space. @@ -1023,3 +1018,23 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option) -> Vec { tcx.mir_keys(()).iter().map(|def_id| def_id.to_def_id()).collect() } } + +/// Calc converted u64 decimal into hex and return it's length in chars +/// +/// ```ignore (cannot-test-private-function) +/// assert_eq!(1, hex_number_length(0)); +/// assert_eq!(1, hex_number_length(1)); +/// assert_eq!(2, hex_number_length(16)); +/// ``` +fn hex_number_length(x: u64) -> usize { + if x == 0 { + return 1; + } + let mut length = 0; + let mut x_left = x; + while x_left > 0 { + x_left /= 16; + length += 1; + } + length +} diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 8426b24270..df71379c1d 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -74,8 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // First we build all the statements in the block. let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; - let outer_push_unsafe_count = this.push_unsafe_count; - let outer_unpushed_unsafe = this.unpushed_unsafe; + let outer_in_scope_unsafe = this.in_scope_unsafe; this.update_source_scope_for_safety_mode(span, safety_mode); let source_info = this.source_info(span); @@ -206,8 +205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } // Restore the original source scope. this.source_scope = outer_source_scope; - this.push_unsafe_count = outer_push_unsafe_count; - this.unpushed_unsafe = outer_unpushed_unsafe; + this.in_scope_unsafe = outer_in_scope_unsafe; block.unit() } @@ -216,9 +214,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!("update_source_scope_for({:?}, {:?})", span, safety_mode); let new_unsafety = match safety_mode { BlockSafety::Safe => None, + BlockSafety::BuiltinUnsafe => Some(Safety::BuiltinUnsafe), BlockSafety::ExplicitUnsafe(hir_id) => { - assert_eq!(self.push_unsafe_count, 0); - match self.unpushed_unsafe { + match self.in_scope_unsafe { Safety::Safe => {} // no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585) Safety::FnUnsafe @@ -226,20 +224,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { != Level::Allow => {} _ => return, } - self.unpushed_unsafe = Safety::ExplicitUnsafe(hir_id); + self.in_scope_unsafe = Safety::ExplicitUnsafe(hir_id); Some(Safety::ExplicitUnsafe(hir_id)) } - BlockSafety::PushUnsafe => { - self.push_unsafe_count += 1; - Some(Safety::BuiltinUnsafe) - } - BlockSafety::PopUnsafe => { - self.push_unsafe_count = self - .push_unsafe_count - .checked_sub(1) - .unwrap_or_else(|| span_bug!(span, "unsafe count underflow")); - if self.push_unsafe_count == 0 { Some(self.unpushed_unsafe) } else { None } - } }; if let Some(unsafety) = new_unsafety { 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 5511cd4c73..bedb8b1c58 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -217,6 +217,10 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( ty::ClosureKind::FnOnce => {} } + // We won't be building MIR if the closure wasn't local + let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + let closure_span = tcx.hir().span(closure_hir_id); + let (capture_index, capture) = if let Some(capture_details) = find_capture_matching_projections( typeck_results, @@ -226,7 +230,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( ) { capture_details } else { - if !tcx.features().capture_disjoint_fields { + if !enable_precise_capture(tcx, closure_span) { bug!( "No associated capture found for {:?}[{:#?}] even though \ capture_disjoint_fields isn't enabled", @@ -242,8 +246,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( return Err(from_builder); }; - let closure_ty = typeck_results - .node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local())); + let closure_ty = typeck_results.node_type(closure_hir_id); let substs = match closure_ty.kind() { ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), @@ -780,3 +783,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } } + +/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if +/// user is using Rust Edition 2021 or higher. +fn enable_precise_capture(tcx: TyCtxt<'_>, closure_span: Span) -> bool { + tcx.features().capture_disjoint_fields || closure_span.rust_2021() +} diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index f2b00f0f6e..d7b3a85c15 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -264,7 +264,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, address_of); block.unit() } - ExprKind::Adt { adt_def, variant_index, substs, user_ty, ref fields, ref base } => { + ExprKind::Adt(box Adt { + adt_def, + variant_index, + substs, + user_ty, + ref fields, + ref base, + }) => { // See the notes for `ExprKind::Array` in `as_rvalue` and for // `ExprKind::Borrow` above. let is_union = adt_def.is_union(); diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs index 539de80cab..7c1a592f55 100644 --- a/compiler/rustc_mir_build/src/build/expr/mod.rs +++ b/compiler/rustc_mir_build/src/build/expr/mod.rs @@ -65,6 +65,6 @@ mod as_operand; pub mod as_place; mod as_rvalue; mod as_temp; -mod category; +pub mod category; mod into; mod stmt; diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 10d6521e7d..60cfd73b19 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -367,12 +367,8 @@ struct Builder<'a, 'tcx> { /// `{ STMTS; EXPR1 } + EXPR2`. block_context: BlockContext, - /// The current unsafe block in scope, even if it is hidden by - /// a `PushUnsafeBlock`. - unpushed_unsafe: Safety, - - /// The number of `push_unsafe_block` levels in scope. - push_unsafe_count: usize, + /// The current unsafe block in scope + in_scope_unsafe: Safety, /// The vector of all scopes that we have created thus far; /// we track this for debuginfo later. @@ -877,8 +873,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_scopes: IndexVec::new(), source_scope: OUTERMOST_SOURCE_SCOPE, guard_context: vec![], - push_unsafe_count: 0, - unpushed_unsafe: safety, + in_scope_unsafe: safety, local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1), canonical_user_type_annotations: IndexVec::new(), upvar_mutbls: vec![], @@ -1136,3 +1131,5 @@ mod expr; mod matches; mod misc; mod scope; + +pub(crate) use expr::category::Category as ExprCategory; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 2d52577829..82e19c0552 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,9 +1,11 @@ +use crate::build::ExprCategory; use crate::thir::visit::{self, Visitor}; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; use rustc_span::def_id::{DefId, LocalDefId}; @@ -25,15 +27,14 @@ struct UnsafetyVisitor<'a, 'tcx> { /// The `#[target_feature]` attributes of the body. Used for checking /// calls to functions with `#[target_feature]` (RFC 2396). body_target_features: &'tcx Vec, - is_const: bool, + in_possible_lhs_union_assign: bool, + in_union_destructure: bool, + param_env: ParamEnv<'tcx>, + inside_adt: bool, } impl<'tcx> UnsafetyVisitor<'_, 'tcx> { - fn in_safety_context( - &mut self, - safety_context: SafetyContext, - f: impl FnOnce(&mut Self) -> R, - ) { + fn in_safety_context(&mut self, safety_context: SafetyContext, f: impl FnOnce(&mut Self)) { if let ( SafetyContext::UnsafeBlock { span: enclosing_span, .. }, SafetyContext::UnsafeBlock { span: block_span, hir_id, .. }, @@ -63,7 +64,6 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { ); } self.safety_context = prev_context; - return; } } @@ -71,6 +71,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { let (description, note) = kind.description_and_note(); let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed(); match self.safety_context { + SafetyContext::BuiltinUnsafeBlock => {} SafetyContext::UnsafeBlock { ref mut used, .. } => { if !self.body_unsafety.is_unsafe() || !unsafe_op_in_unsafe_fn_allowed { // Mark this block as useful @@ -136,30 +137,207 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { } } +// Searches for accesses to layout constrained fields. +struct LayoutConstrainedPlaceVisitor<'a, 'tcx> { + found: bool, + thir: &'a Thir<'tcx>, + tcx: TyCtxt<'tcx>, +} + +impl<'a, 'tcx> LayoutConstrainedPlaceVisitor<'a, 'tcx> { + fn new(thir: &'a Thir<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + Self { found: false, thir, tcx } + } +} + +impl<'a, 'tcx> Visitor<'a, 'tcx> for LayoutConstrainedPlaceVisitor<'a, 'tcx> { + fn thir(&self) -> &'a Thir<'tcx> { + self.thir + } + + fn visit_expr(&mut self, expr: &Expr<'tcx>) { + match expr.kind { + ExprKind::Field { lhs, .. } => { + if let ty::Adt(adt_def, _) = self.thir[lhs].ty.kind() { + if (Bound::Unbounded, Bound::Unbounded) + != self.tcx.layout_scalar_valid_range(adt_def.did) + { + self.found = true; + } + } + visit::walk_expr(self, expr); + } + + // Keep walking through the expression as long as we stay in the same + // place, i.e. the expression is a place expression and not a dereference + // (since dereferencing something leads us to a different place). + ExprKind::Deref { .. } => {} + ref kind if ExprCategory::of(kind).map_or(true, |cat| cat == ExprCategory::Place) => { + visit::walk_expr(self, expr); + } + + _ => {} + } + } +} + impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { fn thir(&self) -> &'a Thir<'tcx> { &self.thir } fn visit_block(&mut self, block: &Block) { - if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode { - self.in_safety_context( - SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false }, - |this| visit::walk_block(this, block), - ); - } else { - visit::walk_block(self, block); + match block.safety_mode { + // compiler-generated unsafe code should not count towards the usefulness of + // an outer unsafe block + BlockSafety::BuiltinUnsafe => { + self.in_safety_context(SafetyContext::BuiltinUnsafeBlock, |this| { + visit::walk_block(this, block) + }); + } + BlockSafety::ExplicitUnsafe(hir_id) => { + self.in_safety_context( + SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false }, + |this| visit::walk_block(this, block), + ); + } + BlockSafety::Safe => { + visit::walk_block(self, block); + } + } + } + + fn visit_pat(&mut self, pat: &Pat<'tcx>) { + if self.in_union_destructure { + match *pat.kind { + // binding to a variable allows getting stuff out of variable + PatKind::Binding { .. } + // match is conditional on having this value + | PatKind::Constant { .. } + | PatKind::Variant { .. } + | PatKind::Leaf { .. } + | PatKind::Deref { .. } + | PatKind::Range { .. } + | PatKind::Slice { .. } + | PatKind::Array { .. } => { + self.requires_unsafe(pat.span, AccessToUnionField); + return; // we can return here since this already requires unsafe + } + // wildcard doesn't take anything + PatKind::Wild | + // these just wrap other patterns + PatKind::Or { .. } | + PatKind::AscribeUserType { .. } => {} + } + }; + + match &*pat.kind { + PatKind::Leaf { .. } => { + if let ty::Adt(adt_def, ..) = pat.ty.kind() { + if adt_def.is_union() { + let old_in_union_destructure = + std::mem::replace(&mut self.in_union_destructure, true); + visit::walk_pat(self, pat); + self.in_union_destructure = old_in_union_destructure; + } else if (Bound::Unbounded, Bound::Unbounded) + != self.tcx.layout_scalar_valid_range(adt_def.did) + { + let old_inside_adt = std::mem::replace(&mut self.inside_adt, true); + visit::walk_pat(self, pat); + self.inside_adt = old_inside_adt; + } else { + visit::walk_pat(self, pat); + } + } else { + visit::walk_pat(self, pat); + } + } + PatKind::Binding { mode: BindingMode::ByRef(borrow_kind), ty, .. } => { + if self.inside_adt { + if let ty::Ref(_, ty, _) = ty.kind() { + match borrow_kind { + BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { + if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) { + self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); + } + } + BorrowKind::Mut { .. } => { + self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField); + } + } + } else { + span_bug!( + pat.span, + "BindingMode::ByRef in pattern, but found non-reference type {}", + ty + ); + } + } + visit::walk_pat(self, pat); + } + PatKind::Deref { .. } => { + let old_inside_adt = std::mem::replace(&mut self.inside_adt, false); + visit::walk_pat(self, pat); + self.inside_adt = old_inside_adt; + } + _ => { + visit::walk_pat(self, pat); + } } } fn visit_expr(&mut self, expr: &Expr<'tcx>) { + // could we be in a the LHS of an assignment of a union? + match expr.kind { + ExprKind::Field { .. } + | ExprKind::VarRef { .. } + | ExprKind::UpvarRef { .. } + | ExprKind::Scope { .. } + | ExprKind::Cast { .. } => {} + + ExprKind::AddressOf { .. } + | ExprKind::Adt { .. } + | ExprKind::Array { .. } + | ExprKind::Binary { .. } + | ExprKind::Block { .. } + | ExprKind::Borrow { .. } + | ExprKind::Literal { .. } + | ExprKind::ConstBlock { .. } + | ExprKind::Deref { .. } + | ExprKind::Index { .. } + | ExprKind::NeverToAny { .. } + | ExprKind::PlaceTypeAscription { .. } + | ExprKind::ValueTypeAscription { .. } + | ExprKind::Pointer { .. } + | ExprKind::Repeat { .. } + | ExprKind::StaticRef { .. } + | ExprKind::ThreadLocalRef { .. } + | ExprKind::Tuple { .. } + | ExprKind::Unary { .. } + | ExprKind::Call { .. } + | ExprKind::Assign { .. } + | ExprKind::AssignOp { .. } + | ExprKind::Break { .. } + | ExprKind::Closure { .. } + | ExprKind::Continue { .. } + | ExprKind::Return { .. } + | ExprKind::Yield { .. } + | ExprKind::Loop { .. } + | ExprKind::Match { .. } + | ExprKind::Box { .. } + | ExprKind::If { .. } + | ExprKind::InlineAsm { .. } + | ExprKind::LlvmInlineAsm { .. } + | ExprKind::LogicalOp { .. } + | ExprKind::Use { .. } => self.in_possible_lhs_union_assign = false, + }; match expr.kind { ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => { let prev_id = self.hir_context; self.hir_context = hir_id; self.visit_expr(&self.thir[value]); self.hir_context = prev_id; - return; + return; // don't visit the whole expression } ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => { if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { @@ -195,27 +373,17 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => { self.requires_unsafe(expr.span, UseOfInlineAssembly); } - ExprKind::Adt { + ExprKind::Adt(box Adt { adt_def, variant_index: _, substs: _, user_ty: _, fields: _, base: _, - } => match self.tcx.layout_scalar_valid_range(adt_def.did) { + }) => match self.tcx.layout_scalar_valid_range(adt_def.did) { (Bound::Unbounded, Bound::Unbounded) => {} _ => self.requires_unsafe(expr.span, InitializingTypeWith), }, - ExprKind::Cast { source } => { - let source = &self.thir[source]; - if self.tcx.features().const_raw_ptr_to_usize_cast - && self.is_const - && (source.ty.is_unsafe_ptr() || source.ty.is_fn_ptr()) - && expr.ty.is_integral() - { - self.requires_unsafe(expr.span, CastOfPointerToInt); - } - } ExprKind::Closure { closure_id, substs: _, @@ -240,9 +408,60 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { // Unsafe blocks can be used in closures, make sure to take it into account self.safety_context = closure_visitor.safety_context; } + ExprKind::Field { lhs, .. } => { + // assigning to union field is okay for AccessToUnionField + if let ty::Adt(adt_def, _) = &self.thir[lhs].ty.kind() { + if adt_def.is_union() { + if self.in_possible_lhs_union_assign { + // FIXME: trigger AssignToDroppingUnionField unsafety if needed + } else { + self.requires_unsafe(expr.span, AccessToUnionField); + } + } + } + } + ExprKind::Assign { lhs, rhs } | ExprKind::AssignOp { lhs, rhs, .. } => { + // First, check whether we are mutating a layout constrained field + let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx); + visit::walk_expr(&mut visitor, &self.thir[lhs]); + if visitor.found { + self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField); + } + + // Second, check for accesses to union fields + // don't have any special handling for AssignOp since it causes a read *and* write to lhs + if matches!(expr.kind, ExprKind::Assign { .. }) { + // assigning to a union is safe, check here so it doesn't get treated as a read later + self.in_possible_lhs_union_assign = true; + visit::walk_expr(self, &self.thir()[lhs]); + self.in_possible_lhs_union_assign = false; + visit::walk_expr(self, &self.thir()[rhs]); + return; // we have already visited everything by now + } + } + ExprKind::Borrow { borrow_kind, arg } => 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) + { + let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx); + visit::walk_expr(&mut visitor, expr); + if visitor.found { + self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField); + } + } + } + BorrowKind::Mut { .. } => { + let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx); + visit::walk_expr(&mut visitor, expr); + if visitor.found { + self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField); + } + } + }, _ => {} } - visit::walk_expr(self, expr); } } @@ -250,6 +469,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { #[derive(Clone, Copy)] enum SafetyContext { Safe, + BuiltinUnsafeBlock, UnsafeFn, UnsafeBlock { span: Span, hir_id: hir::HirId, used: bool }, } @@ -283,13 +503,11 @@ enum UnsafeOpKind { CallToUnsafeFunction, UseOfInlineAssembly, InitializingTypeWith, - CastOfPointerToInt, UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, #[allow(dead_code)] // FIXME AssignToDroppingUnionField, - #[allow(dead_code)] // FIXME AccessToUnionField, #[allow(dead_code)] // FIXME MutationOfLayoutConstrainedField, @@ -317,9 +535,6 @@ impl UnsafeOpKind { "initializing a layout restricted type's field with a value outside the valid \ range is undefined behavior", ), - CastOfPointerToInt => { - ("cast of pointer to int", "casting pointers to integers in constants") - } UseOfMutableStatic => ( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing violations or data \ @@ -368,10 +583,15 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam false, - hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()), - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true, - }; let mut visitor = UnsafetyVisitor { tcx, thir, @@ -404,7 +619,10 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam( } (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { let id = tcx.allocate_bytes(data); - ConstValue::Scalar(Scalar::Ptr(id.into())) + ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx)) } (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1))) @@ -46,9 +46,7 @@ crate fn lit_to_const<'tcx>( (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })? } - (ast::LitKind::Float(n, _), ty::Float(fty)) => { - parse_float(*n, *fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? - } + (ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float(*n, *fty, neg), (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)), (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)), (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported), @@ -57,12 +55,14 @@ crate fn lit_to_const<'tcx>( Ok(ty::Const::from_value(tcx, lit, ty)) } -fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result, ()> { +fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> ConstValue<'tcx> { let num = num.as_str(); use rustc_apfloat::ieee::{Double, Single}; let scalar = match fty { ty::FloatTy::F32 => { - let rust_f = num.parse::().map_err(|_| ())?; + let rust_f = num + .parse::() + .unwrap_or_else(|e| panic!("f32 failed to parse `{}`: {:?}", num, e)); let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) }); @@ -82,7 +82,9 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result { - let rust_f = num.parse::().map_err(|_| ())?; + let rust_f = num + .parse::() + .unwrap_or_else(|e| panic!("f64 failed to parse `{}`: {:?}", num, e)); let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e) }); @@ -103,5 +105,5 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Result Cx<'tcx> { expr: block.expr.map(|expr| self.mirror_expr(expr)), safety_mode: match block.rules { hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe, - hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id), - hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe, - hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe, + hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated) => { + BlockSafety::BuiltinUnsafe + } + hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) => { + BlockSafety::ExplicitUnsafe(block.hir_id) + } }, } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index aa4acfab5c..c3908ddd4f 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -228,14 +228,14 @@ impl<'tcx> Cx<'tcx> { expr: self.mirror_expr(e), }) .collect(); - ExprKind::Adt { + ExprKind::Adt(Box::new(Adt { adt_def, substs, variant_index: index, fields: field_refs, user_ty, base: None, - } + })) } else { ExprKind::Call { ty: self.typeck_results().node_type(fun.hir_id), @@ -362,7 +362,7 @@ impl<'tcx> Cx<'tcx> { let user_provided_types = self.typeck_results().user_provided_types(); let user_ty = user_provided_types.get(expr.hir_id).copied(); debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty); - ExprKind::Adt { + ExprKind::Adt(Box::new(Adt { adt_def: adt, variant_index: VariantIdx::new(0), substs, @@ -375,7 +375,7 @@ impl<'tcx> Cx<'tcx> { .copied() .collect(), }), - } + })) } AdtKind::Enum => { let res = self.typeck_results().qpath_res(qpath, expr.hir_id); @@ -388,14 +388,14 @@ impl<'tcx> Cx<'tcx> { self.typeck_results().user_provided_types(); let user_ty = user_provided_types.get(expr.hir_id).copied(); debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty); - ExprKind::Adt { + ExprKind::Adt(Box::new(Adt { adt_def: adt, variant_index: index, substs, user_ty, fields: self.field_refs(fields), base: None, - } + })) } _ => { span_bug!(expr.span, "unexpected res: {:?}", res); @@ -906,14 +906,14 @@ impl<'tcx> Cx<'tcx> { match ty.kind() { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. - ty::Adt(adt_def, substs) => ExprKind::Adt { + ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(Adt { adt_def, variant_index: adt_def.variant_index_with_ctor_id(def_id), substs, user_ty: user_provided_type, fields: box [], base: None, - }, + })), _ => bug!("unexpected ty: {:?}", ty), } } @@ -928,7 +928,11 @@ impl<'tcx> Cx<'tcx> { } else { let ptr = self.tcx.create_static_alloc(id); ExprKind::StaticRef { - literal: ty::Const::from_scalar(self.tcx, Scalar::Ptr(ptr.into()), ty), + literal: ty::Const::from_scalar( + self.tcx, + Scalar::from_pointer(ptr.into(), &self.tcx), + ty, + ), def_id: id, } }; diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 49ba71e352..604e544286 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -67,12 +67,6 @@ impl<'tcx> Cx<'tcx> { match self.tcx.at(sp).lit_to_const(LitToConstInput { lit, ty, neg }) { Ok(c) => c, - Err(LitToConstError::UnparseableFloat) => { - // FIXME(#31407) this is only necessary because float parsing is buggy - self.tcx.sess.span_err(sp, "could not evaluate float literal (see issue #31407)"); - // create a dummy value and continue compiling - self.tcx.const_error(ty) - } Err(LitToConstError::Reported) => { // create a dummy value and continue compiling self.tcx.const_error(ty) 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 389a759531..22c07fbec6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -84,7 +84,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { } impl PatCtxt<'_, '_> { - fn report_inlining_errors(&self, pat_span: Span) { + fn report_inlining_errors(&self) { for error in &self.errors { match *error { PatternError::StaticInPattern(span) => { @@ -96,14 +96,6 @@ impl PatCtxt<'_, '_> { PatternError::ConstParamInPattern(span) => { self.span_e0158(span, "const parameters cannot be referenced in patterns") } - PatternError::FloatBug => { - // FIXME(#31407) this is only necessary because float parsing is buggy - rustc_middle::mir::interpret::struct_error( - self.tcx.at(pat_span), - "could not evaluate float literal (see issue #31407)", - ) - .emit(); - } PatternError::NonConstPath(span) => { rustc_middle::mir::interpret::struct_error( self.tcx.at(span), @@ -142,7 +134,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(pattern)); if !patcx.errors.is_empty() { *have_errors = true; - patcx.report_inlining_errors(pat.span); + patcx.report_inlining_errors(); } (pattern, pattern_ty) } 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 369fff0045..926bd830da 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 @@ -133,9 +133,6 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { traits::NonStructuralMatchTy::Generator => { "generators cannot be used in patterns".to_string() } - traits::NonStructuralMatchTy::Closure => { - "closures cannot be used in patterns".to_string() - } traits::NonStructuralMatchTy::Param => { bug!("use of a constant whose type is a parameter inside a pattern") } @@ -272,12 +269,14 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { let kind = match cv.ty.kind() { ty::Float(_) => { - tcx.struct_span_lint_hir( - lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - id, - span, - |lint| lint.build("floating-point types cannot be used in patterns").emit(), - ); + if self.include_lint_checks { + tcx.struct_span_lint_hir( + lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, + id, + span, + |lint| lint.build("floating-point types cannot be used in patterns").emit(), + ); + } PatKind::Constant { value: cv } } ty::Adt(adt_def, _) if adt_def.is_union() => { @@ -488,17 +487,29 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. _ => { - let old = self.behind_reference.replace(true); - // In case there are structural-match violations somewhere in this subpattern, - // we fall back to a const pattern. If we do not do this, we may end up with - // a !structural-match constant that is not of reference type, which makes it - // very hard to invoke `PartialEq::eq` on it as a fallback. - let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) { - Ok(subpattern) => PatKind::Deref { subpattern }, - Err(_) => PatKind::Constant { value: cv }, - }; - self.behind_reference.set(old); - val + if !pointee_ty.is_sized(tcx.at(span), param_env) { + // `tcx.deref_const()` 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); + if self.include_lint_checks { + tcx.sess.span_err(span, &msg); + } else { + tcx.sess.delay_span_bug(span, &msg); + } + PatKind::Wild + } else { + let old = self.behind_reference.replace(true); + // In case there are structural-match violations somewhere in this subpattern, + // we fall back to a const pattern. If we do not do this, we may end up with + // a !structural-match constant that is not of reference type, which makes it + // very hard to invoke `PartialEq::eq` on it as a fallback. + let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) { + Ok(subpattern) => PatKind::Deref { subpattern }, + Err(_) => PatKind::Constant { value: cv }, + }; + self.behind_reference.set(old); + val + } } }, ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => { 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 4b5b648c50..ace13ea446 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -123,7 +123,7 @@ impl IntRange { // straight to the result, after doing a bit of checking. (We // could remove this branch and just fall through, which // is more general but much slower.) - if let Ok(bits) = scalar.to_bits_or_ptr(target_size, &tcx) { + if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size) { return Some(bits); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3225d302cb..dd265d881e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -31,7 +31,6 @@ crate enum PatternError { AssocConstInPattern(Span), ConstParamInPattern(Span), StaticInPattern(Span), - FloatBug, NonConstPath(Span), } @@ -325,7 +324,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_tuple_subpats( &mut self, - pats: &'tcx [&'tcx hir::Pat<'tcx>], + pats: &'tcx [hir::Pat<'tcx>], expected_len: usize, gap_pos: Option, ) -> Vec> { @@ -338,7 +337,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .collect() } - fn lower_patterns(&mut self, pats: &'tcx [&'tcx hir::Pat<'tcx>]) -> Vec> { + fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec> { pats.iter().map(|p| self.lower_pattern(p)).collect() } @@ -350,9 +349,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { &mut self, span: Span, ty: Ty<'tcx>, - prefix: &'tcx [&'tcx hir::Pat<'tcx>], + prefix: &'tcx [hir::Pat<'tcx>], slice: &'tcx Option<&'tcx hir::Pat<'tcx>>, - suffix: &'tcx [&'tcx hir::Pat<'tcx>], + suffix: &'tcx [hir::Pat<'tcx>], ) -> PatKind<'tcx> { let prefix = self.lower_patterns(prefix); let slice = self.lower_opt_pattern(slice); @@ -423,6 +422,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => { let pattern_error = match res { Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span), + Res::Def(DefKind::Static, _) => PatternError::StaticInPattern(span), _ => PatternError::NonConstPath(span), }; self.errors.push(pattern_error); @@ -468,11 +468,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { Ok(Some(i)) => i, Ok(None) => { - self.errors.push(if is_associated_const { - PatternError::AssocConstInPattern(span) - } else { - PatternError::StaticInPattern(span) - }); + // It should be assoc consts if there's no error but we cannot resolve it. + debug_assert!(is_associated_const); + + self.errors.push(PatternError::AssocConstInPattern(span)); return pat_from_kind(PatKind::Wild); } @@ -563,10 +562,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, - Err(LitToConstError::UnparseableFloat) => { - self.errors.push(PatternError::FloatBug); - PatKind::Wild - } Err(LitToConstError::Reported) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_mir_build/src/thir/visit.rs index 1a60b1de7f..ce5d4362c0 100644 --- a/compiler/rustc_mir_build/src/thir/visit.rs +++ b/compiler/rustc_mir_build/src/thir/visit.rs @@ -1,4 +1,4 @@ -use rustc_middle::thir::*; +use rustc_middle::thir::{self, *}; use rustc_middle::ty::Const; pub trait Visitor<'a, 'tcx: 'a>: Sized { @@ -20,6 +20,10 @@ pub trait Visitor<'a, 'tcx: 'a>: Sized { walk_arm(self, arm); } + fn visit_pat(&mut self, pat: &Pat<'tcx>) { + walk_pat(self, pat); + } + fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {} } @@ -94,7 +98,14 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp visitor.visit_expr(&visitor.thir()[field]); } } - Adt { ref fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => { + Adt(box thir::Adt { + ref fields, + ref base, + adt_def: _, + variant_index: _, + substs: _, + user_ty: _, + }) => { for field in &**fields { visitor.visit_expr(&visitor.thir()[field.expr]); } @@ -142,18 +153,19 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp } pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) { - match stmt.kind { - StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]), + match &stmt.kind { + StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]), StmtKind::Let { initializer, remainder_scope: _, init_scope: _, - pattern: _, + ref pattern, lint_level: _, } => { if let Some(init) = initializer { - visitor.visit_expr(&visitor.thir()[init]); + visitor.visit_expr(&visitor.thir()[*init]); } + visitor.visit_pat(pattern); } } } @@ -170,10 +182,56 @@ pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &B pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) { match arm.guard { Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]), - Some(Guard::IfLet(ref _pat, expr)) => { + Some(Guard::IfLet(ref pat, expr)) => { + visitor.visit_pat(pat); visitor.visit_expr(&visitor.thir()[expr]); } None => {} } + visitor.visit_pat(&arm.pattern); visitor.visit_expr(&visitor.thir()[arm.body]); } + +pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) { + use PatKind::*; + match pat.kind.as_ref() { + AscribeUserType { subpattern, ascription: _ } + | Deref { subpattern } + | Binding { + subpattern: Some(subpattern), + mutability: _, + mode: _, + var: _, + ty: _, + is_primary: _, + name: _, + } => visitor.visit_pat(&subpattern), + Binding { .. } | Wild => {} + Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => { + for subpattern in subpatterns { + visitor.visit_pat(&subpattern.pattern); + } + } + Constant { value } => visitor.visit_const(value), + Range(range) => { + visitor.visit_const(range.lo); + visitor.visit_const(range.hi); + } + Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { + for subpattern in prefix { + visitor.visit_pat(&subpattern); + } + if let Some(pat) = slice { + visitor.visit_pat(pat); + } + for subpattern in suffix { + visitor.visit_pat(&subpattern); + } + } + Or { pats } => { + for pat in pats { + visitor.visit_pat(&pat); + } + } + }; +} diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index c887729c35..60c2175719 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -19,4 +19,3 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_ast = { path = "../rustc_ast" } unicode-normalization = "0.1.11" -smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 1c2f9a9645..98befe4066 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1,12 +1,14 @@ -use rustc_ast::ast::AttrStyle; +use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_lexer::unescape::{self, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; +use rustc_session::lint::builtin::RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX; +use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::ParseSess; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{BytePos, Pos, Span}; +use rustc_span::{edition::Edition, BytePos, Pos, Span}; use tracing::debug; @@ -166,12 +168,18 @@ impl<'a> StringReader<'a> { 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::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); @@ -491,6 +499,42 @@ impl<'a> StringReader<'a> { FatalError.raise() } + // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021, + // using a (unknown) prefix is an error. In earlier editions, however, they + // only result in a (allowed by default) lint, and are treated as regular + // identifier tokens. + fn report_unknown_prefix(&self, start: BytePos) { + let prefix_span = self.mk_sp(start, self.pos); + let msg = format!("prefix `{}` is unknown", self.str_from_to(start, self.pos)); + + let expn_data = prefix_span.ctxt().outer_expn_data(); + + if expn_data.edition >= Edition::Edition2021 { + // In Rust 2021, this is a hard error. + let mut err = self.sess.span_diagnostic.struct_span_err(prefix_span, &msg); + err.span_label(prefix_span, "unknown prefix"); + if expn_data.is_root() { + err.span_suggestion_verbose( + prefix_span.shrink_to_hi(), + "consider inserting whitespace here", + " ".into(), + Applicability::MachineApplicable, + ); + } + err.note("prefixed identifiers and literals are reserved since Rust 2021"); + err.emit(); + } else { + // Before Rust 2021, only emit a lint for migration. + self.sess.buffer_lint_with_diagnostic( + &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + prefix_span, + ast::CRATE_NODE_ID, + &msg, + BuiltinLintDiagnostics::ReservedPrefix(prefix_span), + ); + } + } + /// Note: It was decided to not add a test case, because it would be too big. /// fn report_too_many_hashes(&self, start: BytePos, found: usize) -> ! { diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index 40e2e34aa0..3eebc088f3 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -1,5 +1,5 @@ // Characters and their corresponding confusables were collected from -// http://www.unicode.org/Public/security/10.0.0/confusables.txt +// https://www.unicode.org/Public/security/10.0.0/confusables.txt use super::StringReader; use crate::token; diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 8b05038907..e9f0038b2d 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -64,7 +64,14 @@ impl<'a> Parser<'a> { } self.bump(); just_parsed_doc_comment = true; - Some(attr::mk_doc_comment(comment_kind, attr_style, data, self.prev_token.span)) + // Always make an outer attribute - this allows us to recover from a misplaced + // inner attribute. + Some(attr::mk_doc_comment( + comment_kind, + ast::AttrStyle::Outer, + data, + self.prev_token.span, + )) } else { None }; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0c814ccfdc..ef05f64da9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,4 +1,4 @@ -use super::pat::{RecoverComma, PARAM_EXPECTED}; +use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken}; @@ -431,7 +431,8 @@ impl<'a> Parser<'a> { let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span); let limits = if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; - Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits), AttrVec::new())) + let range = self.mk_range(Some(lhs), rhs, limits); + Ok(self.mk_expr(span, range, AttrVec::new())) } fn is_at_start_of_range_notation_rhs(&self) -> bool { @@ -479,7 +480,8 @@ impl<'a> Parser<'a> { } else { (lo, None) }; - Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits), attrs.into())) + let range = this.mk_range(None, opt_end, limits); + Ok(this.mk_expr(span, range, attrs.into())) }) } @@ -1813,7 +1815,7 @@ impl<'a> Parser<'a> { /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; - let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?; self.expect(&token::Eq)?; let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) @@ -1876,7 +1878,7 @@ impl<'a> Parser<'a> { _ => None, }; - let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?; if !self.eat_keyword(kw::In) { self.error_missing_in_for_loop(); } @@ -2083,7 +2085,7 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; - let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes)?; + let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?; let guard = if this.eat_keyword(kw::If) { let if_span = this.prev_token.span; let cond = this.parse_expr()?; @@ -2117,7 +2119,7 @@ impl<'a> Parser<'a> { let span = body.span; return Ok(( ast::Arm { - attrs, + attrs: attrs.into(), pat, guard, body, @@ -2171,7 +2173,7 @@ impl<'a> Parser<'a> { Ok(( ast::Arm { - attrs, + attrs: attrs.into(), pat, guard, body: expr, @@ -2517,13 +2519,13 @@ impl<'a> Parser<'a> { } fn mk_range( - &self, + &mut self, start: Option>, end: Option>, limits: RangeLimits, ) -> ExprKind { if end.is_none() && limits == RangeLimits::Closed { - self.error_inclusive_range_with_no_end(self.prev_token.span); + self.inclusive_range_with_incorrect_end(self.prev_token.span); ExprKind::Err } else { ExprKind::Range(start, end, limits) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 54e6ff6272..2ce63d011f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1143,7 +1143,7 @@ impl<'a> Parser<'a> { ident, vis, id: DUMMY_NODE_ID, - attrs: variant_attrs, + attrs: variant_attrs.into(), data: struct_def, disr_expr, span: vlo.to(this.prev_token.span), @@ -1286,7 +1286,7 @@ impl<'a> Parser<'a> { ident: None, id: DUMMY_NODE_ID, ty, - attrs, + attrs: attrs.into(), is_placeholder: false, }, TrailingToken::MaybeComma, @@ -1460,7 +1460,7 @@ impl<'a> Parser<'a> { vis, id: DUMMY_NODE_ID, ty, - attrs, + attrs: attrs.into(), is_placeholder: false, }) } @@ -1791,7 +1791,13 @@ impl<'a> Parser<'a> { if self.check_keyword(kw::Pub) { let sp = sp_start.to(self.prev_token.span); if let Ok(snippet) = self.span_to_snippet(sp) { - let vis = self.parse_visibility(FollowedByType::No)?; + let vis = match self.parse_visibility(FollowedByType::No) { + Ok(v) => v, + Err(mut d) => { + d.cancel(); + return Err(err); + } + }; let vs = pprust::vis_to_string(&vis); let vs = vs.trim_end(); err.span_suggestion( diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index cd9f84db5e..51d4e007b5 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -14,7 +14,7 @@ use crate::lexer::UnmatchedBrace; pub use attr_wrapper::AttrWrapper; pub use diagnostics::AttemptLocalParseRecovery; use diagnostics::Error; -pub use pat::RecoverComma; +pub use pat::{RecoverColon, RecoverComma}; pub use path::PathStyle; use rustc_ast::ptr::P; diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 30a6b61407..313d9db58f 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; -use crate::parser::pat::RecoverComma; +use crate::parser::pat::{RecoverColon, RecoverComma}; use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle}; impl<'a> Parser<'a> { @@ -125,7 +125,7 @@ impl<'a> Parser<'a> { token::NtPat(self.collect_tokens_no_attrs(|this| match kind { NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None), NonterminalKind::PatWithOr { .. } => { - this.parse_pat_allow_top_alt(None, RecoverComma::No) + this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) } _ => unreachable!(), })?) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 418122202b..7219e39ea6 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -24,6 +24,13 @@ pub enum RecoverComma { No, } +/// Whether or not to recover a `:` when parsing patterns that were meant to be paths. +#[derive(PartialEq, Copy, Clone)] +pub enum RecoverColon { + Yes, + No, +} + /// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid /// emitting duplicate diagnostics. #[derive(Debug, Clone, Copy)] @@ -58,8 +65,9 @@ impl<'a> Parser<'a> { &mut self, expected: Expected, rc: RecoverComma, + ra: RecoverColon, ) -> PResult<'a, P> { - self.parse_pat_allow_top_alt_inner(expected, rc).map(|(pat, _)| pat) + self.parse_pat_allow_top_alt_inner(expected, rc, ra).map(|(pat, _)| pat) } /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true = @@ -68,6 +76,7 @@ impl<'a> Parser<'a> { &mut self, expected: Expected, rc: RecoverComma, + ra: RecoverColon, ) -> PResult<'a, (P, bool)> { // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated // suggestions (which bothers rustfix). @@ -89,6 +98,56 @@ impl<'a> Parser<'a> { // If we parsed a leading `|` which should be gated, // then we should really gate the leading `|`. // This complicated procedure is done purely for diagnostics UX. + let mut first_pat = first_pat; + + if let (RecoverColon::Yes, token::Colon) = (ra, &self.token.kind) { + if matches!( + first_pat.kind, + PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) + | PatKind::Path(..) + ) && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) + { + // The pattern looks like it might be a path with a `::` -> `:` typo: + // `match foo { bar:baz => {} }` + let span = self.token.span; + // We only emit "unexpected `:`" error here if we can successfully parse the + // whole pattern correctly in that case. + let snapshot = self.clone(); + + // Create error for "unexpected `:`". + match self.expected_one_of_not_found(&[], &[]) { + Err(mut err) => { + self.bump(); // Skip the `:`. + match self.parse_pat_no_top_alt(expected) { + Err(mut inner_err) => { + // Carry on as if we had not done anything, callers will emit a + // reasonable error. + inner_err.cancel(); + err.cancel(); + *self = snapshot; + } + Ok(pat) => { + // We've parsed the rest of the pattern. + err.span_suggestion( + span, + "maybe write a path separator here", + "::".to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + first_pat = + self.mk_pat(first_pat.span.to(pat.span), PatKind::Wild); + } + } + } + _ => { + // Carry on as if we had not done anything. This should be unreachable. + *self = snapshot; + } + }; + } + } + if let Some(leading_vert_span) = leading_vert_span { // If there was a leading vert, treat this as an or-pattern. This improves // diagnostics. @@ -140,7 +199,8 @@ impl<'a> Parser<'a> { // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level // or-patterns so that we can detect when a user tries to use it. This allows us to print a // better error message. - let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, rc)?; + let (pat, trailing_vert) = + self.parse_pat_allow_top_alt_inner(expected, rc, RecoverColon::No)?; let colon = self.eat(&token::Colon); if let PatKind::Or(pats) = &pat.kind { @@ -350,7 +410,7 @@ impl<'a> Parser<'a> { } else if self.check(&token::OpenDelim(token::Bracket)) { // Parse `[pat, pat,...]` as a slice pattern. let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| { - p.parse_pat_allow_top_alt(None, RecoverComma::No) + p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) })?; PatKind::Slice(pats) } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) { @@ -563,8 +623,9 @@ impl<'a> Parser<'a> { /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { - let (fields, trailing_comma) = - self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?; + let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { + p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) + })?; // Here, `(pat,)` is a tuple pattern. // For backward compatibility, `(..)` is a tuple pattern as well. @@ -715,7 +776,6 @@ impl<'a> Parser<'a> { } else if self.eat(&token::DotDotEq) { RangeEnd::Included(RangeSyntax::DotDotEq) } else if self.eat(&token::DotDot) { - self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_token.span); RangeEnd::Excluded } else { return None; @@ -735,18 +795,50 @@ impl<'a> Parser<'a> { Some(self.parse_pat_range_end()?) } else { // Parsing e.g. `X..`. - self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span)); if let RangeEnd::Included(_) = re.node { // FIXME(Centril): Consider semantic errors instead in `ast_validation`. - // Possibly also do this for `X..=` in *expression* contexts. - self.error_inclusive_range_with_no_end(re.span); + self.inclusive_range_with_incorrect_end(re.span); } None }; Ok(PatKind::Range(Some(begin), end, re)) } - pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) { + pub(super) fn inclusive_range_with_incorrect_end(&mut self, span: Span) { + let tok = &self.token; + + // If the user typed "..==" instead of "..=", we want to give them + // a specific error message telling them to use "..=". + // Otherwise, we assume that they meant to type a half open exclusive + // range and give them an error telling them to do that instead. + if matches!(tok.kind, token::Eq) && tok.span.lo() == span.hi() { + let span_with_eq = span.to(tok.span); + + // Ensure the user doesn't receive unhelpful unexpected token errors + self.bump(); + if self.is_pat_range_end_start(0) { + let _ = self.parse_pat_range_end(); + } + + self.error_inclusive_range_with_extra_equals(span_with_eq); + } else { + self.error_inclusive_range_with_no_end(span); + } + } + + fn error_inclusive_range_with_extra_equals(&self, span: Span) { + self.struct_span_err(span, "unexpected `=` after inclusive range") + .span_suggestion_short( + span, + "use `..=` instead", + "..=".to_string(), + Applicability::MaybeIncorrect, + ) + .note("inclusive ranges end with a single equals sign (`..=`)") + .emit(); + } + + fn error_inclusive_range_with_no_end(&self, span: Span) { struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end") .span_suggestion_short( span, @@ -875,8 +967,9 @@ impl<'a> Parser<'a> { /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`). fn parse_pat_tuple_struct(&mut self, qself: Option, path: Path) -> PResult<'a, PatKind> { - let (fields, _) = - self.parse_paren_comma_seq(|p| p.parse_pat_allow_top_alt(None, RecoverComma::No))?; + let (fields, _) = self.parse_paren_comma_seq(|p| { + p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No) + })?; if qself.is_some() { self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); } @@ -1035,7 +1128,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form `fieldname: pat`. let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No)?; + let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)?; hi = pat.span; (pat, fieldname, false) } else { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index de5a563260..1fbf01b1b9 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -393,7 +393,7 @@ impl<'a> Parser<'a> { let and_span = self.prev_token.span; let mut opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None }; - let mutbl = self.parse_mutability(); + let mut mutbl = self.parse_mutability(); if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() { // A lifetime is invalid here: it would be part of a bare trait bound, which requires // it to be followed by a plus, but we disallow plus in the pointee type. @@ -417,6 +417,26 @@ impl<'a> Parser<'a> { opt_lifetime = Some(self.expect_lifetime()); } + } else if self.token.is_keyword(kw::Dyn) + && mutbl == Mutability::Not + && self.look_ahead(1, |t| t.is_keyword(kw::Mut)) + { + // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`. + let span = and_span.to(self.look_ahead(1, |t| t.span)); + let mut err = self.struct_span_err(span, "`mut` must precede `dyn`"); + err.span_suggestion( + span, + "place `mut` before `dyn`", + "&mut dyn".to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + + // Recovery + mutbl = Mutability::Mut; + let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing); + self.bump(); + self.bump_with((dyn_tok, dyn_tok_sp)); } let ty = self.parse_ty_no_plus()?; Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl })) diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index 9fd0497fff..b7693a85ad 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -144,8 +144,7 @@ fn format_align_fill() { } #[test] fn format_counts() { - use rustc_span::{edition, SessionGlobals, SESSION_GLOBALS}; - SESSION_GLOBALS.set(&SessionGlobals::new(edition::DEFAULT_EDITION), || { + rustc_span::create_default_session_globals_then(|| { same( "{:10x}", &[NextArgument(Argument { diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 4069fb2127..c69d4886bd 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -17,6 +17,5 @@ rustc_target = { path = "../rustc_target" } rustc_ast = { path = "../rustc_ast" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } -rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_lexer = { path = "../rustc_lexer" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9c42a42fe6..71231830e9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -97,6 +97,10 @@ impl CheckAttrVisitor<'tcx> { | sym::rustc_dirty | sym::rustc_if_this_changed | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), + sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target), + sym::default_method_body_is_const => { + self.check_default_method_body_is_const(attr, span, target) + } _ => true, }; // lint-only checks @@ -234,6 +238,25 @@ impl CheckAttrVisitor<'tcx> { } } + /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition. + fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: &Span, target: Target) -> bool { + match target { + Target::Fn + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + _ => { + self.tcx + .sess + .struct_span_err( + attr.span, + "attribute should be applied to a function definition", + ) + .span_label(*span, "not a function definition") + .emit(); + false + } + } + } + /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid. fn check_track_caller( &self, @@ -456,6 +479,8 @@ impl CheckAttrVisitor<'tcx> { _ => None, } } + // we check the validity of params elsewhere + Target::Param => return false, _ => None, } { return err_fn(meta.span(), &format!("isn't allowed on {}", err)); @@ -523,8 +548,11 @@ impl CheckAttrVisitor<'tcx> { self.doc_attr_str_error(meta, "keyword"); return false; } - match self.tcx.hir().expect_item(hir_id).kind { - ItemKind::Mod(ref module) => { + match self.tcx.hir().find(hir_id).and_then(|node| match node { + hir::Node::Item(item) => Some(&item.kind), + _ => None, + }) { + Some(ItemKind::Mod(ref module)) => { if !module.item_ids.is_empty() { self.tcx .sess @@ -1193,17 +1221,41 @@ impl CheckAttrVisitor<'tcx> { let mut is_transparent = false; for hint in &hints { + if !hint.is_meta_item() { + struct_span_err!( + self.tcx.sess, + hint.span(), + E0565, + "meta item in `repr` must be an identifier" + ) + .emit(); + continue; + } + let (article, allowed_targets) = match hint.name_or_empty() { - _ if !matches!(target, Target::Struct | Target::Enum | Target::Union) => { - ("a", "struct, enum, or union") - } - name @ sym::C | name @ sym::align => { - is_c |= name == sym::C; + sym::C => { + is_c = true; match target { Target::Struct | Target::Union | Target::Enum => continue, _ => ("a", "struct, enum, or union"), } } + sym::align => { + if let (Target::Fn, true) = (target, !self.tcx.features().fn_align) { + feature_err( + &self.tcx.sess.parse_sess, + sym::fn_align, + hint.span(), + "`repr(align)` attributes on functions are unstable", + ) + .emit(); + } + + match target { + Target::Struct | Target::Union | Target::Enum | Target::Fn => continue, + _ => ("a", "struct, enum, function, or union"), + } + } sym::packed => { if target != Target::Struct && target != Target::Union { ("a", "struct or union") @@ -1260,7 +1312,17 @@ impl CheckAttrVisitor<'tcx> { continue; } } - _ => continue, + _ => { + struct_span_err!( + self.tcx.sess, + hint.span(), + E0552, + "unrecognized representation hint" + ) + .emit(); + + continue; + } }; struct_span_err!( @@ -1406,6 +1468,29 @@ impl CheckAttrVisitor<'tcx> { } } } + + /// default_method_body_is_const should only be applied to trait methods with default bodies. + fn check_default_method_body_is_const( + &self, + attr: &Attribute, + span: &Span, + target: Target, + ) -> bool { + match target { + Target::Method(MethodKind::Trait { body: true }) => true, + _ => { + self.tcx + .sess + .struct_span_err( + attr.span, + "attribute should be applied to a trait method with body", + ) + .span_label(*span, "not a trait method or missing a body") + .emit(); + false + } + } + } } impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index da713566c3..6ee54cfe37 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -8,11 +8,13 @@ //! through, but errors for structured control flow in a `const` should be emitted here. use rustc_attr as attr; +use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_middle::hir::map::Map; +use rustc_middle::ty; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; @@ -59,12 +61,80 @@ impl NonConstExpr { fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let mut vis = CheckConstVisitor::new(tcx); tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor()); + tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckConstTraitVisitor::new(tcx)); } pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_mod_const_bodies, ..*providers }; } +struct CheckConstTraitVisitor<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> CheckConstTraitVisitor<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + CheckConstTraitVisitor { tcx } + } +} + +impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<'tcx> { + /// check for const trait impls, and errors if the impl uses provided/default functions + /// of the trait being implemented; as those provided functions can be non-const. + fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { + let _: Option<_> = try { + if let hir::ItemKind::Impl(ref imp) = item.kind { + if let hir::Constness::Const = imp.constness { + let did = imp.of_trait.as_ref()?.trait_def_id()?; + let mut to_implement = FxHashSet::default(); + + for did in self.tcx.associated_item_def_ids(did) { + if let ty::AssocItem { + kind: ty::AssocKind::Fn, ident, defaultness, .. + } = self.tcx.associated_item(*did) + { + // we can ignore functions that do not have default bodies: + // if those are unimplemented it will be catched by typeck. + if defaultness.has_value() + && !self.tcx.has_attr(*did, sym::default_method_body_is_const) + { + to_implement.insert(ident); + } + } + } + + for it in imp + .items + .iter() + .filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. })) + { + to_implement.remove(&it.ident); + } + + // all nonconst trait functions (not marked with #[default_method_body_is_const]) + // must be implemented + if !to_implement.is_empty() { + self.tcx + .sess + .struct_span_err( + item.span, + "const trait implementations may not use non-const default functions", + ) + .note(&format!("`{}` not implemented", to_implement.into_iter().map(|id| id.to_string()).collect::>().join("`, `"))) + .emit(); + } + } + } + }; + } + + fn visit_trait_item(&mut self, _: &'hir hir::TraitItem<'hir>) {} + + fn visit_impl_item(&mut self, _: &'hir hir::ImplItem<'hir>) {} + + fn visit_foreign_item(&mut self, _: &'hir hir::ForeignItem<'hir>) {} +} + #[derive(Copy, Clone)] struct CheckConstVisitor<'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index c1b6da97f4..b71ec700f8 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -151,6 +151,60 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } + #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. + fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) { + fn check_for_self_assign_helper( + tcx: TyCtxt<'tcx>, + typeck_results: &'tcx ty::TypeckResults<'tcx>, + lhs: &'tcx hir::Expr<'tcx>, + rhs: &'tcx hir::Expr<'tcx>, + ) -> bool { + match (&lhs.kind, &rhs.kind) { + (hir::ExprKind::Path(ref qpath_l), hir::ExprKind::Path(ref qpath_r)) => { + if let (Res::Local(id_l), Res::Local(id_r)) = ( + typeck_results.qpath_res(qpath_l, lhs.hir_id), + typeck_results.qpath_res(qpath_r, rhs.hir_id), + ) { + if id_l == id_r { + return true; + } + } + return false; + } + (hir::ExprKind::Field(lhs_l, ident_l), hir::ExprKind::Field(lhs_r, ident_r)) => { + if ident_l == ident_r { + return check_for_self_assign_helper(tcx, typeck_results, lhs_l, lhs_r); + } + return false; + } + _ => { + return false; + } + } + } + + if let hir::ExprKind::Assign(lhs, rhs, _) = assign.kind { + if check_for_self_assign_helper(self.tcx, self.typeck_results(), lhs, rhs) + && !assign.span.from_expansion() + { + let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..)); + self.tcx.struct_span_lint_hir( + 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(); + }, + ) + } + } + } + fn handle_field_pattern_match( &mut self, lhs: &hir::Pat<'_>, diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index f345d45d17..ddcc6fc123 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -121,7 +121,7 @@ fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashMap, visitor: &EntryContext<'_, '_>) -> Option<(De Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Start)) } else if let Some((hir_id, _)) = visitor.attr_main_fn { Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Main)) - } else if let Some(def_id) = tcx.main_def.and_then(|main_def| main_def.opt_fn_def_id()) { - if tcx.main_def.unwrap().is_import && !tcx.features().imported_main { - let span = tcx.main_def.unwrap().span; - feature_err( - &tcx.sess.parse_sess, - sym::imported_main, - span, - "using an imported function as entry point `main` is experimental", - ) - .emit(); - } - Some((def_id, EntryFnType::Main)) } else { + if let Some(main_def) = tcx.resolutions(()).main_def { + if let Some(def_id) = main_def.opt_fn_def_id() { + // non-local main imports are handled below + if def_id.is_local() { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + if matches!(tcx.hir().find(hir_id), Some(Node::ForeignItem(_))) { + tcx.sess + .struct_span_err( + tcx.hir().span(hir_id), + "the `main` function cannot be declared in an `extern` block", + ) + .emit(); + return None; + } + } + + if main_def.is_import && !tcx.features().imported_main { + let span = main_def.span; + feature_err( + &tcx.sess.parse_sess, + sym::imported_main, + span, + "using an imported function as entry point `main` is experimental", + ) + .emit(); + } + return Some((def_id, EntryFnType::Main)); + } + } no_main_err(tcx, visitor); None } @@ -209,7 +226,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { err.note(¬e); } - if let Some(main_def) = tcx.main_def { + if let Some(main_def) = tcx.resolutions(()).main_def { if main_def.opt_fn_def_id().is_none() { // There is something at `crate::main`, but it is not a function definition. err.span_label(main_def.span, &format!("non-function item at `crate::main` is found")); diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 118fcca450..3a88d1932a 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -257,9 +257,6 @@ impl LanguageItemCollector<'tcx> { | LangItem::Unpin | LangItem::Termination | LangItem::Try - | LangItem::Send - | LangItem::UnwindSafe - | LangItem::RefUnwindSafe => Some(0), // Not a trait @@ -309,7 +306,7 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { let mut collector = LanguageItemCollector::new(tcx); // Collect lang items in other crates. - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() { collector.collect_item(item_index, def_id); } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 28633faa20..cadb8d2358 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -10,6 +10,7 @@ #![feature(iter_zip)] #![feature(nll)] #![feature(min_specialization)] +#![feature(try_blocks)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index f41e0e0370..42a4753c29 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -20,6 +20,7 @@ use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use rustc_target::spec::abi::Abi; use std::cmp::Ordering; use std::iter; @@ -95,10 +96,12 @@ struct Annotator<'a, 'tcx> { impl<'a, 'tcx> Annotator<'a, 'tcx> { // Determine the stability for a node based on its attributes and inherited // stability. The stability is recorded in the index and used as the parent. + // If the node is a function, `fn_sig` is its signature fn annotate( &mut self, hir_id: HirId, item_sp: Span, + fn_sig: Option<&'tcx hir::FnSig<'tcx>>, kind: AnnotationKind, inherit_deprecation: InheritDeprecation, inherit_const_stability: InheritConstStability, @@ -163,13 +166,30 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp); + let mut const_span = None; - let const_stab = const_stab.map(|(const_stab, _)| { + let const_stab = const_stab.map(|(const_stab, const_span_node)| { let const_stab = self.tcx.intern_const_stability(const_stab); self.index.const_stab_map.insert(hir_id, const_stab); + const_span = Some(const_span_node); const_stab }); + // If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI, + // check if the function/method is const or the parent impl block is const + if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) { + if fn_sig.header.abi != Abi::RustIntrinsic + && fn_sig.header.abi != Abi::PlatformIntrinsic + && !fn_sig.header.is_const() + { + if !self.in_trait_impl + || (self.in_trait_impl && !self.tcx.is_const_fn_raw(hir_id.owner.to_def_id())) + { + missing_const_err(&self.tcx.sess, fn_sig.span, const_span); + } + } + } + // `impl const Trait for Type` items forward their const stability to their // immediate children. if const_stab.is_none() { @@ -367,6 +387,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { let orig_in_trait_impl = self.in_trait_impl; let mut kind = AnnotationKind::Required; let mut const_stab_inherit = InheritConstStability::No; + let mut fn_sig = None; + match i.kind { // Inherent impls and foreign modules serve only as containers for other items, // they don't have their own stability. They still can be annotated as unstable @@ -387,6 +409,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { self.annotate( ctor_hir_id, i.span, + None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -395,12 +418,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { ) } } + hir::ItemKind::Fn(ref item_fn_sig, _, _) => { + fn_sig = Some(item_fn_sig); + } _ => {} } self.annotate( i.hir_id(), i.span, + fn_sig, kind, InheritDeprecation::Yes, const_stab_inherit, @@ -411,9 +438,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { + let fn_sig = match ti.kind { + hir::TraitItemKind::Fn(ref fn_sig, _) => Some(fn_sig), + _ => None, + }; + self.annotate( ti.hir_id(), ti.span, + fn_sig, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -427,9 +460,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let kind = if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required }; + + let fn_sig = match ii.kind { + hir::ImplItemKind::Fn(ref fn_sig, _) => Some(fn_sig), + _ => None, + }; + self.annotate( ii.hir_id(), ii.span, + fn_sig, kind, InheritDeprecation::Yes, InheritConstStability::No, @@ -444,6 +484,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { self.annotate( var.id, var.span, + None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -453,6 +494,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { v.annotate( ctor_hir_id, var.span, + None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -470,6 +512,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { self.annotate( s.hir_id, s.span, + None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -484,6 +527,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { self.annotate( i.hir_id(), i.span, + None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -498,6 +542,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { self.annotate( md.hir_id(), md.span, + None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -517,6 +562,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { self.annotate( p.hir_id, p.span, + None, kind, InheritDeprecation::No, InheritConstStability::No, @@ -687,6 +733,7 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { annotator.annotate( hir::CRATE_HIR_ID, krate.item.inner, + None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, @@ -828,7 +875,8 @@ impl Visitor<'tcx> for Checker<'tcx> { fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { - self.tcx.check_stability(def_id, Some(id), path.span, None) + let method_span = path.segments.last().map(|s| s.ident.span); + self.tcx.check_stability(def_id, Some(id), path.span, method_span) } intravisit::walk_path(self, path) } @@ -938,7 +986,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { if !remaining_lib_features.is_empty() { check_features(&mut remaining_lib_features, &local_defined_features); - for &cnum in &*tcx.crates() { + for &cnum in tcx.crates(()) { if remaining_lib_features.is_empty() { break; } @@ -969,3 +1017,15 @@ 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 de369ba9bb..629513c7cf 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -53,7 +53,7 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { } let mut missing = FxHashSet::default(); - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { for &item in tcx.missing_lang_items(cnum).iter() { missing.insert(item); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index e64f12ef48..d969f50c1d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -156,6 +156,7 @@ where let leaf = leaf.subst(tcx, ct.substs); self.visit_const(leaf) } + ACNode::Cast(_, _, ty) => self.visit_ty(ty), ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { ControlFlow::CONTINUE } @@ -2030,7 +2031,7 @@ pub fn provide(providers: &mut Providers) { fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility { let def_id = def_id.expect_local(); - match tcx.visibilities.get(&def_id) { + match tcx.resolutions(()).visibilities.get(&def_id) { Some(vis) => *vis, None => { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 383e30ca29..6a1768b92d 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -12,16 +12,13 @@ measureme = "9.0.0" rustc-rayon-core = "0.3.1" tracing = "0.1" rustc_ast = { path = "../rustc_ast" } -rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_feature = { path = "../rustc_feature" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } -rustc_span = { path = "../rustc_span" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } -rustc_target = { path = "../rustc_target" } +rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 27a0dc4768..0ad360c7d8 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -3,6 +3,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_middle::infer::canonical::Canonical; use rustc_middle::mir; +use rustc_middle::traits; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::subst::{GenericArg, SubstsRef}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -14,7 +15,7 @@ use rustc_span::{Span, DUMMY_SP}; pub trait Key { /// Given an instance of this key, what crate is it referring to? /// This is used to find the provider. - fn query_crate(&self) -> CrateNum; + fn query_crate_is_local(&self) -> bool; /// In the event that a cycle occurs, if no explicit span has been /// given for a query with key `self`, what span should we use? @@ -22,8 +23,9 @@ pub trait Key { } impl Key for () { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { @@ -32,8 +34,9 @@ impl Key for () { } impl<'tcx> Key for ty::InstanceDef<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -42,8 +45,9 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> { } impl<'tcx> Key for ty::Instance<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -52,8 +56,9 @@ impl<'tcx> Key for ty::Instance<'tcx> { } impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { - fn query_crate(&self) -> CrateNum { - self.instance.query_crate() + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -62,8 +67,9 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { } impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { @@ -72,8 +78,9 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { } impl Key for CrateNum { - fn query_crate(&self) -> CrateNum { - *self + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + *self == LOCAL_CRATE } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -81,8 +88,9 @@ impl Key for CrateNum { } impl Key for LocalDefId { - fn query_crate(&self) -> CrateNum { - self.to_def_id().query_crate() + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.to_def_id().default_span(tcx) @@ -90,8 +98,9 @@ impl Key for LocalDefId { } impl Key for DefId { - fn query_crate(&self) -> CrateNum { - self.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) @@ -99,8 +108,9 @@ impl Key for DefId { } impl Key for ty::WithOptConstParam { - fn query_crate(&self) -> CrateNum { - self.did.query_crate() + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.did.default_span(tcx) @@ -108,8 +118,9 @@ impl Key for ty::WithOptConstParam { } impl Key for (DefId, DefId) { - fn query_crate(&self) -> CrateNum { - self.0.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -117,8 +128,9 @@ impl Key for (DefId, DefId) { } impl Key for (ty::Instance<'tcx>, LocalDefId) { - fn query_crate(&self) -> CrateNum { - self.0.query_crate() + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -126,8 +138,9 @@ impl Key for (ty::Instance<'tcx>, LocalDefId) { } impl Key for (DefId, LocalDefId) { - fn query_crate(&self) -> CrateNum { - self.0.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -135,8 +148,9 @@ impl Key for (DefId, LocalDefId) { } impl Key for (LocalDefId, DefId) { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -144,8 +158,9 @@ impl Key for (LocalDefId, DefId) { } impl Key for (DefId, Option) { - fn query_crate(&self) -> CrateNum { - self.0.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.0) @@ -153,8 +168,9 @@ impl Key for (DefId, Option) { } impl Key for (DefId, LocalDefId, Ident) { - fn query_crate(&self) -> CrateNum { - self.0.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -162,8 +178,9 @@ impl Key for (DefId, LocalDefId, Ident) { } impl Key for (CrateNum, DefId) { - fn query_crate(&self) -> CrateNum { - self.0 + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0 == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -171,8 +188,9 @@ impl Key for (CrateNum, DefId) { } impl Key for (DefId, SimplifiedType) { - fn query_crate(&self) -> CrateNum { - self.0.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -180,8 +198,9 @@ impl Key for (DefId, SimplifiedType) { } impl<'tcx> Key for SubstsRef<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -189,8 +208,9 @@ impl<'tcx> Key for SubstsRef<'tcx> { } impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { - fn query_crate(&self) -> CrateNum { - self.0.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -203,8 +223,9 @@ impl<'tcx> Key (ty::WithOptConstParam, SubstsRef<'tcx>), ) { - fn query_crate(&self) -> CrateNum { - (self.0).0.did.krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + (self.0).0.did.krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { (self.0).0.did.default_span(tcx) @@ -212,8 +233,9 @@ impl<'tcx> Key } impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -221,8 +243,9 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) { } impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { - fn query_crate(&self) -> CrateNum { - self.1.def_id().krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.1.def_id().krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.1.def_id()) @@ -230,8 +253,9 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { } impl<'tcx> Key for (&'tcx ty::Const<'tcx>, mir::Field) { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -239,8 +263,9 @@ impl<'tcx> Key for (&'tcx ty::Const<'tcx>, mir::Field) { } impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -248,8 +273,9 @@ impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> { } impl<'tcx> Key for ty::PolyTraitRef<'tcx> { - fn query_crate(&self) -> CrateNum { - self.def_id().krate + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.def_id().krate == LOCAL_CRATE } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) @@ -257,8 +283,9 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> { } impl<'tcx> Key for GenericArg<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -266,8 +293,9 @@ impl<'tcx> Key for GenericArg<'tcx> { } impl<'tcx> Key for mir::ConstantKind<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -275,8 +303,9 @@ impl<'tcx> Key for mir::ConstantKind<'tcx> { } impl<'tcx> Key for &'tcx ty::Const<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -284,8 +313,9 @@ impl<'tcx> Key for &'tcx ty::Const<'tcx> { } impl<'tcx> Key for Ty<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -293,8 +323,9 @@ impl<'tcx> Key for Ty<'tcx> { } impl<'tcx> Key for &'tcx ty::List> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -302,8 +333,9 @@ impl<'tcx> Key for &'tcx ty::List> { } impl<'tcx> Key for ty::ParamEnv<'tcx> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -311,8 +343,9 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> { } impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { - fn query_crate(&self) -> CrateNum { - self.value.query_crate() + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.value.query_crate_is_local() } fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.value.default_span(tcx) @@ -320,8 +353,9 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { } impl Key for Symbol { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -331,8 +365,9 @@ impl Key for Symbol { /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. impl<'tcx, T> Key for Canonical<'tcx, T> { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { @@ -341,8 +376,9 @@ impl<'tcx, T> Key for Canonical<'tcx, T> { } impl Key for (Symbol, u32, u32) { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { @@ -351,8 +387,20 @@ impl Key for (Symbol, u32, u32) { } impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) { - fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + +impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true } fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 4175fb6925..5022bf2653 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -1,12 +1,16 @@ //! Support for serializing the dep-graph and reloading it. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(min_specialization)] +#![feature(once_cell)] #![feature(rustc_attrs)] #![recursion_limit = "256"] +#[macro_use] +extern crate rustc_macros; #[macro_use] extern crate rustc_middle; #[macro_use] @@ -14,14 +18,12 @@ extern crate tracing; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::{DiagnosticBuilder, Handler}; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_errors::DiagnosticBuilder; use rustc_middle::dep_graph; use rustc_middle::ich::StableHashingContext; use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values}; use rustc_middle::ty::query::{Providers, QueryEngine}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_serialize::opaque; use rustc_span::Span; #[macro_use] @@ -43,7 +45,8 @@ use rustc_query_system::query::QueryAccessors; pub use rustc_query_system::query::QueryConfig; pub(crate) use rustc_query_system::query::QueryDescription; -use rustc_middle::ty::query::on_disk_cache; +mod on_disk_cache; +pub use on_disk_cache::OnDiskCache; mod profiling_support; pub use self::profiling_support::alloc_self_profile_query_strings; diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs similarity index 90% rename from compiler/rustc_middle/src/ty/query/on_disk_cache.rs rename to compiler/rustc_query_impl/src/on_disk_cache.rs index 6df8e64fad..b024668d63 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -1,9 +1,4 @@ -use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; -use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; -use crate::mir::{self, interpret}; -use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; -use crate::ty::context::TyCtxt; -use crate::ty::{self, Ty}; +use crate::QueryCtxt; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; use rustc_data_structures::thin_vec::ThinVec; @@ -12,6 +7,11 @@ use rustc_errors::Diagnostic; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; +use rustc_middle::mir::{self, interpret}; +use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_query_system::dep_graph::DepContext; use rustc_query_system::query::QueryContext; use rustc_serialize::{ @@ -20,12 +20,11 @@ use rustc_serialize::{ }; use rustc_session::Session; use rustc_span::hygiene::{ - ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext, - SyntaxContext, SyntaxContextData, + ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, }; use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::CachingSourceMapView; -use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP}; +use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP}; use std::collections::hash_map::Entry; use std::mem; @@ -84,7 +83,7 @@ pub struct OnDiskCache<'sess> { // `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively, // we could look up the `ExpnData` from the metadata of foreign crates, // but it seemed easier to have `OnDiskCache` be independent of the `CStore`. - expn_data: FxHashMap, + expn_data: UnhashMap, // Additional information used when decoding hygiene data. hygiene_context: HygieneDecodeContext, // Maps `DefPathHash`es to their `RawDefId`s from the *previous* @@ -92,6 +91,8 @@ pub struct OnDiskCache<'sess> { // we try to map a `DefPathHash` to its `DefId` in the current compilation // session. foreign_def_path_hashes: UnhashMap, + // Likewise for ExpnId. + foreign_expn_data: UnhashMap, // The *next* compilation sessison's `foreign_def_path_hashes` - at // the end of our current compilation session, this will get written @@ -119,8 +120,9 @@ struct Footer { // See `OnDiskCache.syntax_contexts` syntax_contexts: FxHashMap, // See `OnDiskCache.expn_data` - expn_data: FxHashMap, + expn_data: UnhashMap, foreign_def_path_hashes: UnhashMap, + foreign_expn_data: UnhashMap, } pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; @@ -183,9 +185,8 @@ impl EncodedSourceFileId { } } -impl<'sess> OnDiskCache<'sess> { - /// Creates a new `OnDiskCache` instance from the serialized data in `data`. - pub fn new(sess: &'sess Session, data: Vec, start_pos: usize) -> Self { +impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { + fn new(sess: &'sess Session, data: Vec, start_pos: usize) -> Self { debug_assert!(sess.opts.incremental.is_some()); // Wrap in a scope so we can borrow `data`. @@ -218,6 +219,7 @@ impl<'sess> OnDiskCache<'sess> { alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index), syntax_contexts: footer.syntax_contexts, expn_data: footer.expn_data, + foreign_expn_data: footer.foreign_expn_data, hygiene_context: Default::default(), foreign_def_path_hashes: footer.foreign_def_path_hashes, latest_foreign_def_path_hashes: Default::default(), @@ -225,7 +227,7 @@ impl<'sess> OnDiskCache<'sess> { } } - pub fn new_empty(source_map: &'sess SourceMap) -> Self { + fn new_empty(source_map: &'sess SourceMap) -> Self { Self { serialized_data: Vec::new(), file_index_to_stable_id: Default::default(), @@ -237,7 +239,8 @@ impl<'sess> OnDiskCache<'sess> { prev_diagnostics_index: Default::default(), alloc_decoding_state: AllocDecodingState::new(Vec::new()), syntax_contexts: FxHashMap::default(), - expn_data: FxHashMap::default(), + expn_data: UnhashMap::default(), + foreign_expn_data: UnhashMap::default(), hygiene_context: Default::default(), foreign_def_path_hashes: Default::default(), latest_foreign_def_path_hashes: Default::default(), @@ -245,11 +248,7 @@ impl<'sess> OnDiskCache<'sess> { } } - pub fn serialize<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - encoder: &mut FileEncoder, - ) -> FileEncodeResult { + fn serialize(&self, tcx: TyCtxt<'sess>, encoder: &mut FileEncoder) -> FileEncodeResult { // Serializing the `DepGraph` should not modify it. tcx.dep_graph.with_ignore(|| { // Allocate `SourceFileIndex`es. @@ -284,7 +283,7 @@ impl<'sess> OnDiskCache<'sess> { // Do this *before* we clone 'latest_foreign_def_path_hashes', since // loading existing queries may cause us to create new DepNodes, which // may in turn end up invoking `store_foreign_def_id_hash` - tcx.queries.exec_cache_promotions(tcx); + tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx)); let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone(); let hygiene_encode_context = HygieneEncodeContext::default(); @@ -307,7 +306,7 @@ impl<'sess> OnDiskCache<'sess> { tcx.sess.time("encode_query_results", || -> FileEncodeResult { let enc = &mut encoder; let qri = &mut query_result_index; - tcx.queries.encode_query_results(tcx, enc, qri) + QueryCtxt::from_tcx(tcx).encode_query_results(enc, qri) })?; // Encode diagnostics. @@ -351,7 +350,8 @@ impl<'sess> OnDiskCache<'sess> { }; let mut syntax_contexts = FxHashMap::default(); - let mut expn_ids = FxHashMap::default(); + let mut expn_data = UnhashMap::default(); + let mut foreign_expn_data = UnhashMap::default(); // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current // session. @@ -364,10 +364,14 @@ impl<'sess> OnDiskCache<'sess> { syntax_contexts.insert(index, pos); Ok(()) }, - |encoder, index, expn_data| -> FileEncodeResult { - let pos = AbsoluteBytePos::new(encoder.position()); - encoder.encode_tagged(TAG_EXPN_DATA, expn_data)?; - expn_ids.insert(index, pos); + |encoder, expn_id, data, hash| -> FileEncodeResult { + if expn_id.krate == LOCAL_CRATE { + let pos = AbsoluteBytePos::new(encoder.position()); + encoder.encode_tagged(TAG_EXPN_DATA, data)?; + expn_data.insert(hash, pos); + } else { + foreign_expn_data.insert(hash, expn_id.local_id.as_u32()); + } Ok(()) }, )?; @@ -385,7 +389,8 @@ impl<'sess> OnDiskCache<'sess> { diagnostics_index, interpret_alloc_index, syntax_contexts, - expn_data: expn_ids, + expn_data, + foreign_expn_data, foreign_def_path_hashes, }, )?; @@ -401,6 +406,88 @@ impl<'sess> OnDiskCache<'sess> { }) } + fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> Option { + let mut cache = self.def_path_hash_to_def_id_cache.lock(); + match cache.entry(hash) { + Entry::Occupied(e) => *e.get(), + Entry::Vacant(e) => { + debug!("def_path_hash_to_def_id({:?})", hash); + // Check if the `DefPathHash` corresponds to a definition in the current + // crate + if let Some(def_id) = + tcx.definitions_untracked().local_def_path_hash_to_def_id(hash) + { + let def_id = def_id.to_def_id(); + e.insert(Some(def_id)); + return Some(def_id); + } + // This `raw_def_id` represents the `DefId` of this `DefPathHash` in + // the *previous* compliation session. The `DefPathHash` includes the + // owning crate, so if the corresponding definition still exists in the + // current compilation session, the crate is guaranteed to be the same + // (otherwise, we would compute a different `DefPathHash`). + let raw_def_id = self.get_raw_def_id(&hash)?; + debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id); + // If the owning crate no longer exists, the corresponding definition definitely + // no longer exists. + let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?; + debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate); + // If our `DefPathHash` corresponded to a definition in the local crate, + // we should have either found it in `local_def_path_hash_to_def_id`, or + // never attempted to load it in the first place. Any query result or `DepNode` + // that references a local `DefId` should depend on some HIR-related `DepNode`. + // If a local definition is removed/modified such that its old `DefPathHash` + // no longer has a corresponding definition, that HIR-related `DepNode` should + // end up red. This should prevent us from ever calling + // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any + // queries involved. + debug_assert_ne!(krate, LOCAL_CRATE); + // Try to find a definition in the current session, using the previous `DefIndex` + // as an initial guess. + let opt_def_id = + tcx.cstore_untracked().def_path_hash_to_def_id(krate, raw_def_id.index, hash); + debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id); + e.insert(opt_def_id); + opt_def_id + } + } + } + + fn register_reused_dep_node(&self, tcx: TyCtxt<'sess>, dep_node: &DepNode) { + // For reused dep nodes, we only need to store the mapping if the node + // is one whose query key we can reconstruct from the hash. We use the + // mapping to aid that reconstruction in the next session. While we also + // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`, + // they're already registered during `DefId` encoding. + if dep_node.kind.can_reconstruct_query_key() { + let hash = DefPathHash(dep_node.hash.into()); + + // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to + // `latest_foreign_def_path_hashes`, since the `RawDefId` might have + // changed in the current compilation session (e.g. we've added/removed crates, + // or added/removed definitions before/after the target definition). + if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) { + if !def_id.is_local() { + self.store_foreign_def_id_hash(def_id, hash); + } + } + } + } + + fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) { + // We may overwrite an existing entry, but it will have the same value, + // so it's fine + self.latest_foreign_def_path_hashes + .lock() + .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() }); + } +} + +impl<'sess> OnDiskCache<'sess> { + pub fn as_dyn(&self) -> &dyn rustc_middle::ty::OnDiskCache<'sess> { + self as _ + } + /// Loads a diagnostic emitted during the previous compilation session. pub fn load_diagnostics( &self, @@ -439,44 +526,6 @@ impl<'sess> OnDiskCache<'sess> { cnum_map.get(&stable_crate_id).copied() } - pub(crate) fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) { - // We may overwrite an existing entry, but it will have the same value, - // so it's fine - self.latest_foreign_def_path_hashes - .lock() - .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() }); - } - - /// If the given `dep_node`'s hash still exists in the current compilation, - /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it. - /// - /// Normally, `store_foreign_def_id_hash` can be called directly by - /// the dependency graph when we construct a `DepNode`. However, - /// when we re-use a deserialized `DepNode` from the previous compilation - /// session, we only have the `DefPathHash` available. This method is used - /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written - /// out for usage in the next compilation session. - pub fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) { - // For reused dep nodes, we only need to store the mapping if the node - // is one whose query key we can reconstruct from the hash. We use the - // mapping to aid that reconstruction in the next session. While we also - // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`, - // they're already registered during `DefId` encoding. - if dep_node.kind.can_reconstruct_query_key() { - let hash = DefPathHash(dep_node.hash.into()); - - // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to - // `latest_foreign_def_path_hashes`, since the `RawDefId` might have - // changed in the current compilation session (e.g. we've added/removed crates, - // or added/removed definitions before/after the target definition). - if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) { - if !def_id.is_local() { - self.store_foreign_def_id_hash(def_id, hash); - } - } - } - } - /// Returns the cached query result if there is something in the cache for /// the given `SerializedDepNodeIndex`; otherwise returns `None`. pub fn try_load_query_result<'tcx, T>( @@ -547,6 +596,7 @@ impl<'sess> OnDiskCache<'sess> { alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(), syntax_contexts: &self.syntax_contexts, expn_data: &self.expn_data, + foreign_expn_data: &self.foreign_expn_data, hygiene_context: &self.hygiene_context, }; f(&mut decoder) @@ -558,7 +608,7 @@ impl<'sess> OnDiskCache<'sess> { // maps to None. fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap { tcx.dep_graph.with_ignore(|| { - tcx.all_crate_nums(()) + tcx.crates(()) .iter() .chain(std::iter::once(&LOCAL_CRATE)) .map(|&cnum| { @@ -568,57 +618,6 @@ impl<'sess> OnDiskCache<'sess> { .collect() }) } - - /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation - /// session, if it still exists. This is used during incremental compilation to - /// turn a deserialized `DefPathHash` into its current `DefId`. - pub(crate) fn def_path_hash_to_def_id( - &self, - tcx: TyCtxt<'tcx>, - hash: DefPathHash, - ) -> Option { - let mut cache = self.def_path_hash_to_def_id_cache.lock(); - match cache.entry(hash) { - Entry::Occupied(e) => *e.get(), - Entry::Vacant(e) => { - debug!("def_path_hash_to_def_id({:?})", hash); - // Check if the `DefPathHash` corresponds to a definition in the current - // crate - if let Some(def_id) = tcx.definitions.local_def_path_hash_to_def_id(hash) { - let def_id = def_id.to_def_id(); - e.insert(Some(def_id)); - return Some(def_id); - } - // This `raw_def_id` represents the `DefId` of this `DefPathHash` in - // the *previous* compliation session. The `DefPathHash` includes the - // owning crate, so if the corresponding definition still exists in the - // current compilation session, the crate is guaranteed to be the same - // (otherwise, we would compute a different `DefPathHash`). - let raw_def_id = self.get_raw_def_id(&hash)?; - debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id); - // If the owning crate no longer exists, the corresponding definition definitely - // no longer exists. - let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?; - debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate); - // If our `DefPathHash` corresponded to a definition in the local crate, - // we should have either found it in `local_def_path_hash_to_def_id`, or - // never attempted to load it in the first place. Any query result or `DepNode` - // that references a local `DefId` should depend on some HIR-related `DepNode`. - // If a local definition is removed/modified such that its old `DefPathHash` - // no longer has a corresponding definition, that HIR-related `DepNode` should - // end up red. This should prevent us from ever calling - // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any - // queries involved. - debug_assert_ne!(krate, LOCAL_CRATE); - // Try to find a definition in the current session, using the previous `DefIndex` - // as an initial guess. - let opt_def_id = tcx.cstore.def_path_hash_to_def_id(krate, raw_def_id.index, hash); - debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id); - e.insert(opt_def_id); - opt_def_id - } - } - } } //- DECODING ------------------------------------------------------------------- @@ -635,7 +634,8 @@ pub struct CacheDecoder<'a, 'tcx> { file_index_to_stable_id: &'a FxHashMap, alloc_decoding_session: AllocDecodingSession<'a>, syntax_contexts: &'a FxHashMap, - expn_data: &'a FxHashMap, + expn_data: &'a UnhashMap, + foreign_expn_data: &'a UnhashMap, hygiene_context: &'a HygieneDecodeContext, } @@ -758,7 +758,7 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { } } -crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>); +rustc_middle::implement_ty_decoder!(CacheDecoder<'a, 'tcx>); // This ensures that the `Decodable::decode` specialization for `Vec` is used // when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt @@ -786,23 +786,43 @@ impl<'a, 'tcx> Decodable> for SyntaxContext { impl<'a, 'tcx> Decodable> for ExpnId { fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result { - let expn_data = decoder.expn_data; - rustc_span::hygiene::decode_expn_id( - decoder, - ExpnDataDecodeMode::incr_comp(decoder.hygiene_context), - |this, index| { - // This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing. - // We look up the position of the associated `ExpnData` and decode it. - let pos = expn_data - .get(&index) - .unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data)); - - this.with_position(pos.to_usize(), |decoder| { - let data: ExpnData = decode_tagged(decoder, TAG_EXPN_DATA)?; - Ok(data) - }) - }, - ) + let hash = ExpnHash::decode(decoder)?; + if hash.is_root() { + return Ok(ExpnId::root()); + } + + if let Some(expn_id) = ExpnId::from_hash(hash) { + return Ok(expn_id); + } + + let krate = decoder.cnum_map[&hash.stable_crate_id()]; + + let expn_id = if krate == LOCAL_CRATE { + // We look up the position of the associated `ExpnData` and decode it. + let pos = decoder + .expn_data + .get(&hash) + .unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, decoder.expn_data)); + + let data: ExpnData = decoder + .with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))?; + rustc_span::hygiene::register_local_expn_id(data, hash) + } else { + let index_guess = decoder.foreign_expn_data[&hash]; + decoder.tcx.cstore_untracked().expn_hash_to_expn_id(krate, index_guess, hash) + }; + + #[cfg(debug_assertions)] + { + use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; + let mut hcx = decoder.tcx.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(true, |hcx| expn_id.expn_data().hash_stable(hcx, &mut hasher)); + let local_hash: u64 = hasher.finish(); + debug_assert_eq!(hash.local_hash(), local_hash); + } + + Ok(expn_id) } } @@ -977,12 +997,8 @@ where E: 'a + OpaqueEncoder, { fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> { - rustc_span::hygiene::raw_encode_expn_id( - *self, - s.hygiene_context, - ExpnDataEncodeMode::IncrComp, - s, - ) + s.hygiene_context.schedule_expn_data_for_encoding(*self); + self.expn_hash().encode(s) } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b4191c135b..58c1b57dbb 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -2,9 +2,8 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use super::queries; +use crate::{on_disk_cache, queries, Queries}; use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; -use rustc_middle::ty::query::on_disk_cache; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::HasDepContext; @@ -12,14 +11,16 @@ use rustc_query_system::query::{QueryContext, QueryDescription, QueryJobId, Quer use rustc_data_structures::sync::Lock; use rustc_data_structures::thin_vec::ThinVec; -use rustc_errors::Diagnostic; +use rustc_errors::{Diagnostic, Handler}; use rustc_serialize::opaque; use rustc_span::def_id::LocalDefId; +use std::any::Any; + #[derive(Copy, Clone)] pub struct QueryCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, - pub queries: &'tcx super::Queries<'tcx>, + pub queries: &'tcx Queries<'tcx>, } impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> { @@ -83,14 +84,15 @@ impl QueryContext for QueryCtxt<'tcx> { // Interactions with on_disk_cache fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec { - self.on_disk_cache + self.queries + .on_disk_cache .as_ref() .map(|c| c.load_diagnostics(**self, prev_dep_node_index)) .unwrap_or_default() } fn store_diagnostics(&self, dep_node_index: DepNodeIndex, diagnostics: ThinVec) { - if let Some(c) = self.on_disk_cache.as_ref() { + if let Some(c) = self.queries.on_disk_cache.as_ref() { c.store_diagnostics(dep_node_index, diagnostics) } } @@ -100,7 +102,7 @@ impl QueryContext for QueryCtxt<'tcx> { dep_node_index: DepNodeIndex, diagnostics: ThinVec, ) { - if let Some(c) = self.on_disk_cache.as_ref() { + if let Some(c) = self.queries.on_disk_cache.as_ref() { c.store_diagnostics_for_anon_node(dep_node_index, diagnostics) } } @@ -137,6 +139,27 @@ impl QueryContext for QueryCtxt<'tcx> { } impl<'tcx> QueryCtxt<'tcx> { + #[inline] + pub fn from_tcx(tcx: TyCtxt<'tcx>) -> Self { + let queries = tcx.queries.as_any(); + let queries = unsafe { + let queries = std::mem::transmute::<&dyn Any, &dyn Any>(queries); + let queries = queries.downcast_ref().unwrap(); + let queries = std::mem::transmute::<&Queries<'_>, &Queries<'_>>(queries); + queries + }; + QueryCtxt { tcx, queries } + } + + crate fn on_disk_cache(self) -> Option<&'tcx on_disk_cache::OnDiskCache<'tcx>> { + self.queries.on_disk_cache.as_ref() + } + + #[cfg(parallel_compiler)] + pub unsafe fn deadlock(self, registry: &rustc_rayon_core::Registry) { + rustc_query_system::query::deadlock(self, registry) + } + pub(super) fn encode_query_results( self, encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>, @@ -158,6 +181,15 @@ impl<'tcx> QueryCtxt<'tcx> { Ok(()) } + + pub fn try_print_query_stack( + self, + query: Option>, + handler: &Handler, + num_frames: Option, + ) -> usize { + rustc_query_system::query::print_query_stack(self, query, handler, num_frames) + } } /// This struct stores metadata about each Query. @@ -353,14 +385,14 @@ macro_rules! define_queries { } #[inline] - fn compute(tcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { - let is_local = key.query_crate() == LOCAL_CRATE; - let provider = if is_local { + fn compute_fn(tcx: QueryCtxt<'tcx>, key: &Self::Key) -> + fn(TyCtxt<'tcx>, Self::Key) -> Self::Value + { + if key.query_crate_is_local() { tcx.queries.local_providers.$name } else { tcx.queries.extern_providers.$name - }; - provider(*tcx, key) + } } fn hash_result( @@ -462,6 +494,8 @@ macro_rules! define_queries_struct { local_providers: Box, extern_providers: Box, + pub on_disk_cache: Option>, + $($(#[$attr])* $name: QueryState< crate::dep_graph::DepKind, query_keys::$name<$tcx>, @@ -472,10 +506,12 @@ macro_rules! define_queries_struct { pub fn new( local_providers: Providers, extern_providers: Providers, + on_disk_cache: Option>, ) -> Self { Queries { local_providers: Box::new(local_providers), extern_providers: Box::new(extern_providers), + on_disk_cache, $($name: Default::default()),* } } @@ -501,25 +537,9 @@ macro_rules! define_queries_struct { } impl QueryEngine<'tcx> for Queries<'tcx> { - #[cfg(parallel_compiler)] - unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry) { - let tcx = QueryCtxt { tcx, queries: self }; - rustc_query_system::query::deadlock(tcx, registry) - } - - fn encode_query_results( - &'tcx self, - tcx: TyCtxt<'tcx>, - encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>, - query_result_index: &mut on_disk_cache::EncodedQueryResultIndex, - ) -> opaque::FileEncodeResult { - let tcx = QueryCtxt { tcx, queries: self }; - tcx.encode_query_results(encoder, query_result_index) - } - - fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>) { - let tcx = QueryCtxt { tcx, queries: self }; - tcx.dep_graph.exec_cache_promotions(tcx) + fn as_any(&'tcx self) -> &'tcx dyn std::any::Any { + let this = unsafe { std::mem::transmute::<&Queries<'_>, &Queries<'_>>(self) }; + this as _ } fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool { @@ -527,17 +547,6 @@ macro_rules! define_queries_struct { tcx.dep_graph.try_mark_green(qcx, dep_node).is_some() } - fn try_print_query_stack( - &'tcx self, - tcx: TyCtxt<'tcx>, - query: Option>, - handler: &Handler, - num_frames: Option, - ) -> usize { - let qcx = QueryCtxt { tcx, queries: self }; - rustc_query_system::query::print_query_stack(qcx, query, handler, num_frames) - } - $($(#[$attr])* #[inline(always)] fn $name( diff --git a/compiler/rustc_query_impl/src/stats.rs b/compiler/rustc_query_impl/src/stats.rs index e877034bd7..fa48df3ed4 100644 --- a/compiler/rustc_query_impl/src/stats.rs +++ b/compiler/rustc_query_impl/src/stats.rs @@ -108,7 +108,7 @@ pub fn print_stats(tcx: TyCtxt<'_>) { queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect(); def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap()); eprintln!("\nLocal DefId density:"); - let total = tcx.hir().definitions().def_index_count() as f64; + let total = tcx.resolutions(()).definitions.def_index_count() as f64; for q in def_id_density.iter().rev() { let local = q.local_def_id_keys.unwrap(); eprintln!(" {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total); diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 71e67dfee5..c8a46e974f 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1,7 +1,6 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::profiling::QueryInvocationId; -use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef}; use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; @@ -36,6 +35,12 @@ pub struct DepGraph { /// each task has a `DepNodeIndex` that uniquely identifies it. This unique /// ID is used for self-profiling. virtual_dep_node_index: Lrc, + + /// The cached event id for profiling node interning. This saves us + /// from having to look up the event id every time we intern a node + /// which may incur too much overhead. + /// This will be None if self-profiling is disabled. + node_intern_event_id: Option, } rustc_index::newtype_index! { @@ -130,6 +135,10 @@ impl DepGraph { ); debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE); + let node_intern_event_id = profiler + .get_or_alloc_cached_string("incr_comp_intern_dep_graph_node") + .map(EventId::from_label); + DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, @@ -141,11 +150,16 @@ impl DepGraph { colors: DepNodeColorMap::new(prev_graph_node_count), })), virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), + node_intern_event_id, } } pub fn new_disabled() -> DepGraph { - DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) } + DepGraph { + data: None, + virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), + node_intern_event_id: None, + } } /// Returns `true` if we are actually building the full dep-graph, and `false` otherwise. @@ -244,10 +258,15 @@ impl DepGraph { let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads); let mut hcx = dcx.create_stable_hashing_context(); + let hashing_timer = dcx.profiler().incr_result_hashing(); let current_fingerprint = hash_result(&mut hcx, &result); let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; + // Get timer for profiling `DepNode` interning + let node_intern_timer = self + .node_intern_event_id + .map(|eid| dcx.profiler().generic_activity_with_event_id(eid)); // Intern the new `DepNode`. let (dep_node_index, prev_and_color) = data.current.intern_node( dcx.profiler(), @@ -257,6 +276,9 @@ impl DepGraph { current_fingerprint, print_status, ); + drop(node_intern_timer); + + hashing_timer.finish_with_query_invocation_id(dep_node_index.into()); if let Some((prev_index, color)) = prev_and_color { debug_assert!( diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index f2a6b6df4b..d1e527dff9 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -23,9 +23,6 @@ pub(crate) struct QueryVtable { pub dep_kind: CTX::DepKind, pub eval_always: bool, - // Don't use this method to compute query results, instead use the methods on TyCtxt - pub compute: fn(CTX, K) -> V, - pub hash_result: fn(&mut CTX::StableHashingContext, &V) -> Option, pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V, pub cache_on_disk: fn(CTX, &K, Option<&V>) -> bool, @@ -40,10 +37,6 @@ impl QueryVtable { DepNode::construct(tcx, self.dep_kind, key) } - pub(crate) fn compute(&self, tcx: CTX, key: K) -> V { - (self.compute)(tcx, key) - } - pub(crate) fn hash_result( &self, hcx: &mut CTX::StableHashingContext, @@ -79,7 +72,7 @@ pub trait QueryAccessors: QueryConfig { CTX: 'a; // Don't use this method to compute query results, instead use the methods on TyCtxt - fn compute(tcx: CTX, key: Self::Key) -> Self::Value; + fn compute_fn(tcx: CTX, key: &Self::Key) -> fn(CTX::DepContext, Self::Key) -> Self::Value; fn hash_result( hcx: &mut CTX::StableHashingContext, @@ -115,7 +108,6 @@ where anon: Q::ANON, dep_kind: Q::DEP_KIND, eval_always: Q::EVAL_ALWAYS, - compute: Q::compute, hash_result: Q::hash_result, handle_cycle_error: Q::handle_cycle_error, cache_on_disk: Q::cache_on_disk, diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index c1f9fa39e9..c227c2aaff 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -428,6 +428,7 @@ fn try_execute_query( key: C::Key, lookup: QueryLookup, query: &QueryVtable, + compute: fn(CTX::DepContext, C::Key) -> C::Value, ) -> C::Stored where C: QueryCache, @@ -457,7 +458,7 @@ where // Fast path for when incr. comp. is off. if !dep_graph.is_fully_enabled() { let prof_timer = tcx.dep_context().profiler().query_provider(); - let result = tcx.start_query(job.id, None, || query.compute(tcx, key)); + let result = tcx.start_query(job.id, None, || compute(*tcx.dep_context(), key)); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); return job.complete(result, dep_node_index); @@ -468,8 +469,9 @@ where let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { tcx.start_query(job.id, diagnostics, || { - dep_graph - .with_anon_task(*tcx.dep_context(), query.dep_kind, || query.compute(tcx, key)) + dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || { + compute(*tcx.dep_context(), key) + }) }) }); @@ -501,6 +503,7 @@ where dep_node_index, &dep_node, query, + compute, ), dep_node_index, ) @@ -511,7 +514,7 @@ where } } - let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query); + let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query, compute); dep_graph.read_index(dep_node_index); result } @@ -523,6 +526,7 @@ fn load_from_disk_and_cache_in_memory( dep_node_index: DepNodeIndex, dep_node: &DepNode, query: &QueryVtable, + compute: fn(CTX::DepContext, K) -> V, ) -> V where CTX: QueryContext, @@ -565,7 +569,7 @@ where let prof_timer = tcx.dep_context().profiler().query_provider(); // The dep-graph for this computation is already in-place. - let result = tcx.dep_context().dep_graph().with_ignore(|| query.compute(tcx, key)); + let result = tcx.dep_context().dep_graph().with_ignore(|| compute(*tcx.dep_context(), key)); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -627,6 +631,7 @@ fn force_query_with_job( job: JobOwner<'_, CTX::DepKind, C>, dep_node: DepNode, query: &QueryVtable, + compute: fn(CTX::DepContext, C::Key) -> C::Value, ) -> (C::Stored, DepNodeIndex) where C: QueryCache, @@ -653,17 +658,17 @@ where if query.eval_always { tcx.dep_context().dep_graph().with_eval_always_task( dep_node, - tcx, + *tcx.dep_context(), key, - query.compute, + compute, query.hash_result, ) } else { tcx.dep_context().dep_graph().with_task( dep_node, - tcx, + *tcx.dep_context(), key, - query.compute, + compute, query.hash_result, ) } @@ -690,13 +695,14 @@ fn get_query_impl( key: C::Key, lookup: QueryLookup, query: &QueryVtable, + compute: fn(CTX::DepContext, C::Key) -> C::Value, ) -> C::Stored where CTX: QueryContext, C: QueryCache, C::Key: DepNodeParams, { - try_execute_query(tcx, state, cache, span, key, lookup, query) + try_execute_query(tcx, state, cache, span, key, lookup, query, compute) } /// Ensure that either this query has all green inputs or been executed. @@ -744,8 +750,10 @@ fn force_query_impl( tcx: CTX, state: &QueryState, cache: &QueryCacheStore, + key: C::Key, dep_node: DepNode, query: &QueryVtable, + compute: fn(CTX::DepContext, C::Key) -> C::Value, ) -> bool where C: QueryCache, @@ -754,18 +762,6 @@ where { debug_assert!(!query.anon); - if !>::can_reconstruct_query_key() { - return false; - } - - let key = if let Some(key) = - >::recover(*tcx.dep_context(), &dep_node) - { - key - } else { - return false; - }; - // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. let cached = cache.cache.lookup(cache, &key, |_, index| { @@ -798,7 +794,7 @@ where TryGetJob::JobCompleted(_) => return true, }; - force_query_with_job(tcx, key, job, dep_node, query); + force_query_with_job(tcx, key, job, dep_node, query, compute); true } @@ -828,8 +824,17 @@ where } debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - let value = - get_query_impl(tcx, Q::query_state(tcx), Q::query_cache(tcx), span, key, lookup, query); + let compute = Q::compute_fn(tcx, &key); + let value = get_query_impl( + tcx, + Q::query_state(tcx), + Q::query_cache(tcx), + span, + key, + lookup, + query, + compute, + ); Some(value) } @@ -843,5 +848,26 @@ where return false; } - force_query_impl(tcx, Q::query_state(tcx), Q::query_cache(tcx), *dep_node, &Q::VTABLE) + if !>::can_reconstruct_query_key() { + return false; + } + + let key = if let Some(key) = + >::recover(*tcx.dep_context(), &dep_node) + { + key + } else { + return false; + }; + + let compute = Q::compute_fn(tcx, &key); + force_query_impl( + tcx, + Q::query_state(tcx), + Q::query_cache(tcx), + key, + *dep_node, + &Q::VTABLE, + compute, + ) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e10314a11f..178d727418 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -31,7 +31,7 @@ use rustc_middle::bug; use rustc_middle::hir::exports::Export; use rustc_middle::middle::cstore::CrateStore; use rustc_middle::ty; -use rustc_span::hygiene::{ExpnId, MacroKind}; +use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -42,7 +42,7 @@ use tracing::debug; type Res = def::Res; -impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, ExpnId) { +impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, LocalExpnId) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Module(self.0), @@ -54,7 +54,7 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, ExpnId) { } } -impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) { +impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Res(self.0, false), @@ -68,7 +68,7 @@ impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) { struct IsMacroExport; -impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport) { +impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId, IsMacroExport) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Res(self.0, true), @@ -128,7 +128,7 @@ impl<'a> Resolver<'a> { let (name, parent) = if def_id.index == CRATE_DEF_INDEX { // This is the crate root - (self.cstore().crate_name_untracked(def_id.krate), None) + (self.cstore().crate_name(def_id.krate), None) } else { let def_key = self.cstore().def_key(def_id); let name = def_key @@ -157,8 +157,17 @@ impl<'a> Resolver<'a> { crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { let def_id = match expn_id.expn_data().macro_def_id { Some(def_id) => def_id, - None => return self.ast_transform_scopes.get(&expn_id).unwrap_or(&self.graph_root), + None => { + return expn_id + .as_local() + .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id)) + .unwrap_or(&self.graph_root); + } }; + self.macro_def_scope_from_def_id(def_id) + } + + crate fn macro_def_scope_from_def_id(&mut self, def_id: DefId) -> Module<'a> { if let Some(id) = def_id.as_local() { self.local_macro_def_scopes[&id] } else { @@ -735,7 +744,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { if ptr::eq(parent, self.r.graph_root) { if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if expansion != ExpnId::root() + if expansion != LocalExpnId::ROOT && orig_name.is_some() && entry.extern_crate_item.is_none() { @@ -765,7 +774,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { no_implicit_prelude: parent.no_implicit_prelude || { self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude) }, - ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span) + ..ModuleData::new( + Some(parent), + module_kind, + def_id, + expansion.to_expn_id(), + item.span, + ) }); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.r.module_map.insert(local_def_id, module); @@ -804,7 +819,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { parent, module_kind, parent.nearest_parent_mod, - expansion, + expansion.to_expn_id(), item.span, ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); @@ -879,7 +894,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { parent, module_kind, parent.nearest_parent_mod, - expansion, + expansion.to_expn_id(), item.span, ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); @@ -922,7 +937,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { parent, ModuleKind::Block(block.id), parent.nearest_parent_mod, - expansion, + expansion.to_expn_id(), block.span, ); self.r.block_map.insert(block.id, module); @@ -942,7 +957,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { parent, ModuleKind::Def(kind, def_id, ident.name), def_id, - expansion, + expansion.to_expn_id(), span, ); self.r.define(parent, ident, TypeNS, (module, vis, span, expansion)); @@ -1108,7 +1123,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }) }; - let allow_shadowing = self.parent_scope.expansion == ExpnId::root(); + let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT; if let Some(span) = import_all { let import = macro_use_import(self, span); self.r.potentially_unused_imports.push(import); @@ -1171,7 +1186,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { false } - fn visit_invoc(&mut self, id: NodeId) -> ExpnId { + fn visit_invoc(&mut self, id: NodeId) -> LocalExpnId { let invoc_id = id.placeholder_to_expn_id(); let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope); assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation"); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 17f0c39e39..6f4f1bdaea 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -6,7 +6,7 @@ use rustc_ast_lowering::ResolverAstLowering; use rustc_expand::expand::AstFragment; use rustc_hir::def_id::LocalDefId; use rustc_hir::definitions::*; -use rustc_span::hygiene::ExpnId; +use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use tracing::debug; @@ -14,7 +14,7 @@ use tracing::debug; crate fn collect_definitions( resolver: &mut Resolver<'_>, fragment: &AstFragment, - expansion: ExpnId, + expansion: LocalExpnId, ) { let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion]; fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context }); @@ -25,14 +25,14 @@ struct DefCollector<'a, 'b> { resolver: &'a mut Resolver<'b>, parent_def: LocalDefId, impl_trait_context: ImplTraitContext, - expansion: ExpnId, + expansion: LocalExpnId, } impl<'a, 'b> DefCollector<'a, 'b> { fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId { let parent_def = self.parent_def; debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); - self.resolver.create_def(parent_def, node_id, data, self.expansion, span) + self.resolver.create_def(parent_def, node_id, data, self.expansion.to_expn_id(), span) } fn with_parent(&mut self, parent_def: LocalDefId, f: F) { @@ -285,7 +285,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { item_def, node_id, DefPathData::ImplTrait, - self.expansion, + self.expansion.to_expn_id(), ty.span, ), ImplTraitContext::Existential => { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 03d94f4389..7439cd9a0f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -502,14 +502,14 @@ impl<'a> Resolver<'a> { err } - ResolutionError::SelfInTyParamDefault => { + ResolutionError::SelfInGenericParamDefault => { let mut err = struct_span_err!( self.session, span, E0735, - "type parameters cannot use `Self` in their defaults" + "generic parameters cannot use `Self` in their defaults" ); - err.span_label(span, "`Self` in type parameter default".to_string()); + err.span_label(span, "`Self` in generic parameter default".to_string()); err } ResolutionError::UnreachableLabel { name, definition_span, suggestion } => { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 26858915f4..acfa389fed 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -22,7 +22,7 @@ use rustc_middle::span_bug; use rustc_middle::ty; use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc_session::lint::BuiltinLintDiagnostics; -use rustc_span::hygiene::ExpnId; +use rustc_span::hygiene::LocalExpnId; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{MultiSpan, Span}; @@ -237,8 +237,9 @@ impl<'a> Resolver<'a> { if ns == TypeNS { if ident.name == kw::Crate || ident.name == kw::DollarCrate { let module = self.resolve_crate_root(ident); - let binding = (module, ty::Visibility::Public, module.span, ExpnId::root()) - .to_name_binding(self.arenas); + let binding = + (module, ty::Visibility::Public, module.span, LocalExpnId::ROOT) + .to_name_binding(self.arenas); return Ok(binding); } else if ident.name == kw::Super || ident.name == kw::SelfLower { // FIXME: Implement these with renaming requirements so that e.g. @@ -265,7 +266,7 @@ impl<'a> Resolver<'a> { self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. if let Some(binding) = resolution.binding { - if !restricted_shadowing && binding.expansion != ExpnId::root() { + if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT { if let NameBindingKind::Res(_, true) = binding.kind { self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); } @@ -307,7 +308,7 @@ impl<'a> Resolver<'a> { if let Some(shadowed_glob) = resolution.shadowed_glob { // Forbid expanded shadowing to avoid time travel. if restricted_shadowing - && binding.expansion != ExpnId::root() + && binding.expansion != LocalExpnId::ROOT && binding.res() != shadowed_glob.res() { self.ambiguity_errors.push(AmbiguityError { @@ -521,7 +522,7 @@ impl<'a> Resolver<'a> { if old_glob { (old_binding, binding) } else { (binding, old_binding) }; if glob_binding.res() != nonglob_binding.res() && key.ns == MacroNS - && nonglob_binding.expansion != ExpnId::root() + && nonglob_binding.expansion != LocalExpnId::ROOT { resolution.binding = Some(this.ambiguity( AmbiguityKind::GlobVsExpanded, @@ -1271,7 +1272,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { target: Ident, ) { // Skip if the import was produced by a macro. - if import.parent_scope.expansion != ExpnId::root() { + if import.parent_scope.expansion != LocalExpnId::ROOT { return; } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 03b578d4ad..76979ab50b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1962,6 +1962,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { hir::GenericParamKind::Type { synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. + } | hir::GenericParamKind::Lifetime { + kind: hir::LifetimeParamKind::Elided } ) }) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6d5531d330..7114fd3318 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -11,7 +11,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(bool_to_option)] -#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] #![feature(iter_zip)] @@ -40,7 +39,7 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; @@ -54,8 +53,8 @@ use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; use rustc_span::edition::Edition; -use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency}; -use rustc_span::source_map::Spanned; +use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext, Transparency}; +use rustc_span::source_map::{CachingSourceMapView, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -104,7 +103,7 @@ impl Determinacy { /// but not for late resolution yet. #[derive(Clone, Copy)] enum Scope<'a> { - DeriveHelpers(ExpnId), + DeriveHelpers(LocalExpnId), DeriveHelpersCompat, MacroRules(MacroRulesScopeRef<'a>), CrateRoot, @@ -144,7 +143,7 @@ enum ScopeSet<'a> { #[derive(Clone, Copy, Debug)] pub struct ParentScope<'a> { module: Module<'a>, - expansion: ExpnId, + expansion: LocalExpnId, macro_rules: MacroRulesScopeRef<'a>, derives: &'a [ast::Path], } @@ -155,7 +154,7 @@ impl<'a> ParentScope<'a> { pub fn module(module: Module<'a>, resolver: &Resolver<'a>) -> ParentScope<'a> { ParentScope { module, - expansion: ExpnId::root(), + expansion: LocalExpnId::ROOT, macro_rules: resolver.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty), derives: &[], } @@ -250,7 +249,7 @@ enum ResolutionError<'a> { /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { name: Symbol, is_type: bool }, /// Error E0735: generic parameters with a default cannot use `Self` - SelfInTyParamDefault, + SelfInGenericParamDefault, /// Error E0767: use of unreachable label UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option }, } @@ -336,15 +335,15 @@ impl UsePlacementFinder { if self.span.map_or(true, |span| item.span < span) && !item.span.from_expansion() { + self.span = Some(item.span.shrink_to_lo()); // don't insert between attributes and an item - if item.attrs.is_empty() { - self.span = Some(item.span.shrink_to_lo()); - } else { - // find the first attribute on the item - for attr in &item.attrs { - if self.span.map_or(true, |span| attr.span < span) { - self.span = Some(attr.span.shrink_to_lo()); - } + // find the first attribute on the item + // FIXME: This is broken for active attributes. + for attr in &item.attrs { + if !attr.span.is_dummy() + && self.span.map_or(true, |span| attr.span < span) + { + self.span = Some(attr.span.shrink_to_lo()); } } } @@ -516,7 +515,7 @@ pub struct ModuleData<'a> { populate_on_access: Cell, /// Macro invocations that can expand into items in this module. - unexpanded_invocations: RefCell>, + unexpanded_invocations: RefCell>, /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, @@ -646,7 +645,7 @@ impl<'a> fmt::Debug for ModuleData<'a> { pub struct NameBinding<'a> { kind: NameBindingKind<'a>, ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>, - expansion: ExpnId, + expansion: LocalExpnId, span: Span, vis: ty::Visibility, } @@ -830,7 +829,11 @@ impl<'a> NameBinding<'a> { // in some later round and screw up our previously found resolution. // See more detailed explanation in // https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049 - fn may_appear_after(&self, invoc_parent_expansion: ExpnId, binding: &NameBinding<'_>) -> bool { + fn may_appear_after( + &self, + invoc_parent_expansion: LocalExpnId, + binding: &NameBinding<'_>, + ) -> bool { // self > max(invoc, binding) => !(self <= invoc || self <= binding) // Expansions are partially ordered, so "may appear after" is an inversion of // "certainly appears before or simultaneously" and includes unordered cases. @@ -967,7 +970,7 @@ pub struct Resolver<'a> { dummy_ext_derive: Lrc, non_macro_attrs: [Lrc; 2], local_macro_def_scopes: FxHashMap>, - ast_transform_scopes: FxHashMap>, + ast_transform_scopes: FxHashMap>, unused_macros: FxHashMap, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. @@ -979,18 +982,18 @@ pub struct Resolver<'a> { /// `derive(Copy)` marks items they are applied to so they are treated specially later. /// Derive macros cannot modify the item themselves and have to store the markers in the global /// context, so they attach the markers to derive container IDs using this resolver table. - containers_deriving_copy: FxHashSet, + containers_deriving_copy: FxHashSet, /// Parent scopes in which the macros were invoked. /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere. - invocation_parent_scopes: FxHashMap>, + invocation_parent_scopes: FxHashMap>, /// `macro_rules` scopes *produced* by expanding the macro invocations, /// include all the `macro_rules` items and other invocations generated by them. - output_macro_rules_scopes: FxHashMap>, + output_macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. - helper_attrs: FxHashMap>, + helper_attrs: FxHashMap>, /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute /// with the given `ExpnId`. - derive_data: FxHashMap, + derive_data: FxHashMap, /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, @@ -1019,7 +1022,7 @@ pub struct Resolver<'a> { /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` /// we know what parent node that fragment should be attached to thanks to this table, /// and how the `impl Trait` fragments were introduced. - invocation_parents: FxHashMap, + invocation_parents: FxHashMap, next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, /// Some way to know that we are in a *trait* impl in `visit_assoc_item`. @@ -1150,6 +1153,13 @@ impl ResolverAstLowering for Resolver<'_> { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) } + fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + match def_id.as_local() { + Some(def_id) => self.definitions.def_path_hash(def_id), + None => self.cstore().def_path_hash(def_id), + } + } + /// Adds a definition with a parent definition. fn create_def( &mut self, @@ -1193,6 +1203,32 @@ impl ResolverAstLowering for Resolver<'_> { } } +struct ExpandHasher<'a, 'b> { + source_map: CachingSourceMapView<'a>, + resolver: &'a Resolver<'b>, +} + +impl<'a, 'b> rustc_span::HashStableContext for ExpandHasher<'a, 'b> { + #[inline] + fn hash_spans(&self) -> bool { + true + } + + #[inline] + fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + self.resolver.def_path_hash(def_id) + } + + #[inline] + fn span_data_to_lines_and_cols( + &mut self, + span: &rustc_span::SpanData, + ) -> Option<(Lrc, usize, rustc_span::BytePos, usize, rustc_span::BytePos)> + { + self.source_map.span_data_to_lines_and_cols(span) + } +} + impl<'a> Resolver<'a> { pub fn new( session: &'a Session, @@ -1222,7 +1258,7 @@ impl<'a> Resolver<'a> { let mut module_map = FxHashMap::default(); module_map.insert(root_local_def_id, graph_root); - let definitions = Definitions::new(crate_name, session.local_crate_disambiguator()); + let definitions = Definitions::new(session.local_stable_crate_id()); let root = definitions.get_root_def(); let mut visibilities = FxHashMap::default(); @@ -1236,7 +1272,7 @@ impl<'a> Resolver<'a> { node_id_to_def_id.insert(CRATE_NODE_ID, root); let mut invocation_parents = FxHashMap::default(); - invocation_parents.insert(ExpnId::root(), (root, ImplTraitContext::Existential)); + invocation_parents.insert(LocalExpnId::ROOT, (root, ImplTraitContext::Existential)); let mut extern_prelude: FxHashMap> = session .opts @@ -1310,7 +1346,7 @@ impl<'a> Resolver<'a> { dummy_binding: arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Res(Res::Err, false), ambiguity: None, - expansion: ExpnId::root(), + expansion: LocalExpnId::ROOT, span: DUMMY_SP, vis: ty::Visibility::Public, }), @@ -1360,11 +1396,18 @@ impl<'a> Resolver<'a> { }; let root_parent_scope = ParentScope::module(graph_root, &resolver); - resolver.invocation_parent_scopes.insert(ExpnId::root(), root_parent_scope); + resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); resolver } + fn create_stable_hashing_context(&self) -> ExpandHasher<'_, 'a> { + ExpandHasher { + source_map: CachingSourceMapView::new(self.session.source_map()), + resolver: self, + } + } + pub fn next_node_id(&mut self) -> NodeId { let next = self .next_node_id @@ -1771,20 +1814,18 @@ impl<'a> Resolver<'a> { } scope = match scope { - Scope::DeriveHelpers(expn_id) if expn_id != ExpnId::root() => { + Scope::DeriveHelpers(LocalExpnId::ROOT) => Scope::DeriveHelpersCompat, + Scope::DeriveHelpers(expn_id) => { // Derive helpers are not visible to code generated by bang or derive macros. let expn_data = expn_id.expn_data(); match expn_data.kind { ExpnKind::Root - | ExpnKind::Macro { - kind: MacroKind::Bang | MacroKind::Derive, - name: _, - proc_macro: _, - } => Scope::DeriveHelpersCompat, - _ => Scope::DeriveHelpers(expn_data.parent), + | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => { + Scope::DeriveHelpersCompat + } + _ => Scope::DeriveHelpers(expn_data.parent.expect_local()), } } - Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat, Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules), Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() { MacroRulesScope::Binding(binding) => { @@ -2606,7 +2647,7 @@ impl<'a> Resolver<'a> { if let ForwardGenericParamBanRibKind = all_ribs[rib_index].kind { if record_used { let res_error = if rib_ident.name == kw::SelfUpper { - ResolutionError::SelfInTyParamDefault + ResolutionError::SelfInGenericParamDefault } else { ResolutionError::ForwardDeclaredGenericParam }; @@ -3211,7 +3252,7 @@ impl<'a> Resolver<'a> { }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); Some( - (crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root()) + (crate_root, ty::Visibility::Public, DUMMY_SP, LocalExpnId::ROOT) .to_name_binding(self.arenas), ) } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 3f7db2b696..b2a8aa0cec 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -20,7 +20,7 @@ use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; use rustc_feature::is_builtin_attr_name; use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; -use rustc_hir::def_id::{self, CrateNum}; +use rustc_hir::def_id::{CrateNum, LocalDefId}; use rustc_hir::PrimTy; use rustc_middle::middle::stability; use rustc_middle::ty; @@ -30,7 +30,7 @@ use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::edition::Edition; -use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind}; +use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -62,7 +62,7 @@ pub enum MacroRulesScope<'a> { Binding(&'a MacroRulesBinding<'a>), /// The scope introduced by a macro invocation that can potentially /// create a `macro_rules!` macro definition. - Invocation(ExpnId), + Invocation(LocalExpnId), } /// `macro_rules!` scopes are always kept by reference and inside a cell. @@ -190,7 +190,11 @@ impl<'a> ResolverExpand for Resolver<'a> { }); } - fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment: &AstFragment) { + fn visit_ast_fragment_with_placeholders( + &mut self, + expansion: LocalExpnId, + fragment: &AstFragment, + ) { // Integrate the new AST fragment into all the definition and module structures. // We are inside the `expansion` now, but other parent scope components are still the same. let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; @@ -216,27 +220,24 @@ impl<'a> ResolverExpand for Resolver<'a> { pass: AstPass, features: &[Symbol], parent_module_id: Option, - ) -> ExpnId { - let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable( - ExpnKind::AstPass(pass), - call_site, - self.session.edition(), - features.into(), - None, - ))); - - let parent_scope = if let Some(module_id) = parent_module_id { - let parent_def_id = self.local_def_id(module_id); - self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id.to_def_id()); - self.module_map[&parent_def_id] - } else { - self.definitions.add_parent_module_of_macro_def( - expn_id, - def_id::DefId::local(def_id::CRATE_DEF_INDEX), - ); - self.empty_module - }; + ) -> LocalExpnId { + let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id)); + let expn_id = LocalExpnId::fresh( + ExpnData::allow_unstable( + ExpnKind::AstPass(pass), + call_site, + self.session.edition(), + features.into(), + None, + parent_module.map(LocalDefId::to_def_id), + ), + self.create_stable_hashing_context(), + ); + + let parent_scope = parent_module + .map_or(self.empty_module, |parent_def_id| self.module_map[&parent_def_id]); self.ast_transform_scopes.insert(expn_id, parent_scope); + expn_id } @@ -247,7 +248,7 @@ impl<'a> ResolverExpand for Resolver<'a> { fn resolve_macro_invocation( &mut self, invoc: &Invocation, - eager_expansion_root: ExpnId, + eager_expansion_root: LocalExpnId, force: bool, ) -> Result, Indeterminate> { let invoc_id = invoc.expansion_data.id; @@ -280,7 +281,7 @@ impl<'a> ResolverExpand for Resolver<'a> { // Derives are not included when `invocations` are collected, so we have to add them here. let parent_scope = &ParentScope { derives, ..parent_scope }; let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion(); - let node_id = self.lint_node_id(eager_expansion_root); + let node_id = invoc.expansion_data.lint_node_id; let (ext, res) = self.smart_resolve_macro_path( path, kind, @@ -293,17 +294,20 @@ impl<'a> ResolverExpand for Resolver<'a> { )?; let span = invoc.span(); - invoc_id.set_expn_data(ext.expn_data( - parent_scope.expansion, - span, - fast_print_path(path), - res.opt_def_id(), - )); + invoc_id.set_expn_data( + ext.expn_data( + parent_scope.expansion, + span, + fast_print_path(path), + res.opt_def_id(), + res.opt_def_id().map(|macro_def_id| { + self.macro_def_scope_from_def_id(macro_def_id).nearest_parent_mod + }), + ), + self.create_stable_hashing_context(), + ); if let Res::Def(_, _) = res { - let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod; - self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id); - // Gate macro attributes in `#[derive]` output. if !self.session.features_untracked().macro_attributes_in_derive_output && kind == MacroKind::Attr @@ -325,14 +329,10 @@ impl<'a> ResolverExpand for Resolver<'a> { let expn_data = expn_id.expn_data(); match expn_data.kind { ExpnKind::Root - | ExpnKind::Macro { - name: _, - kind: MacroKind::Bang | MacroKind::Derive, - proc_macro: _, - } => { + | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => { break; } - _ => expn_id = expn_data.parent, + _ => expn_id = expn_data.parent.expect_local(), } } } @@ -348,21 +348,13 @@ impl<'a> ResolverExpand for Resolver<'a> { } } - fn lint_node_id(&self, expn_id: ExpnId) -> NodeId { - // FIXME - make this more precise. This currently returns the NodeId of the - // nearest closing item - we should try to return the closest parent of the ExpnId - self.invocation_parents - .get(&expn_id) - .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]) - } - - fn has_derive_copy(&self, expn_id: ExpnId) -> bool { + fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool { self.containers_deriving_copy.contains(&expn_id) } fn resolve_derives( &mut self, - expn_id: ExpnId, + expn_id: LocalExpnId, force: bool, derive_paths: &dyn Fn() -> DeriveResolutions, ) -> Result<(), Indeterminate> { @@ -380,7 +372,7 @@ impl<'a> ResolverExpand for Resolver<'a> { has_derive_copy: false, }); let parent_scope = self.invocation_parent_scopes[&expn_id]; - for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() { + for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() { if opt_ext.is_none() { *opt_ext = Some( match self.resolve_macro_path( @@ -427,7 +419,7 @@ impl<'a> ResolverExpand for Resolver<'a> { Ok(()) } - fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option { + fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option { self.derive_data.remove(&expn_id).map(|data| data.resolutions) } @@ -435,7 +427,11 @@ impl<'a> ResolverExpand for Resolver<'a> { // Returns true if the path can certainly be resolved in one of three namespaces, // returns false if the path certainly cannot be resolved in any of the three namespaces. // Returns `Indeterminate` if we cannot give a certain answer yet. - fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result { + fn cfg_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + ) -> Result { let span = path.span; let path = &Segment::from_path(path); let parent_scope = self.invocation_parent_scopes[&expn_id]; @@ -718,7 +714,8 @@ impl<'a> Resolver<'a> { let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt)); let ok = |res, span, arenas| { Ok(( - (res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas), + (res, ty::Visibility::Public, span, LocalExpnId::ROOT) + .to_name_binding(arenas), Flags::empty(), )) }; @@ -1100,9 +1097,13 @@ impl<'a> Resolver<'a> { let seg = Segment::from_ident(ident); check_consistency(self, &[seg], ident.span, kind, initial_res, res); if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) { + let node_id = self + .invocation_parents + .get(&parent_scope.expansion) + .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]); self.lint_buffer.buffer_lint_with_diagnostic( LEGACY_DERIVE_HELPERS, - self.lint_node_id(parent_scope.expansion), + node_id, ident.span, "derive helper attribute is used before it is introduced", BuiltinLintDiagnostics::LegacyDeriveHelpers(binding.span), diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 54b6a12158..842f7f9dee 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -142,12 +142,7 @@ impl<'tcx> DumpVisitor<'tcx> { let data = CratePreludeData { crate_id: GlobalCrateId { name: name.into(), - disambiguator: self - .tcx - .sess - .local_crate_disambiguator() - .to_fingerprint() - .as_value(), + disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0), }, crate_root: crate_root.unwrap_or_else(|| "".to_owned()), external_crates: self.save_ctxt.get_external_crates(), diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 297383bfed..0a8a88132e 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -109,9 +109,9 @@ impl<'tcx> SaveContext<'tcx> { // List external crates used by the current crate. pub fn get_external_crates(&self) -> Vec { - let mut result = Vec::with_capacity(self.tcx.crates().len()); + let mut result = Vec::with_capacity(self.tcx.crates(()).len()); - for &n in self.tcx.crates().iter() { + for &n in self.tcx.crates(()).iter() { let span = match self.tcx.extern_crate(n.as_def_id()) { Some(&ExternCrate { span, .. }) => span, None => { @@ -127,7 +127,10 @@ impl<'tcx> SaveContext<'tcx> { num: n.as_u32(), id: GlobalCrateId { name: self.tcx.crate_name(n).to_string(), - disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(), + disambiguator: ( + self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(), + 0, + ), }, }); } @@ -785,7 +788,7 @@ impl<'tcx> SaveContext<'tcx> { let callee = span.source_callee()?; let mac_name = match callee.kind { - ExpnKind::Macro { kind, name, proc_macro: _ } => match kind { + ExpnKind::Macro(kind, name) => match kind { MacroKind::Bang => name, // Ignore attribute macros, their spans are usually mangled diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index b79adb6f7b..4d213207fb 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -1114,6 +1114,15 @@ impl Json { } } + /// If the Json value is an Object, deletes the value associated with the + /// provided key from the Object and returns it. Otherwise, returns None. + pub fn remove_key(&mut self, key: &str) -> Option { + match *self { + Json::Object(ref mut map) => map.remove(key), + _ => None, + } + } + /// Attempts to get a nested Json Object for each key in `keys`. /// If any key is found not to exist, `find_path` will return `None`. /// Otherwise, it will return the Json value associated with the final key. diff --git a/compiler/rustc_serialize/tests/json.rs b/compiler/rustc_serialize/tests/json.rs index e3a823127d..a759fa1bf1 100644 --- a/compiler/rustc_serialize/tests/json.rs +++ b/compiler/rustc_serialize/tests/json.rs @@ -437,7 +437,7 @@ fn test_decode_str() { ("\"\\uAB12\"", "\u{AB12}"), ]; - for &(i, o) in &s { + for (i, o) in s { let v: string::String = json::decode(i).unwrap(); assert_eq!(v, o); } diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 4c72920502..571fd581d3 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -5,7 +5,6 @@ version = "0.0.0" edition = "2018" [dependencies] -bitflags = "1.2.1" getopts = "0.2" rustc_macros = { path = "../rustc_macros" } tracing = "0.1" diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 2b547f8be9..2d7f5f9b32 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::impl_stable_hash_via_hash; use rustc_target::abi::{Align, TargetDataLayout}; -use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple}; +use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TargetWarnings}; use rustc_serialize::json; @@ -31,6 +31,7 @@ use std::collections::btree_map::{ }; use std::collections::{BTreeMap, BTreeSet}; use std::fmt; +use std::hash::Hash; use std::iter::{self, FromIterator}; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; @@ -325,12 +326,11 @@ impl Default for TrimmedDefPaths { /// Use tree-based collections to cheaply get a deterministic `Hash` implementation. /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break -/// dependency tracking for command-line arguments. -#[derive(Clone, Hash, Debug)] +/// dependency tracking for command-line arguments. Also only hash keys, since tracking +/// should only depend on the output types, not the paths they're written to. +#[derive(Clone, Debug, Hash)] pub struct OutputTypes(BTreeMap>); -impl_stable_hash_via_hash!(OutputTypes); - impl OutputTypes { pub fn new(entries: &[(OutputType, Option)]) -> OutputTypes { OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone())))) @@ -677,7 +677,6 @@ impl Default for Options { optimize: OptLevel::No, debuginfo: DebugInfo::None, lint_opts: Vec::new(), - force_warns: Vec::new(), lint_cap: None, describe_lints: false, output_types: OutputTypes(BTreeMap::new()), @@ -805,6 +804,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { let wordsz = sess.target.pointer_width.to_string(); let os = &sess.target.os; let env = &sess.target.env; + let abi = &sess.target.abi; let vendor = &sess.target.vendor; let min_atomic_width = sess.target.min_atomic_width(); let max_atomic_width = sess.target.max_atomic_width(); @@ -814,7 +814,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { }); let mut ret = FxHashSet::default(); - ret.reserve(6); // the minimum number of insertions + ret.reserve(7); // the minimum number of insertions // Target bindings. ret.insert((sym::target_os, Some(Symbol::intern(os)))); for fam in &sess.target.families { @@ -829,11 +829,12 @@ fn default_configuration(sess: &Session) -> CrateConfig { ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str())))); ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz)))); ret.insert((sym::target_env, Some(Symbol::intern(env)))); + ret.insert((sym::target_abi, Some(Symbol::intern(abi)))); ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); if sess.target.has_elf_tls { ret.insert((sym::target_thread_local, None)); } - for &(i, align) in &[ + for (i, align) in [ (8, layout.i8_align.abi), (16, layout.i16_align.abi), (32, layout.i32_align.abi), @@ -899,9 +900,11 @@ pub(super) fn build_target_config( target_override: Option, sysroot: &PathBuf, ) -> Target { - let target_result = - target_override.map_or_else(|| Target::search(&opts.target_triple, sysroot), Ok); - let target = target_result.unwrap_or_else(|e| { + let target_result = target_override.map_or_else( + || Target::search(&opts.target_triple, sysroot), + |t| Ok((t, TargetWarnings::empty())), + ); + let (target, target_warnings) = target_result.unwrap_or_else(|e| { early_error( opts.error_format, &format!( @@ -911,6 +914,9 @@ pub(super) fn build_target_config( ), ) }); + for warning in target_warnings.warning_messages() { + early_warn(opts.error_format, &warning) + } if !matches!(target.pointer_width, 16 | 32 | 64) { early_error( @@ -1095,7 +1101,7 @@ pub fn rustc_short_optgroups() -> Vec { ), opt::multi_s( "", - "force-warns", + "force-warn", "Specifiy lints that should warn even if \ they are allowed somewhere else", "LINT", @@ -1165,20 +1171,20 @@ pub fn get_cmd_lint_options( matches: &getopts::Matches, error_format: ErrorOutputType, debugging_opts: &DebuggingOptions, -) -> (Vec<(String, lint::Level)>, bool, Option, Vec) { +) -> (Vec<(String, lint::Level)>, bool, Option) { let mut lint_opts_with_position = vec![]; let mut describe_lints = false; - for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] { - for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { - let arg_pos = if let lint::Forbid = level { - // HACK: forbid is always specified last, so it can't be overridden. - // FIXME: remove this once is - // fixed and `forbid` works as expected. - usize::MAX - } else { - passed_arg_pos - }; + if !debugging_opts.unstable_options && matches.opt_present("force-warn") { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to enable \ + the flag `--force-warn=lints`", + ); + } + + for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] { + for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { if lint_name == "help" { describe_lints = true; } else { @@ -1199,17 +1205,7 @@ pub fn get_cmd_lint_options( .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap))) }); - if !debugging_opts.unstable_options && matches.opt_present("force-warns") { - early_error( - error_format, - "the `-Z unstable-options` flag must also be passed to enable \ - the flag `--force-warns=lints`", - ); - } - - let force_warns = matches.opt_strs("force-warns"); - - (lint_opts, describe_lints, lint_cap, force_warns) + (lint_opts, describe_lints, lint_cap) } /// Parses the `--color` flag. @@ -1947,7 +1943,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { .unwrap_or_else(|e| early_error(error_format, &e[..])); let mut debugging_opts = DebuggingOptions::build(matches, error_format); - let (lint_opts, describe_lints, lint_cap, force_warns) = + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format, &debugging_opts); check_debug_option_stability(&debugging_opts, error_format, json_rendered); @@ -2121,7 +2117,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { optimize: opt_level, debuginfo, lint_opts, - force_warns, lint_cap, describe_lints, output_types, @@ -2420,8 +2415,8 @@ crate mod dep_tracking { use super::LdImpl; use super::{ CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto, - LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath, - SymbolManglingVersion, TrimmedDefPaths, + LtoCli, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, + SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, }; use crate::lint; use crate::options::WasiExecModel; @@ -2437,13 +2432,18 @@ crate mod dep_tracking { use std::path::PathBuf; pub trait DepTrackingHash { - fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType); + fn hash( + &self, + hasher: &mut DefaultHasher, + error_format: ErrorOutputType, + for_crate_hash: bool, + ); } macro_rules! impl_dep_tracking_hash_via_hash { ($($t:ty),+ $(,)?) => {$( impl DepTrackingHash for $t { - fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) { + fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType, _for_crate_hash: bool) { Hash::hash(self, hasher); } } @@ -2451,11 +2451,16 @@ crate mod dep_tracking { } impl DepTrackingHash for Option { - fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { + fn hash( + &self, + hasher: &mut DefaultHasher, + error_format: ErrorOutputType, + for_crate_hash: bool, + ) { match self { Some(x) => { Hash::hash(&1, hasher); - DepTrackingHash::hash(x, hasher, error_format); + DepTrackingHash::hash(x, hasher, error_format, for_crate_hash); } None => Hash::hash(&0, hasher), } @@ -2485,7 +2490,6 @@ crate mod dep_tracking { LtoCli, DebugInfo, UnstableFeatures, - OutputTypes, NativeLib, NativeLibKind, SanitizerSet, @@ -2499,6 +2503,7 @@ crate mod dep_tracking { SourceFileHashAlgorithm, TrimmedDefPaths, Option, + OutputType, ); impl DepTrackingHash for (T1, T2) @@ -2506,11 +2511,16 @@ crate mod dep_tracking { T1: DepTrackingHash, T2: DepTrackingHash, { - fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { + fn hash( + &self, + hasher: &mut DefaultHasher, + error_format: ErrorOutputType, + for_crate_hash: bool, + ) { Hash::hash(&0, hasher); - DepTrackingHash::hash(&self.0, hasher, error_format); + DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash); Hash::hash(&1, hasher); - DepTrackingHash::hash(&self.1, hasher, error_format); + DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash); } } @@ -2520,22 +2530,49 @@ crate mod dep_tracking { T2: DepTrackingHash, T3: DepTrackingHash, { - fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { + fn hash( + &self, + hasher: &mut DefaultHasher, + error_format: ErrorOutputType, + for_crate_hash: bool, + ) { Hash::hash(&0, hasher); - DepTrackingHash::hash(&self.0, hasher, error_format); + DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash); Hash::hash(&1, hasher); - DepTrackingHash::hash(&self.1, hasher, error_format); + DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash); Hash::hash(&2, hasher); - DepTrackingHash::hash(&self.2, hasher, error_format); + DepTrackingHash::hash(&self.2, hasher, error_format, for_crate_hash); } } impl DepTrackingHash for Vec { - fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) { + fn hash( + &self, + hasher: &mut DefaultHasher, + error_format: ErrorOutputType, + for_crate_hash: bool, + ) { Hash::hash(&self.len(), hasher); for (index, elem) in self.iter().enumerate() { Hash::hash(&index, hasher); - DepTrackingHash::hash(elem, hasher, error_format); + DepTrackingHash::hash(elem, hasher, error_format, for_crate_hash); + } + } + } + + impl DepTrackingHash for OutputTypes { + fn hash( + &self, + hasher: &mut DefaultHasher, + error_format: ErrorOutputType, + for_crate_hash: bool, + ) { + Hash::hash(&self.0.len(), hasher); + for (key, val) in &self.0 { + DepTrackingHash::hash(key, hasher, error_format, for_crate_hash); + if !for_crate_hash { + DepTrackingHash::hash(val, hasher, error_format, for_crate_hash); + } } } } @@ -2545,13 +2582,14 @@ crate mod dep_tracking { sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>, hasher: &mut DefaultHasher, error_format: ErrorOutputType, + for_crate_hash: bool, ) { for (key, sub_hash) in sub_hashes { // Using Hash::hash() instead of DepTrackingHash::hash() is fine for // the keys, as they are just plain strings Hash::hash(&key.len(), hasher); Hash::hash(key, hasher); - sub_hash.hash(hasher, error_format); + sub_hash.hash(hasher, error_format, for_crate_hash); } } } diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 8d00a9a959..9a82ae3fc1 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -24,3 +24,8 @@ pub use session::*; pub mod output; pub use getopts; + +/// Requirements for a `StableHashingContext` to be used in this crate. +/// This is a hack to allow using the `HashStable_Generic` derive macro +/// instead of implementing everything in `rustc_middle`. +pub trait HashStableContext {} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 1946bfd78c..172337aca3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -48,7 +48,11 @@ macro_rules! hash_substruct { ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [TRACKED_NO_CRATE_HASH]) => {{}}; ($opt_name:ident, $opt_expr:expr, $error_format:expr, $for_crate_hash:expr, $hasher:expr, [SUBSTRUCT]) => { use crate::config::dep_tracking::DepTrackingHash; - $opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash($hasher, $error_format); + $opt_expr.dep_tracking_hash($for_crate_hash, $error_format).hash( + $hasher, + $error_format, + $for_crate_hash, + ); }; } @@ -79,7 +83,8 @@ macro_rules! top_level_options { let mut hasher = DefaultHasher::new(); dep_tracking::stable_hash(sub_hashes, &mut hasher, - self.error_format); + self.error_format, + for_crate_hash); $({ hash_substruct!($opt, &self.$opt, @@ -128,9 +133,8 @@ top_level_options!( /// can influence whether overflow checks are done or not. debug_assertions: bool [TRACKED], debuginfo: DebugInfo [TRACKED], - lint_opts: Vec<(String, lint::Level)> [TRACKED], - lint_cap: Option [TRACKED], - force_warns: Vec [TRACKED], + lint_opts: Vec<(String, lint::Level)> [TRACKED_NO_CRATE_HASH], + lint_cap: Option [TRACKED_NO_CRATE_HASH], describe_lints: bool [UNTRACKED], output_types: OutputTypes [TRACKED], search_paths: Vec [UNTRACKED], @@ -236,19 +240,21 @@ macro_rules! options { build_options(matches, $stat, $prefix, $outputname, error_format) } - fn dep_tracking_hash(&self, _for_crate_hash: bool, error_format: ErrorOutputType) -> u64 { + fn dep_tracking_hash(&self, for_crate_hash: bool, error_format: ErrorOutputType) -> u64 { let mut sub_hashes = BTreeMap::new(); $({ hash_opt!($opt, &self.$opt, &mut sub_hashes, - _for_crate_hash, + for_crate_hash, [$dep_tracking_marker]); })* let mut hasher = DefaultHasher::new(); dep_tracking::stable_hash(sub_hashes, &mut hasher, - error_format); + error_format, + for_crate_hash + ); hasher.finish() } } @@ -1077,6 +1083,8 @@ options! { "set the optimization fuel quota for a crate"), function_sections: Option = (None, parse_opt_bool, [TRACKED], "whether each function should go in its own section"), + future_incompat_test: bool = (false, parse_bool, [UNTRACKED], + "forces all lints to be future incompatible, used for internal testing (default: no)"), gcc_ld: Option = (None, parse_gcc_ld, [TRACKED], "implementation of ld used by cc"), graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED], "use dark-themed colors in graphviz output (default: no)"), @@ -1122,6 +1130,8 @@ options! { "link native libraries in the linker invocation (default: yes)"), link_only: bool = (false, parse_bool, [TRACKED], "link the `.rlink` file generated by `-Z no-link` (default: no)"), + llvm_plugins: Vec = (Vec::new(), parse_list, [TRACKED], + "a list LLVM plugins to enable (space separated)"), llvm_time_trace: bool = (false, parse_bool, [UNTRACKED], "generate JSON tracing data file from LLVM data (default: no)"), ls: bool = (false, parse_bool, [UNTRACKED], @@ -1148,7 +1158,7 @@ options! { "the directory the NLL facts are dumped into (default: `nll-facts`)"), no_analysis: bool = (false, parse_no_flag, [UNTRACKED], "parse and expand the source, but run no analysis"), - no_codegen: bool = (false, parse_no_flag, [TRACKED], + no_codegen: bool = (false, parse_no_flag, [TRACKED_NO_CRATE_HASH], "run all passes except codegen; no output"), no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED], "omit DWARF address ranges that give faster lookups"), @@ -1160,8 +1170,6 @@ 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_profiler_runtime: bool = (false, parse_no_flag, [TRACKED], - "prevent automatic injection of the profiler_builtins crate"), normalize_docs: bool = (false, parse_bool, [TRACKED], "normalize associated items in rustdoc when generating documentation"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], @@ -1202,9 +1210,13 @@ options! { "show backtraces for panics during proc-macro execution (default: no)"), profile: bool = (false, parse_bool, [TRACKED], "insert profiling code (default: no)"), + profile_closures: bool = (false, parse_no_flag, [UNTRACKED], + "profile size of closures"), profile_emit: Option = (None, parse_opt_pathbuf, [TRACKED], "file path to emit profiling data at runtime when using 'profile' \ (default based on relative source path)"), + profiler_runtime: Option = (Some(String::from("profiler_builtins")), parse_opt_string, [TRACKED], + "name of the profiler runtime crate to automatically inject, or None to disable"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing (default: no)"), query_stats: bool = (false, parse_bool, [UNTRACKED], @@ -1238,7 +1250,7 @@ options! { "specify the events recorded by the self profiler; for example: `-Z self-profile-events=default,query-keys` all options: none, all, default, generic-activity, query-provider, query-cache-hit - query-blocked, incr-cache-load, query-keys, function-args, args, llvm"), + query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm"), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), show_span: Option = (None, parse_opt_string, [TRACKED], diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 7b7878e9c7..226fde2343 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -133,6 +133,8 @@ pub struct ParseSess { pub reached_eof: Lock, /// Environment variables accessed during the build and their values when they exist. pub env_depinfo: Lock)>>, + /// File paths accessed during the build. + pub file_depinfo: Lock>, /// All the type ascriptions expressions that have had a suggestion for likely path typo. pub type_ascription_path_suggestions: Lock>, /// Whether cfg(version) should treat the current release as incomplete @@ -165,6 +167,7 @@ impl ParseSess { symbol_gallery: SymbolGallery::default(), reached_eof: Lock::new(false), env_depinfo: Default::default(), + file_depinfo: Default::default(), type_ascription_path_suggestions: Default::default(), assume_incomplete_release: false, proc_macro_quoted_spans: Default::default(), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 86b8389a67..86d495c335 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1,7 +1,7 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; -use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath}; +use crate::config::{self, CrateType, OutputType, SwitchWithOptPath}; use crate::filesearch; use crate::lint::{self, LintId}; use crate::parse::ParseSess; @@ -20,9 +20,9 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; -use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported}; -use rustc_lint_defs::FutureBreakage; -pub use rustc_span::crate_disambiguator::CrateDisambiguator; +use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorReported}; +use rustc_macros::HashStable_Generic; +pub use rustc_span::def_id::StableCrateId; use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; use rustc_span::{edition::Edition, RealFileName}; use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; @@ -66,7 +66,7 @@ pub enum CtfeBacktrace { /// New-type wrapper around `usize` for representing limits. Ensures that comparisons against /// limits are consistent throughout the compiler. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct Limit(pub usize); impl Limit { @@ -111,6 +111,20 @@ impl Mul for Limit { } } +#[derive(Clone, Copy, Debug, HashStable_Generic)] +pub struct Limits { + /// The maximum recursion limit for potentially infinitely recursive + /// operations such as auto-dereference and monomorphization. + pub recursion_limit: Limit, + /// The size at which the `large_assignments` lint starts + /// being emitted. + pub move_size_limit: Limit, + /// The maximum length of types during monomorphization. + pub type_length_limit: Limit, + /// The maximum blocks a const expression can evaluate. + pub const_eval_limit: Limit, +} + /// Represents the data associated with a compilation /// session for a single crate. pub struct Session { @@ -133,31 +147,17 @@ pub struct Session { /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: Lock, String)>>, crate_types: OnceCell>, - /// The `crate_disambiguator` is constructed out of all the `-C metadata` - /// arguments passed to the compiler. Its value together with the crate-name - /// forms a unique global identifier for the crate. It is used to allow - /// multiple crates with the same name to coexist. See the + /// The `stable_crate_id` is constructed out of the crate name and all the + /// `-C metadata` arguments passed to the compiler. Its value forms a unique + /// global identifier for the crate. It is used to allow multiple crates + /// with the same name to coexist. See the /// `rustc_codegen_llvm::back::symbol_names` module for more information. - pub crate_disambiguator: OnceCell, + pub stable_crate_id: OnceCell, features: OnceCell, lint_store: OnceCell>, - /// The maximum recursion limit for potentially infinitely recursive - /// operations such as auto-dereference and monomorphization. - pub recursion_limit: OnceCell, - - /// The size at which the `large_assignments` lint starts - /// being emitted. - pub move_size_limit: OnceCell, - - /// The maximum length of types during monomorphization. - pub type_length_limit: OnceCell, - - /// The maximum blocks a const expression can evaluate. - pub const_eval_limit: OnceCell, - incr_comp_session: OneThread>, /// Used for incremental compilation tests. Will only be populated if /// `-Zquery-dep-graph` is specified. @@ -316,27 +316,11 @@ impl Session { if diags.is_empty() { return; } - // If any future-breakage lints were registered, this lint store - // should be available - let lint_store = self.lint_store.get().expect("`lint_store` not initialized!"); - let diags_and_breakage: Vec<(FutureBreakage, Diagnostic)> = diags - .into_iter() - .map(|diag| { - let lint_name = match &diag.code { - Some(DiagnosticId::Lint { name, has_future_breakage: true }) => name, - _ => panic!("Unexpected code in diagnostic {:?}", diag), - }; - let lint = lint_store.name_to_lint(&lint_name); - let future_breakage = - lint.lint.future_incompatible.unwrap().future_breakage.unwrap(); - (future_breakage, diag) - }) - .collect(); - self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage); + self.parse_sess.span_diagnostic.emit_future_breakage_report(diags); } - pub fn local_crate_disambiguator(&self) -> CrateDisambiguator { - self.crate_disambiguator.get().copied().unwrap() + pub fn local_stable_crate_id(&self) -> StableCrateId { + self.stable_crate_id.get().copied().unwrap() } pub fn crate_types(&self) -> &[CrateType] { @@ -347,28 +331,16 @@ impl Session { self.crate_types.set(crate_types).expect("`crate_types` was initialized twice") } - #[inline] - pub fn recursion_limit(&self) -> Limit { - self.recursion_limit.get().copied().unwrap() - } - - #[inline] - pub fn move_size_limit(&self) -> usize { - self.move_size_limit.get().copied().unwrap() - } - - #[inline] - pub fn type_length_limit(&self) -> Limit { - self.type_length_limit.get().copied().unwrap() - } - - pub fn const_eval_limit(&self) -> Limit { - self.const_eval_limit.get().copied().unwrap() - } - pub fn struct_span_warn>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { self.diagnostic().struct_span_warn(sp, msg) } + pub fn struct_span_force_warn>( + &self, + sp: S, + msg: &str, + ) -> DiagnosticBuilder<'_> { + self.diagnostic().struct_span_force_warn(sp, msg) + } pub fn struct_span_warn_with_code>( &self, sp: S, @@ -380,6 +352,9 @@ impl Session { pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { self.diagnostic().struct_warn(msg) } + pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { + self.diagnostic().struct_force_warn(msg) + } pub fn struct_span_allow>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { self.diagnostic().struct_span_allow(sp, msg) } @@ -792,18 +767,6 @@ impl Session { !self.target.is_like_windows && !self.target.is_like_osx } - pub fn must_not_eliminate_frame_pointers(&self) -> bool { - // "mcount" function relies on stack pointer. - // See . - if self.instrument_mcount() { - true - } else if let Some(x) = self.opts.cg.force_frame_pointers { - x - } else { - !self.target.eliminate_frame_pointer - } - } - pub fn must_emit_unwind_tables(&self) -> bool { // This is used to control the emission of the `uwtable` attribute on // LLVM functions. @@ -833,12 +796,12 @@ impl Session { /// Returns the symbol name for the registrar function, /// given the crate `Svh` and the function `DefIndex`. - pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String { - format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex()) + pub fn generate_plugin_registrar_symbol(&self, stable_crate_id: StableCrateId) -> String { + format!("__rustc_plugin_registrar_{:08x}__", stable_crate_id.to_u64()) } - pub fn generate_proc_macro_decls_symbol(&self, disambiguator: CrateDisambiguator) -> String { - format!("__rustc_proc_macro_decls_{}__", disambiguator.to_fingerprint().to_hex()) + pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String { + format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64()) } pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { @@ -1284,9 +1247,12 @@ pub fn build_session( let target_cfg = config::build_target_config(&sopts, target_override, &sysroot); let host_triple = TargetTriple::from_triple(config::host_triple()); - let host = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { + let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { early_error(sopts.error_format, &format!("Error loading host specification: {}", e)) }); + for warning in target_warnings.warning_messages() { + early_warn(sopts.error_format, &warning) + } let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); let hash_kind = sopts.debugging_opts.src_hash_algorithm.unwrap_or_else(|| { @@ -1397,13 +1363,9 @@ pub fn build_session( working_dir, one_time_diagnostics: Default::default(), crate_types: OnceCell::new(), - crate_disambiguator: OnceCell::new(), + stable_crate_id: OnceCell::new(), features: OnceCell::new(), lint_store: OnceCell::new(), - recursion_limit: OnceCell::new(), - move_size_limit: OnceCell::new(), - type_length_limit: OnceCell::new(), - const_eval_limit: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, prof, @@ -1478,25 +1440,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } - // PGO does not work reliably with panic=unwind on Windows. Let's make it - // an error to combine the two for now. It always runs into an assertions - // if LLVM is built with assertions, but without assertions it sometimes - // does not crash and will probably generate a corrupted binary. - // We should only display this error if we're actually going to run PGO. - // If we're just supposed to print out some data, don't show the error (#61002). - if sess.opts.cg.profile_generate.enabled() - && sess.target.is_like_msvc - && sess.panic_strategy() == PanicStrategy::Unwind - && sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) - { - sess.err( - "Profile-guided optimization does not yet work in conjunction \ - with `-Cpanic=unwind` on Windows when targeting MSVC. \ - See issue #61002 \ - for more information.", - ); - } - // Sanitizers can only be used on platforms that we know have working sanitizer codegen. let supported_sanitizers = sess.target.options.supported_sanitizers; let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers; diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 08645990c4..4552f14de8 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -17,6 +17,6 @@ scoped-tls = "1.0" unicode-width = "0.1.4" cfg-if = "0.1.2" tracing = "0.1" -sha-1 = "0.9" +sha1 = { package = "sha-1", version = "0.9" } sha2 = "0.9" -md-5 = "0.9" +md5 = { package = "md-5", version = "0.9" } diff --git a/compiler/rustc_span/src/crate_disambiguator.rs b/compiler/rustc_span/src/crate_disambiguator.rs deleted file mode 100644 index bd7d851671..0000000000 --- a/compiler/rustc_span/src/crate_disambiguator.rs +++ /dev/null @@ -1,35 +0,0 @@ -// This is here because `rustc_session` wants to refer to it, -// and so does `rustc_hir`, but `rustc_hir` shouldn't refer to `rustc_session`. - -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::{base_n, impl_stable_hash_via_hash}; - -use std::fmt; - -/// Hash value constructed out of all the `-C metadata` arguments passed to the -/// compiler. Together with the crate-name forms a unique global identifier for -/// the crate. -#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)] -pub struct CrateDisambiguator(Fingerprint); - -impl CrateDisambiguator { - pub fn to_fingerprint(self) -> Fingerprint { - self.0 - } -} - -impl fmt::Display for CrateDisambiguator { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - let (a, b) = self.0.as_value(); - let as_u128 = a as u128 | ((b as u128) << 64); - f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE)) - } -} - -impl From for CrateDisambiguator { - fn from(fingerprint: Fingerprint) -> CrateDisambiguator { - CrateDisambiguator(fingerprint) - } -} - -impl_stable_hash_via_hash!(CrateDisambiguator); diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 6ee75376ad..64baf94cc0 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -1,7 +1,6 @@ -use crate::crate_disambiguator::CrateDisambiguator; use crate::HashStableContext; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_data_structures::AtomicRef; use rustc_index::vec::Idx; use rustc_macros::HashStable_Generic; @@ -127,26 +126,51 @@ impl Borrow for DefPathHash { } } -/// A [StableCrateId] is a 64 bit hash of `(crate-name, crate-disambiguator)`. It -/// is to [CrateNum] what [DefPathHash] is to [DefId]. It is stable across -/// compilation sessions. +/// A [StableCrateId] is a 64 bit hash of the crate name combined with all +/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to +/// [DefId]. It is stable across compilation sessions. /// /// Since the ID is a hash value there is a (very small) chance that two crates /// end up with the same [StableCrateId]. The compiler will check for such /// collisions when loading crates and abort compilation in order to avoid /// further trouble. -#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Encodable, Decodable)] -pub struct StableCrateId(u64); +#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub struct StableCrateId(pub(crate) u64); impl StableCrateId { + pub fn to_u64(self) -> u64 { + self.0 + } + /// Computes the stable ID for a crate with the given name and - /// disambiguator. - pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> StableCrateId { + /// `-Cmetadata` arguments. + pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec) -> StableCrateId { use std::hash::Hash; + use std::hash::Hasher; let mut hasher = StableHasher::new(); crate_name.hash(&mut hasher); - crate_disambiguator.hash(&mut hasher); + + // We don't want the stable crate id to dependent on the order + // -C metadata arguments, so sort them: + metadata.sort(); + // Every distinct -C metadata value is only incorporated once: + metadata.dedup(); + + hasher.write(b"metadata"); + for s in &metadata { + // Also incorporate the length of a metadata string, so that we generate + // different values for `-Cmetadata=ab -Cmetadata=c` and + // `-Cmetadata=a -Cmetadata=bc` + hasher.write_usize(s.len()); + hasher.write(s.as_bytes()); + } + + // Also incorporate crate type, so that we don't get symbol conflicts when + // linking against a library of the same name, if this is an executable. + hasher.write(if is_exe { b"exe" } else { b"lib" }); + StableCrateId(hasher.finish()) } } @@ -308,13 +332,49 @@ impl Decodable for LocalDefId { rustc_data_structures::define_id_collections!(LocalDefIdMap, LocalDefIdSet, LocalDefId); impl HashStable for DefId { + #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - hcx.hash_def_id(*self, hasher) + self.to_stable_hash_key(hcx).hash_stable(hcx, hasher); + } +} + +impl HashStable for LocalDefId { + #[inline] + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + self.to_stable_hash_key(hcx).hash_stable(hcx, hasher); } } impl HashStable for CrateNum { + #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - hcx.hash_crate_num(*self, hasher) + self.to_stable_hash_key(hcx).hash_stable(hcx, hasher); + } +} + +impl ToStableHashKey for DefId { + type KeyType = DefPathHash; + + #[inline] + fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash { + hcx.def_path_hash(*self) + } +} + +impl ToStableHashKey for LocalDefId { + type KeyType = DefPathHash; + + #[inline] + fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash { + hcx.def_path_hash(self.to_def_id()) + } +} + +impl ToStableHashKey for CrateNum { + type KeyType = DefPathHash; + + #[inline] + fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash { + self.as_def_id().to_stable_hash_key(hcx) } } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 8f3b8cc2d0..e44a2e9659 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -26,19 +26,20 @@ use crate::edition::Edition; use crate::symbol::{kw, sym, Symbol}; -use crate::SESSION_GLOBALS; -use crate::{BytePos, CachingSourceMapView, ExpnIdCache, SourceFile, Span, DUMMY_SP}; +use crate::with_session_globals; +use crate::{HashStableContext, Span, DUMMY_SP}; -use crate::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::unhash::UnhashMap; +use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::fmt; use std::hash::Hash; -use std::thread::LocalKey; use tracing::*; /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks". @@ -58,9 +59,66 @@ pub struct SyntaxContextData { dollar_crate_name: Symbol, } +rustc_index::newtype_index! { + /// A unique ID associated with a macro invocation and expansion. + pub struct ExpnIndex { + ENCODABLE = custom + } +} + /// A unique ID associated with a macro invocation and expansion. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct ExpnId(u32); +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct ExpnId { + pub krate: CrateNum, + pub local_id: ExpnIndex, +} + +impl fmt::Debug for ExpnId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Generate crate_::{{expn_}}. + write!(f, "{:?}::{{{{expn{}}}}}", self.krate, self.local_id.private) + } +} + +rustc_index::newtype_index! { + /// A unique ID associated with a macro invocation and expansion. + pub struct LocalExpnId { + ENCODABLE = custom + DEBUG_FORMAT = "expn{}" + } +} + +/// A unique hash value associated to an expansion. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)] +pub struct ExpnHash(Fingerprint); + +impl ExpnHash { + /// Returns the [StableCrateId] identifying the crate this [ExpnHash] + /// originates from. + #[inline] + pub fn stable_crate_id(self) -> StableCrateId { + StableCrateId(self.0.as_value().0) + } + + /// Returns the crate-local part of the [ExpnHash]. + /// + /// Used for tests. + #[inline] + pub fn local_hash(self) -> u64 { + self.0.as_value().1 + } + + #[inline] + pub fn is_root(self) -> bool { + self.0 == Fingerprint::ZERO + } + + /// Builds a new [ExpnHash] with the given [StableCrateId] and + /// `local_hash`, where `local_hash` must be unique within its crate. + fn new(stable_crate_id: StableCrateId, local_hash: u64) -> ExpnHash { + ExpnHash(Fingerprint::new(stable_crate_id.0, local_hash)) + } +} /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. @@ -82,47 +140,128 @@ pub enum Transparency { Opaque, } -impl ExpnId { - pub fn fresh(expn_data: Option) -> Self { - let has_data = expn_data.is_some(); - let expn_id = HygieneData::with(|data| data.fresh_expn(expn_data)); - if has_data { - update_disambiguator(expn_id); - } - expn_id +impl LocalExpnId { + /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. + pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0); + + pub fn from_raw(idx: ExpnIndex) -> LocalExpnId { + LocalExpnId::from_u32(idx.as_u32()) } - /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. - #[inline] - pub fn root() -> Self { - ExpnId(0) + pub fn as_raw(self) -> ExpnIndex { + ExpnIndex::from_u32(self.as_u32()) } - #[inline] - pub fn as_u32(self) -> u32 { - self.0 + pub fn fresh_empty() -> LocalExpnId { + HygieneData::with(|data| { + let expn_id = data.local_expn_data.push(None); + let _eid = data.local_expn_hashes.push(ExpnHash(Fingerprint::ZERO)); + debug_assert_eq!(expn_id, _eid); + expn_id + }) + } + + pub fn fresh(mut expn_data: ExpnData, ctx: impl HashStableContext) -> LocalExpnId { + debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE); + let expn_hash = update_disambiguator(&mut expn_data, ctx); + HygieneData::with(|data| { + let expn_id = data.local_expn_data.push(Some(expn_data)); + let _eid = data.local_expn_hashes.push(expn_hash); + debug_assert_eq!(expn_id, _eid); + let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id.to_expn_id()); + debug_assert!(_old_id.is_none()); + expn_id + }) } #[inline] - pub fn from_u32(raw: u32) -> ExpnId { - ExpnId(raw) + pub fn expn_hash(self) -> ExpnHash { + HygieneData::with(|data| data.local_expn_hash(self)) } #[inline] pub fn expn_data(self) -> ExpnData { - HygieneData::with(|data| data.expn_data(self).clone()) + HygieneData::with(|data| data.local_expn_data(self).clone()) } #[inline] - pub fn set_expn_data(self, mut expn_data: ExpnData) { + pub fn to_expn_id(self) -> ExpnId { + ExpnId { krate: LOCAL_CRATE, local_id: self.as_raw() } + } + + #[inline] + pub fn set_expn_data(self, mut expn_data: ExpnData, ctx: impl HashStableContext) { + debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE); + let expn_hash = update_disambiguator(&mut expn_data, ctx); HygieneData::with(|data| { - let old_expn_data = &mut data.expn_data[self.0 as usize]; + let old_expn_data = &mut data.local_expn_data[self]; assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID"); - assert_eq!(expn_data.orig_id, None); - expn_data.orig_id = Some(self.as_u32()); *old_expn_data = Some(expn_data); + debug_assert_eq!(data.local_expn_hashes[self].0, Fingerprint::ZERO); + data.local_expn_hashes[self] = expn_hash; + let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, self.to_expn_id()); + debug_assert!(_old_id.is_none()); }); - update_disambiguator(self) + } + + #[inline] + pub fn is_descendant_of(self, ancestor: LocalExpnId) -> bool { + self.to_expn_id().is_descendant_of(ancestor.to_expn_id()) + } + + /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than + /// `expn_id.is_descendant_of(ctxt.outer_expn())`. + #[inline] + pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool { + self.to_expn_id().outer_expn_is_descendant_of(ctxt) + } + + /// Returns span for the macro which originally caused this expansion to happen. + /// + /// Stops backtracing at include! boundary. + #[inline] + pub fn expansion_cause(self) -> Option { + self.to_expn_id().expansion_cause() + } + + #[inline] + #[track_caller] + pub fn parent(self) -> LocalExpnId { + self.expn_data().parent.as_local().unwrap() + } +} + +impl ExpnId { + /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. + /// Invariant: we do not create any ExpnId with local_id == 0 and krate != 0. + pub const fn root() -> ExpnId { + ExpnId { krate: LOCAL_CRATE, local_id: ExpnIndex::from_u32(0) } + } + + #[inline] + pub fn expn_hash(self) -> ExpnHash { + HygieneData::with(|data| data.expn_hash(self)) + } + + #[inline] + pub fn from_hash(hash: ExpnHash) -> Option { + HygieneData::with(|data| data.expn_hash_to_expn_id.get(&hash).copied()) + } + + #[inline] + pub fn as_local(self) -> Option { + if self.krate == LOCAL_CRATE { Some(LocalExpnId::from_raw(self.local_id)) } else { None } + } + + #[inline] + #[track_caller] + pub fn expect_local(self) -> LocalExpnId { + self.as_local().unwrap() + } + + #[inline] + pub fn expn_data(self) -> ExpnData { + HygieneData::with(|data| data.expn_data(self).clone()) } pub fn is_descendant_of(self, ancestor: ExpnId) -> bool { @@ -144,10 +283,7 @@ impl ExpnId { let expn_data = self.expn_data(); // Stop going up the backtrace once include! is encountered if expn_data.is_root() - || matches!( - expn_data.kind, - ExpnKind::Macro { kind: MacroKind::Bang, name: sym::include, proc_macro: _ } - ) + || expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include) { break; } @@ -163,29 +299,40 @@ pub struct HygieneData { /// Each expansion should have an associated expansion data, but sometimes there's a delay /// between creation of an expansion ID and obtaining its data (e.g. macros are collected /// first and then resolved later), so we use an `Option` here. - expn_data: Vec>, + local_expn_data: IndexVec>, + local_expn_hashes: IndexVec, + /// Data and hash information from external crates. We may eventually want to remove these + /// maps, and fetch the information directly from the other crate's metadata like DefIds do. + foreign_expn_data: FxHashMap, + foreign_expn_hashes: FxHashMap, + expn_hash_to_expn_id: UnhashMap, syntax_context_data: Vec, syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>, - /// Maps the `Fingerprint` of an `ExpnData` to the next disambiguator value. + /// Maps the `local_hash` of an `ExpnData` to the next disambiguator value. /// This is used by `update_disambiguator` to keep track of which `ExpnData`s /// would have collisions without a disambiguator. /// The keys of this map are always computed with `ExpnData.disambiguator` /// set to 0. - expn_data_disambiguators: FxHashMap, + expn_data_disambiguators: FxHashMap, } impl HygieneData { crate fn new(edition: Edition) -> Self { - let mut root_data = ExpnData::default( + let root_data = ExpnData::default( ExpnKind::Root, DUMMY_SP, edition, - Some(DefId::local(CRATE_DEF_INDEX)), + Some(CRATE_DEF_ID.to_def_id()), + None, ); - root_data.orig_id = Some(0); HygieneData { - expn_data: vec![Some(root_data)], + local_expn_data: IndexVec::from_elem_n(Some(root_data), 1), + local_expn_hashes: IndexVec::from_elem_n(ExpnHash(Fingerprint::ZERO), 1), + foreign_expn_data: FxHashMap::default(), + foreign_expn_hashes: FxHashMap::default(), + expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root())) + .collect(), syntax_context_data: vec![SyntaxContextData { outer_expn: ExpnId::root(), outer_transparency: Transparency::Opaque, @@ -200,21 +347,32 @@ impl HygieneData { } pub fn with T>(f: F) -> T { - SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut())) + with_session_globals(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut())) } - fn fresh_expn(&mut self, mut expn_data: Option) -> ExpnId { - let raw_id = self.expn_data.len() as u32; - if let Some(data) = expn_data.as_mut() { - assert_eq!(data.orig_id, None); - data.orig_id = Some(raw_id); + #[inline] + fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash { + self.local_expn_hashes[expn_id] + } + + #[inline] + fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash { + match expn_id.as_local() { + Some(expn_id) => self.local_expn_hashes[expn_id], + None => self.foreign_expn_hashes[&expn_id], } - self.expn_data.push(expn_data); - ExpnId(raw_id) + } + + fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData { + self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID") } fn expn_data(&self, expn_id: ExpnId) -> &ExpnData { - self.expn_data[expn_id.0 as usize].as_ref().expect("no expansion data for an expansion ID") + if let Some(expn_id) = expn_id.as_local() { + self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID") + } else { + &self.foreign_expn_data[&expn_id] + } } fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool { @@ -429,17 +587,21 @@ pub fn debug_hygiene_data(verbose: bool) -> String { } else { let mut s = String::from(""); s.push_str("Expansions:"); - data.expn_data.iter().enumerate().for_each(|(id, expn_info)| { - let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID"); + let mut debug_expn_data = |(id, expn_data): (&ExpnId, &ExpnData)| { s.push_str(&format!( - "\n{}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}", + "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}", id, - expn_info.parent, - expn_info.call_site.ctxt(), - expn_info.def_site.ctxt(), - expn_info.kind, - )); + expn_data.parent, + expn_data.call_site.ctxt(), + expn_data.def_site.ctxt(), + expn_data.kind, + )) + }; + data.local_expn_data.iter_enumerated().for_each(|(id, expn_data)| { + let expn_data = expn_data.as_ref().expect("no expansion data for an expansion ID"); + debug_expn_data((&id.to_expn_id(), expn_data)) }); + data.foreign_expn_data.iter().for_each(debug_expn_data); s.push_str("\n\nSyntaxContexts:"); data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| { s.push_str(&format!( @@ -646,7 +808,7 @@ impl SyntaxContext { } pub fn edition(self) -> Edition { - self.outer_expn_data().edition + HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition) } } @@ -662,16 +824,17 @@ impl Span { /// other compiler-generated code to set per-span properties like allowed unstable features. /// The returned span belongs to the created expansion and has the new properties, /// but its location is inherited from the current span. - pub fn fresh_expansion(self, expn_data: ExpnData) -> Span { - self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent) + pub fn fresh_expansion(self, expn_data: ExpnData, ctx: impl HashStableContext) -> Span { + self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent, ctx) } pub fn fresh_expansion_with_transparency( self, expn_data: ExpnData, transparency: Transparency, + ctx: impl HashStableContext, ) -> Span { - let expn_id = ExpnId::fresh(Some(expn_data)); + let expn_id = LocalExpnId::fresh(expn_data, ctx).to_expn_id(); HygieneData::with(|data| { self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency)) }) @@ -684,11 +847,13 @@ impl Span { allow_internal_unstable: Option>, reason: DesugaringKind, edition: Edition, + ctx: impl HashStableContext, ) -> Span { - self.fresh_expansion(ExpnData { + let expn_data = ExpnData { allow_internal_unstable, - ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None) - }) + ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None) + }; + self.fresh_expansion(expn_data, ctx) } } @@ -711,6 +876,17 @@ pub struct ExpnData { /// call_site span would have its own ExpnData, with the call_site /// pointing to the `foo!` invocation. pub call_site: Span, + /// Used to force two `ExpnData`s to have different `Fingerprint`s. + /// Due to macro expansion, it's possible to end up with two `ExpnId`s + /// that have identical `ExpnData`s. This violates the contract of `HashStable` + /// - the two `ExpnId`s are not equal, but their `Fingerprint`s are equal + /// (since the numerical `ExpnId` value is not considered by the `HashStable` + /// implementation). + /// + /// The `disambiguator` field is set by `update_disambiguator` when two distinct + /// `ExpnId`s would end up with the same `Fingerprint`. Since `ExpnData` includes + /// a `krate` field, this value only needs to be unique within a single crate. + disambiguator: u32, // --- The part specific to the macro/desugaring definition. // --- It may be reasonable to share this part between expansions with the same definition, @@ -734,35 +910,10 @@ pub struct ExpnData { /// The `DefId` of the macro being invoked, /// if this `ExpnData` corresponds to a macro invocation pub macro_def_id: Option, - /// The crate that originally created this `ExpnData`. During - /// metadata serialization, we only encode `ExpnData`s that were - /// created locally - when our serialized metadata is decoded, - /// foreign `ExpnId`s will have their `ExpnData` looked up - /// from the crate specified by `Crate - krate: CrateNum, - /// The raw that this `ExpnData` had in its original crate. - /// An `ExpnData` can be created before being assigned an `ExpnId`, - /// so this might be `None` until `set_expn_data` is called - // This is used only for serialization/deserialization purposes: - // two `ExpnData`s that differ only in their `orig_id` should - // be considered equivalent. - #[stable_hasher(ignore)] - orig_id: Option, - - /// Used to force two `ExpnData`s to have different `Fingerprint`s. - /// Due to macro expansion, it's possible to end up with two `ExpnId`s - /// that have identical `ExpnData`s. This violates the contract of `HashStable` - /// - the two `ExpnId`s are not equal, but their `Fingerprint`s are equal - /// (since the numerical `ExpnId` value is not considered by the `HashStable` - /// implementation). - /// - /// The `disambiguator` field is set by `update_disambiguator` when two distinct - /// `ExpnId`s would end up with the same `Fingerprint`. Since `ExpnData` includes - /// a `krate` field, this value only needs to be unique within a single crate. - disambiguator: u32, + /// The normal module (`mod`) in which the expanded macro was defined. + pub parent_module: Option, } -// These would require special handling of `orig_id`. impl !PartialEq for ExpnData {} impl !Hash for ExpnData {} @@ -777,6 +928,7 @@ impl ExpnData { local_inner_macros: bool, edition: Edition, macro_def_id: Option, + parent_module: Option, ) -> ExpnData { ExpnData { kind, @@ -788,8 +940,7 @@ impl ExpnData { local_inner_macros, edition, macro_def_id, - krate: LOCAL_CRATE, - orig_id: None, + parent_module, disambiguator: 0, } } @@ -800,6 +951,7 @@ impl ExpnData { call_site: Span, edition: Edition, macro_def_id: Option, + parent_module: Option, ) -> ExpnData { ExpnData { kind, @@ -811,8 +963,7 @@ impl ExpnData { local_inner_macros: false, edition, macro_def_id, - krate: LOCAL_CRATE, - orig_id: None, + parent_module, disambiguator: 0, } } @@ -823,10 +974,11 @@ impl ExpnData { edition: Edition, allow_internal_unstable: Lrc<[Symbol]>, macro_def_id: Option, + parent_module: Option, ) -> ExpnData { ExpnData { allow_internal_unstable: Some(allow_internal_unstable), - ..ExpnData::default(kind, call_site, edition, macro_def_id) + ..ExpnData::default(kind, call_site, edition, macro_def_id, parent_module) } } @@ -834,6 +986,13 @@ impl ExpnData { pub fn is_root(&self) -> bool { matches!(self.kind, ExpnKind::Root) } + + #[inline] + fn hash_expn(&self, ctx: &mut impl HashStableContext) -> u64 { + let mut hasher = StableHasher::new(); + self.hash_stable(ctx, &mut hasher); + hasher.finish() + } } /// Expansion kind. @@ -842,13 +1001,7 @@ pub enum ExpnKind { /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind. Root, /// Expansion produced by a macro. - Macro { - kind: MacroKind, - name: Symbol, - /// If `true`, this macro is a procedural macro. This - /// flag is only used for diagnostic purposes - proc_macro: bool, - }, + Macro(MacroKind, Symbol), /// Transform done by the compiler on the AST. AstPass(AstPass), /// Desugaring done by the compiler during HIR lowering. @@ -861,7 +1014,7 @@ impl ExpnKind { pub fn descr(&self) -> String { match *self { ExpnKind::Root => kw::PathRoot.to_string(), - ExpnKind::Macro { kind, name, proc_macro: _ } => match kind { + ExpnKind::Macro(macro_kind, name) => match macro_kind { MacroKind::Bang => format!("{}!", name), MacroKind::Attr => format!("#[{}]", name), MacroKind::Derive => format!("#[derive({})]", name), @@ -918,7 +1071,7 @@ pub enum AstPass { } impl AstPass { - fn descr(self) -> &'static str { + pub fn descr(self) -> &'static str { match self { AstPass::StdImports => "standard library imports", AstPass::TestHarness => "test harness", @@ -955,7 +1108,7 @@ pub enum ForLoopLoc { impl DesugaringKind { /// The description wording should combine well with "desugaring of {}". - fn descr(self) -> &'static str { + pub fn descr(self) -> &'static str { match self { DesugaringKind::CondTemporary => "`if` or `while` condition", DesugaringKind::Async => "`async` block or function", @@ -986,16 +1139,18 @@ pub struct HygieneEncodeContext { } impl HygieneEncodeContext { - pub fn encode< - T, - R, - F: FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>, - G: FnMut(&mut T, u32, &ExpnData) -> Result<(), R>, - >( + /// Record the fact that we need to serialize the corresponding `ExpnData`. + pub fn schedule_expn_data_for_encoding(&self, expn: ExpnId) { + if !self.serialized_expns.lock().contains(&expn) { + self.latest_expns.lock().insert(expn); + } + } + + pub fn encode( &self, encoder: &mut T, - mut encode_ctxt: F, - mut encode_expn: G, + mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>, + mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash) -> Result<(), R>, ) -> Result<(), R> { // When we serialize a `SyntaxContextData`, we may end up serializing // a `SyntaxContext` that we haven't seen before @@ -1013,7 +1168,7 @@ impl HygieneEncodeContext { // It's fine to iterate over a HashMap, because the serialization // of the table that we insert data into doesn't depend on insertion // order - for_all_ctxts_in(latest_ctxts.into_iter(), |(index, ctxt, data)| { + for_all_ctxts_in(latest_ctxts.into_iter(), |index, ctxt, data| { if self.serialized_ctxts.lock().insert(ctxt) { encode_ctxt(encoder, index, data)?; } @@ -1022,9 +1177,9 @@ impl HygieneEncodeContext { let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) }; - for_all_expns_in(latest_expns.into_iter(), |index, expn, data| { + for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| { if self.serialized_expns.lock().insert(expn) { - encode_expn(encoder, index, data)?; + encode_expn(encoder, expn, data, hash)?; } Ok(()) })?; @@ -1043,73 +1198,70 @@ pub struct HygieneDecodeContext { // so that multiple occurrences of the same serialized id are decoded to the same // `SyntaxContext` remapped_ctxts: Lock>>, - // The same as `remapepd_ctxts`, but for `ExpnId`s - remapped_expns: Lock>>, } -pub fn decode_expn_id< - 'a, - D: Decoder, - F: FnOnce(&mut D, u32) -> Result, - G: FnOnce(CrateNum) -> &'a HygieneDecodeContext, ->( - d: &mut D, - mode: ExpnDataDecodeMode<'a, G>, - decode_data: F, -) -> Result { - let index = u32::decode(d)?; - let context = match mode { - ExpnDataDecodeMode::IncrComp(context) => context, - ExpnDataDecodeMode::Metadata(get_context) => { - let krate = CrateNum::decode(d)?; - get_context(krate) - } - }; +/// Register an expansion which has been decoded from the on-disk-cache for the local crate. +pub fn register_local_expn_id(data: ExpnData, hash: ExpnHash) -> ExpnId { + HygieneData::with(|hygiene_data| { + let expn_id = hygiene_data.local_expn_data.next_index(); + hygiene_data.local_expn_data.push(Some(data)); + let _eid = hygiene_data.local_expn_hashes.push(hash); + debug_assert_eq!(expn_id, _eid); + + let expn_id = expn_id.to_expn_id(); - // Do this after decoding, so that we decode a `CrateNum` - // if necessary - if index == ExpnId::root().as_u32() { + let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); + debug_assert!(_old_id.is_none()); + expn_id + }) +} + +/// Register an expansion which has been decoded from the metadata of a foreign crate. +pub fn register_expn_id( + krate: CrateNum, + local_id: ExpnIndex, + data: ExpnData, + hash: ExpnHash, +) -> ExpnId { + let expn_id = ExpnId { krate, local_id }; + HygieneData::with(|hygiene_data| { + let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data); + debug_assert!(_old_data.is_none()); + let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash); + debug_assert!(_old_hash.is_none()); + let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); + debug_assert!(_old_id.is_none()); + }); + expn_id +} + +/// Decode an expansion from the metadata of a foreign crate. +pub fn decode_expn_id( + krate: CrateNum, + index: u32, + decode_data: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash), +) -> ExpnId { + if index == 0 { debug!("decode_expn_id: deserialized root"); - return Ok(ExpnId::root()); + return ExpnId::root(); } - let outer_expns = &context.remapped_expns; + let index = ExpnIndex::from_u32(index); - // Ensure that the lock() temporary is dropped early - { - if let Some(expn_id) = outer_expns.lock().get(index as usize).copied().flatten() { - return Ok(expn_id); - } + // This function is used to decode metadata, so it cannot decode information about LOCAL_CRATE. + debug_assert_ne!(krate, LOCAL_CRATE); + let expn_id = ExpnId { krate, local_id: index }; + + // Fast path if the expansion has already been decoded. + if HygieneData::with(|hygiene_data| hygiene_data.foreign_expn_data.contains_key(&expn_id)) { + return expn_id; } // Don't decode the data inside `HygieneData::with`, since we need to recursively decode // other ExpnIds - let mut expn_data = decode_data(d, index)?; - - let expn_id = HygieneData::with(|hygiene_data| { - let expn_id = ExpnId(hygiene_data.expn_data.len() as u32); - - // If we just deserialized an `ExpnData` owned by - // the local crate, its `orig_id` will be stale, - // so we need to update it to its own value. - // This only happens when we deserialize the incremental cache, - // since a crate will never decode its own metadata. - if expn_data.krate == LOCAL_CRATE { - expn_data.orig_id = Some(expn_id.0); - } - - hygiene_data.expn_data.push(Some(expn_data)); + let (expn_data, hash) = decode_data(expn_id); - let mut expns = outer_expns.lock(); - let new_len = index as usize + 1; - if expns.len() < new_len { - expns.resize(new_len, None); - } - expns[index as usize] = Some(expn_id); - drop(expns); - expn_id - }); - Ok(expn_id) + register_expn_id(krate, index, expn_data, hash) } // Decodes `SyntaxContext`, using the provided `HygieneDecodeContext` @@ -1185,7 +1337,7 @@ pub fn decode_syntax_context< Ok(new_ctxt) } -fn for_all_ctxts_in Result<(), E>>( +fn for_all_ctxts_in Result<(), E>>( ctxts: impl Iterator, mut f: F, ) -> Result<(), E> { @@ -1193,30 +1345,44 @@ fn for_all_ctxts_in Res ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect() }); for (ctxt, data) in all_data.into_iter() { - f((ctxt.0, ctxt, &data))?; + f(ctxt.0, ctxt, &data)?; } Ok(()) } -fn for_all_expns_in Result<(), E>>( +fn for_all_expns_in( expns: impl Iterator, - mut f: F, + mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>, ) -> Result<(), E> { let all_data: Vec<_> = HygieneData::with(|data| { - expns.map(|expn| (expn, data.expn_data[expn.0 as usize].clone())).collect() + expns + .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone())) + .collect() }); - for (expn, data) in all_data.into_iter() { - f(expn.0, expn, &data.unwrap_or_else(|| panic!("Missing data for {:?}", expn)))?; + for (expn, data, hash) in all_data.into_iter() { + f(expn, &data, hash)?; } Ok(()) } +impl Encodable for LocalExpnId { + fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.to_expn_id().encode(e) + } +} + impl Encodable for ExpnId { default fn encode(&self, _: &mut E) -> Result<(), E::Error> { panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::()); } } +impl Decodable for LocalExpnId { + fn decode(d: &mut D) -> Result { + ExpnId::decode(d).map(ExpnId::expect_local) + } +} + impl Decodable for ExpnId { default fn decode(_: &mut D) -> Result { panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::()); @@ -1234,58 +1400,6 @@ pub fn raw_encode_syntax_context( ctxt.0.encode(e) } -pub fn raw_encode_expn_id( - expn: ExpnId, - context: &HygieneEncodeContext, - mode: ExpnDataEncodeMode, - e: &mut E, -) -> Result<(), E::Error> { - // Record the fact that we need to serialize the corresponding - // `ExpnData` - let needs_data = || { - if !context.serialized_expns.lock().contains(&expn) { - context.latest_expns.lock().insert(expn); - } - }; - - match mode { - ExpnDataEncodeMode::IncrComp => { - // Always serialize the `ExpnData` in incr comp mode - needs_data(); - expn.0.encode(e) - } - ExpnDataEncodeMode::Metadata => { - let data = expn.expn_data(); - // We only need to serialize the ExpnData - // if it comes from this crate. - // We currently don't serialize any hygiene information data for - // proc-macro crates: see the `SpecializedEncoder` impl - // for crate metadata. - if data.krate == LOCAL_CRATE { - needs_data(); - } - data.orig_id.expect("Missing orig_id").encode(e)?; - data.krate.encode(e) - } - } -} - -pub enum ExpnDataEncodeMode { - IncrComp, - Metadata, -} - -pub enum ExpnDataDecodeMode<'a, F: FnOnce(CrateNum) -> &'a HygieneDecodeContext> { - IncrComp(&'a HygieneDecodeContext), - Metadata(F), -} - -impl<'a> ExpnDataDecodeMode<'a, Box &'a HygieneDecodeContext>> { - pub fn incr_comp(ctxt: &'a HygieneDecodeContext) -> Self { - ExpnDataDecodeMode::IncrComp(ctxt) - } -} - impl Encodable for SyntaxContext { default fn encode(&self, _: &mut E) -> Result<(), E::Error> { panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::()); @@ -1305,106 +1419,71 @@ impl Decodable for SyntaxContext { /// This method is called only when an `ExpnData` is first associated /// with an `ExpnId` (when the `ExpnId` is initially constructed, or via /// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized -/// from another crate's metadata - since `ExpnData` includes a `krate` field, +/// from another crate's metadata - since `ExpnHash` includes the stable crate id, /// collisions are only possible between `ExpnId`s within the same crate. -fn update_disambiguator(expn_id: ExpnId) { - /// A `HashStableContext` which hashes the raw id values for `DefId` - /// and `CrateNum`, rather than using their computed stable hash. - /// - /// This allows us to use the `HashStable` implementation on `ExpnId` - /// early on in compilation, before we've constructed a `TyCtxt`. - /// The `Fingerprint`s created by this context are not 'stable', since - /// the raw `CrateNum` and `DefId` values for an item may change between - /// sessions due to unrelated changes (e.g. adding/removing an different item). - /// - /// However, this is fine for our purposes - we only need to detect - /// when two `ExpnData`s have the same `Fingerprint`. Since the hashes produced - /// by this context still obey the properties of `HashStable`, we have - /// that - /// `hash_stable(expn1, DummyHashStableContext) == hash_stable(expn2, DummyHashStableContext)` - /// iff `hash_stable(expn1, StableHashingContext) == hash_stable(expn2, StableHasingContext)`. - /// - /// This is sufficient for determining when we need to update the disambiguator. - struct DummyHashStableContext<'a> { - caching_source_map: CachingSourceMapView<'a>, - } - - impl<'a> crate::HashStableContext for DummyHashStableContext<'a> { - fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) { - def_id.krate.as_u32().hash_stable(self, hasher); - def_id.index.as_u32().hash_stable(self, hasher); - } - - fn expn_id_cache() -> &'static LocalKey { - // This cache is only used by `DummyHashStableContext`, - // so we won't pollute the cache values of the normal `StableHashingContext` - thread_local! { - static CACHE: ExpnIdCache = const { ExpnIdCache::new(Vec::new()) }; - } - - &CACHE - } - - fn hash_crate_num(&mut self, krate: CrateNum, hasher: &mut StableHasher) { - krate.as_u32().hash_stable(self, hasher); - } - fn hash_spans(&self) -> bool { - true - } - fn span_data_to_lines_and_cols( - &mut self, - span: &crate::SpanData, - ) -> Option<(Lrc, usize, BytePos, usize, BytePos)> { - self.caching_source_map.span_data_to_lines_and_cols(span) - } - } - - let source_map = SESSION_GLOBALS - .with(|session_globals| session_globals.source_map.borrow().as_ref().unwrap().clone()); - - let mut ctx = - DummyHashStableContext { caching_source_map: CachingSourceMapView::new(&source_map) }; - - let mut hasher = StableHasher::new(); - - let expn_data = expn_id.expn_data(); +fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash { // This disambiguator should not have been set yet. assert_eq!( expn_data.disambiguator, 0, "Already set disambiguator for ExpnData: {:?}", expn_data ); - expn_data.hash_stable(&mut ctx, &mut hasher); - let first_hash = hasher.finish(); + let mut expn_hash = expn_data.hash_expn(&mut ctx); - let modified = HygieneData::with(|data| { + let disambiguator = HygieneData::with(|data| { // If this is the first ExpnData with a given hash, then keep our // disambiguator at 0 (the default u32 value) - let disambig = data.expn_data_disambiguators.entry(first_hash).or_default(); - data.expn_data[expn_id.0 as usize].as_mut().unwrap().disambiguator = *disambig; + let disambig = data.expn_data_disambiguators.entry(expn_hash).or_default(); + let disambiguator = *disambig; *disambig += 1; - - *disambig != 1 + disambiguator }); - if modified { - debug!("Set disambiguator for {:?} (hash {:?})", expn_id, first_hash); - debug!("expn_data = {:?}", expn_id.expn_data()); + if disambiguator != 0 { + debug!("Set disambiguator for expn_data={:?} expn_hash={:?}", expn_data, expn_hash); + + expn_data.disambiguator = disambiguator; + expn_hash = expn_data.hash_expn(&mut ctx); // Verify that the new disambiguator makes the hash unique #[cfg(debug_assertions)] - { - hasher = StableHasher::new(); - expn_id.expn_data().hash_stable(&mut ctx, &mut hasher); - let new_hash: Fingerprint = hasher.finish(); - - HygieneData::with(|data| { - assert_eq!( - data.expn_data_disambiguators.get(&new_hash), - None, - "Hash collision after disambiguator update!", - ); - }); + HygieneData::with(|data| { + assert_eq!( + data.expn_data_disambiguators.get(&expn_hash), + None, + "Hash collision after disambiguator update!", + ); + }); + } + + ExpnHash::new(ctx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), expn_hash) +} + +impl HashStable for SyntaxContext { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + const TAG_EXPANSION: u8 = 0; + const TAG_NO_EXPANSION: u8 = 1; + + if *self == SyntaxContext::root() { + TAG_NO_EXPANSION.hash_stable(ctx, hasher); + } else { + TAG_EXPANSION.hash_stable(ctx, hasher); + let (expn_id, transparency) = self.outer_mark(); + expn_id.hash_stable(ctx, hasher); + transparency.hash_stable(ctx, hasher); + } + } +} + +impl HashStable for ExpnId { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + let hash = if *self == ExpnId::root() { + // Avoid fetching TLS storage for a trivial often-used value. + Fingerprint::ZERO + } else { + self.expn_hash().0 }; + + hash.hash_stable(ctx, hasher); } } diff --git a/compiler/rustc_span/src/lev_distance/tests.rs b/compiler/rustc_span/src/lev_distance/tests.rs index 90e20afc8f..11822e9ef9 100644 --- a/compiler/rustc_span/src/lev_distance/tests.rs +++ b/compiler/rustc_span/src/lev_distance/tests.rs @@ -21,8 +21,8 @@ fn test_lev_distance() { #[test] fn test_find_best_match_for_name() { - use crate::with_default_session_globals; - with_default_session_globals(|| { + use crate::create_default_session_globals_then; + create_default_session_globals_then(|| { let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")]; assert_eq!( find_best_match_for_name(&input, Symbol::intern("aaaa"), None), diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9cf68cbd23..1c95cc9120 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -36,36 +36,31 @@ use source_map::SourceMap; pub mod edition; use edition::Edition; pub mod hygiene; -pub use hygiene::SyntaxContext; use hygiene::Transparency; -pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind}; +pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind}; +pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext}; pub mod def_id; -use def_id::{CrateNum, DefId, LOCAL_CRATE}; +use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE}; pub mod lev_distance; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; -pub mod crate_disambiguator; - pub mod symbol; pub use symbol::{sym, Symbol}; mod analyze_source_file; pub mod fatal_error; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use std::borrow::Cow; -use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; use std::hash::Hash; use std::ops::{Add, Range, Sub}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::thread::LocalKey; use md5::Md5; use sha1::Digest; @@ -99,19 +94,65 @@ impl SessionGlobals { } } -pub fn with_session_globals(edition: Edition, f: impl FnOnce() -> R) -> R { +#[inline] +pub fn create_session_globals_then(edition: Edition, f: impl FnOnce() -> R) -> R { + assert!( + !SESSION_GLOBALS.is_set(), + "SESSION_GLOBALS should never be overwritten! \ + Use another thread if you need another SessionGlobals" + ); let session_globals = SessionGlobals::new(edition); SESSION_GLOBALS.set(&session_globals, f) } -pub fn with_default_session_globals(f: impl FnOnce() -> R) -> R { - with_session_globals(edition::DEFAULT_EDITION, f) +#[inline] +pub fn set_session_globals_then(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R { + assert!( + !SESSION_GLOBALS.is_set(), + "SESSION_GLOBALS should never be overwritten! \ + Use another thread if you need another SessionGlobals" + ); + SESSION_GLOBALS.set(session_globals, f) +} + +#[inline] +pub fn create_default_session_if_not_set_then(f: F) -> R +where + F: FnOnce(&SessionGlobals) -> R, +{ + create_session_if_not_set_then(edition::DEFAULT_EDITION, f) +} + +#[inline] +pub fn create_session_if_not_set_then(edition: Edition, f: F) -> R +where + F: FnOnce(&SessionGlobals) -> R, +{ + if !SESSION_GLOBALS.is_set() { + let session_globals = SessionGlobals::new(edition); + SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f)) + } else { + SESSION_GLOBALS.with(f) + } +} + +#[inline] +pub fn with_session_globals(f: F) -> R +where + F: FnOnce(&SessionGlobals) -> R, +{ + SESSION_GLOBALS.with(f) +} + +#[inline] +pub fn create_default_session_globals_then(f: impl FnOnce() -> R) -> R { + create_session_globals_then(edition::DEFAULT_EDITION, f) } // If this ever becomes non thread-local, `decode_syntax_context` // and `decode_expn_id` will need to be updated to handle concurrent // deserialization. -scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals); +scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals); // FIXME: We should use this enum or something like it to get rid of the // use of magic `/rust/1.x/...` paths across the board. @@ -476,10 +517,7 @@ impl Span { /// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(self) -> bool { - matches!( - self.ctxt().outer_expn_data().kind, - ExpnKind::Macro { kind: MacroKind::Derive, name: _, proc_macro: _ } - ) + matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) } #[inline] @@ -857,13 +895,13 @@ impl Decodable for Span { /// the `SourceMap` provided to this function. If that is not available, /// we fall back to printing the raw `Span` field values. pub fn with_source_map T>(source_map: Lrc, f: F) -> T { - SESSION_GLOBALS.with(|session_globals| { + with_session_globals(|session_globals| { *session_globals.source_map.borrow_mut() = Some(source_map); }); struct ClearSourceMap; impl Drop for ClearSourceMap { fn drop(&mut self) { - SESSION_GLOBALS.with(|session_globals| { + with_session_globals(|session_globals| { session_globals.source_map.borrow_mut().take(); }); } @@ -882,7 +920,7 @@ pub fn debug_with_source_map( } pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { - SESSION_GLOBALS.with(|session_globals| { + with_session_globals(|session_globals| { if let Some(source_map) = &*session_globals.source_map.borrow() { debug_with_source_map(span, f, source_map) } else { @@ -1508,13 +1546,11 @@ 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 { - if self.lines.is_empty() { - return None; + match self.lines.binary_search(&pos) { + Ok(idx) => Some(idx), + Err(0) => None, + Err(idx) => Some(idx - 1), } - - let line_index = lookup_line(&self.lines[..], pos); - assert!(line_index < self.lines.len() as isize); - if line_index >= 0 { Some(line_index as usize) } else { None } } pub fn line_bounds(&self, line_index: usize) -> Range { @@ -1913,28 +1949,12 @@ impl InnerSpan { } } -// Given a slice of line start positions and a position, returns the index of -// the line the position is on. Returns -1 if the position is located before -// the first line. -fn lookup_line(lines: &[BytePos], pos: BytePos) -> isize { - match lines.binary_search(&pos) { - Ok(line) => line as isize, - Err(line) => line as isize - 1, - } -} - /// Requirements for a `StableHashingContext` to be used in this crate. /// /// This is a hack to allow using the [`HashStable_Generic`] derive macro /// instead of implementing everything in rustc_middle. pub trait HashStableContext { - fn hash_def_id(&mut self, _: DefId, hasher: &mut StableHasher); - /// Obtains a cache for storing the `Fingerprint` of an `ExpnId`. - /// This method allows us to have multiple `HashStableContext` implementations - /// that hash things in a different way, without the results of one polluting - /// the cache of the other. - fn expn_id_cache() -> &'static LocalKey; - fn hash_crate_num(&mut self, _: CrateNum, hasher: &mut StableHasher); + fn def_path_hash(&self, def_id: DefId) -> DefPathHash; fn hash_spans(&self) -> bool; fn span_data_to_lines_and_cols( &mut self, @@ -2008,60 +2028,3 @@ where Hash::hash(&len, hasher); } } - -impl HashStable for SyntaxContext { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - const TAG_EXPANSION: u8 = 0; - const TAG_NO_EXPANSION: u8 = 1; - - if *self == SyntaxContext::root() { - TAG_NO_EXPANSION.hash_stable(ctx, hasher); - } else { - TAG_EXPANSION.hash_stable(ctx, hasher); - let (expn_id, transparency) = self.outer_mark(); - expn_id.hash_stable(ctx, hasher); - transparency.hash_stable(ctx, hasher); - } - } -} - -pub type ExpnIdCache = RefCell>>; - -impl HashStable for ExpnId { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - const TAG_ROOT: u8 = 0; - const TAG_NOT_ROOT: u8 = 1; - - if *self == ExpnId::root() { - TAG_ROOT.hash_stable(ctx, hasher); - return; - } - - // Since the same expansion context is usually referenced many - // times, we cache a stable hash of it and hash that instead of - // recursing every time. - let index = self.as_u32() as usize; - let res = CTX::expn_id_cache().with(|cache| cache.borrow().get(index).copied().flatten()); - - if let Some(res) = res { - res.hash_stable(ctx, hasher); - } else { - let new_len = index + 1; - - let mut sub_hasher = StableHasher::new(); - TAG_NOT_ROOT.hash_stable(ctx, &mut sub_hasher); - self.expn_data().hash_stable(ctx, &mut sub_hasher); - let sub_hash: Fingerprint = sub_hasher.finish(); - - CTX::expn_id_cache().with(|cache| { - let mut cache = cache.borrow_mut(); - if cache.len() < new_len { - cache.resize(new_len, None); - } - let prev = cache[index].replace(sub_hash); - assert_eq!(prev, None, "Cache slot was filled"); - }); - sub_hash.hash_stable(ctx, hasher); - } - } -} diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 32031ac707..77a3ad931d 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -461,9 +461,13 @@ impl SourceMap { } pub fn is_multiline(&self, sp: Span) -> bool { - let lo = self.lookup_char_pos(sp.lo()); - let hi = self.lookup_char_pos(sp.hi()); - lo.line != hi.line + let lo = self.lookup_source_file_idx(sp.lo()); + let hi = self.lookup_source_file_idx(sp.hi()); + if lo != hi { + return true; + } + let f = (*self.files.borrow().source_files)[lo].clone(); + f.lookup_line(sp.lo()) != f.lookup_line(sp.hi()) } pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> { diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index 5ea39b343b..cb017709c6 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -5,7 +5,6 @@ // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 use crate::hygiene::SyntaxContext; -use crate::SESSION_GLOBALS; use crate::{BytePos, SpanData}; use rustc_data_structures::fx::FxIndexSet; @@ -122,5 +121,5 @@ impl SpanInterner { // If an interner exists, return it. Otherwise, prepare a fresh one. #[inline] fn with_span_interner T>(f: F) -> T { - SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.span_interner.lock())) + crate::with_session_globals(|session_globals| f(&mut *session_globals.span_interner.lock())) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a31ab5b350..a8f969782b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -13,7 +13,7 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::str; -use crate::{Edition, Span, DUMMY_SP, SESSION_GLOBALS}; +use crate::{with_session_globals, Edition, Span, DUMMY_SP}; #[cfg(test)] mod tests; @@ -122,10 +122,14 @@ symbols! { // nice to have. Symbols { Alignment, + Any, Arc, Argument, ArgumentV1, Arguments, + AsMut, + AsRef, + BTreeEntry, BTreeMap, BTreeSet, BinaryHeap, @@ -139,6 +143,7 @@ symbols! { Continue, Copy, Count, + Cow, Debug, DebugStruct, DebugTuple, @@ -146,26 +151,35 @@ symbols! { Decoder, Default, Deref, + DirBuilder, + DoubleEndedIterator, + Duration, Encodable, Encoder, Eq, Equal, Err, Error, + File, + FileType, FormatSpec, Formatter, From, + FromIterator, Future, FxHashMap, FxHashSet, GlobalAlloc, Hash, HashMap, + HashMapEntry, HashSet, Hasher, Implied, Input, IntoIterator, + IoRead, + IoWrite, Is, ItemContext, Iterator, @@ -353,6 +367,7 @@ symbols! { cfg_eval, cfg_panic, cfg_sanitize, + cfg_target_abi, cfg_target_feature, cfg_target_has_atomic, cfg_target_thread_local, @@ -367,6 +382,8 @@ symbols! { closure, closure_to_fn_coercion, cmp, + cmp_max, + cmp_min, cmpxchg16b_target_feature, cmse_nonsecure_entry, coerce_unsized, @@ -416,7 +433,6 @@ symbols! { constructor, contents, context, - control_flow_enum, convert, copy, copy_closures, @@ -462,6 +478,7 @@ symbols! { decode, default_alloc_error_handler, default_lib_allocator, + default_method_body_is_const, default_type_parameter_fallback, default_type_params, delay_span_bug_from_inside_query, @@ -479,6 +496,7 @@ symbols! { discriminant_type, discriminant_value, dispatch_from_dyn, + display_trait, div, div_assign, doc, @@ -569,6 +587,7 @@ symbols! { fmt, fmt_internals, fmul_fast, + fn_align, fn_must_use, fn_mut, fn_once, @@ -586,6 +605,7 @@ symbols! { from, from_desugaring, from_generator, + from_iter, from_method, from_output, from_residual, @@ -669,6 +689,7 @@ symbols! { item, item_like_imports, iter, + iter_repeat, keyword, kind, kreg, @@ -680,6 +701,7 @@ symbols! { lateout, lazy_normalization_consts, le, + len, let_chains, lhs, lib, @@ -734,6 +756,12 @@ symbols! { maybe_uninit, maybe_uninit_uninit, maybe_uninit_zeroed, + mem_discriminant, + mem_drop, + mem_forget, + mem_replace, + mem_size_of, + mem_size_of_val, mem_uninitialized, mem_zeroed, member_constraints, @@ -752,6 +780,7 @@ symbols! { minnumf64, mips_target_feature, misc, + mmx_reg, modifiers, module, module_path, @@ -895,6 +924,7 @@ symbols! { prefetch_read_instruction, prefetch_write_data, prefetch_write_instruction, + preg, prelude, prelude_import, preserves_flags, @@ -930,6 +960,7 @@ symbols! { quote, range_inclusive_new, raw_dylib, + raw_eq, raw_identifiers, raw_ref_op, re_rebalance_coherence, @@ -944,7 +975,7 @@ symbols! { receiver, recursion_limit, reexport_test_harness_main, - ref_unwind_safe, + ref_unwind_safe_trait, reference, reflect, reg, @@ -1062,6 +1093,7 @@ symbols! { rustdoc, rustfmt, rvalue_static_promotion, + s, sanitize, sanitizer_runtime, saturating_add, @@ -1069,7 +1101,6 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, - send, send_trait, shl, shl_assign, @@ -1146,6 +1177,7 @@ symbols! { skip, slice, slice_alloc, + slice_len_fn, slice_patterns, slice_u8, slice_u8_alloc, @@ -1194,6 +1226,7 @@ symbols! { sync, sync_trait, t32, + target_abi, target_arch, target_endian, target_env, @@ -1235,7 +1268,9 @@ symbols! { truncf32, truncf64, try_blocks, + try_from, try_from_trait, + try_into, try_into_trait, try_trait_v2, tt, @@ -1292,7 +1327,7 @@ symbols! { unused_qualifications, unwind, unwind_attributes, - unwind_safe, + unwind_safe_trait, unwrap, unwrap_or, use_extern_macros, @@ -1335,6 +1370,7 @@ symbols! { wrapping_sub, wreg, write_bytes, + x87_reg, xmm_reg, ymm_reg, zmm_reg, @@ -1783,7 +1819,7 @@ impl Ident { #[inline] fn with_interner T>(f: F) -> T { - SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.symbol_interner.lock())) + with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock())) } /// An alternative to [`Symbol`], useful when the chars within the symbol need to diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs index 47da03424b..11dea265b4 100644 --- a/compiler/rustc_span/src/symbol/tests.rs +++ b/compiler/rustc_span/src/symbol/tests.rs @@ -1,6 +1,6 @@ use super::*; -use crate::{edition, SessionGlobals}; +use crate::create_default_session_globals_then; #[test] fn interner_tests() { @@ -18,7 +18,7 @@ fn interner_tests() { #[test] fn without_first_quote_test() { - SESSION_GLOBALS.set(&SessionGlobals::new(edition::DEFAULT_EDITION), || { + create_default_session_globals_then(|| { let i = Ident::from_str("'break"); assert_eq!(i.without_first_quote().name, kw::Break); }); diff --git a/compiler/rustc_span/src/tests.rs b/compiler/rustc_span/src/tests.rs index 3c8eb8bcd3..11edcacc0d 100644 --- a/compiler/rustc_span/src/tests.rs +++ b/compiler/rustc_span/src/tests.rs @@ -2,18 +2,21 @@ use super::*; #[test] fn test_lookup_line() { - let lines = &[BytePos(3), BytePos(17), BytePos(28)]; + let source = "abcdefghijklm\nabcdefghij\n...".to_owned(); + let sf = + SourceFile::new(FileName::Anon(0), source, BytePos(3), SourceFileHashAlgorithm::Sha256); + assert_eq!(sf.lines.as_slice(), &[BytePos(3), BytePos(17), BytePos(28)]); - assert_eq!(lookup_line(lines, BytePos(0)), -1); - assert_eq!(lookup_line(lines, BytePos(3)), 0); - assert_eq!(lookup_line(lines, BytePos(4)), 0); + assert_eq!(sf.lookup_line(BytePos(0)), None); + assert_eq!(sf.lookup_line(BytePos(3)), Some(0)); + assert_eq!(sf.lookup_line(BytePos(4)), Some(0)); - assert_eq!(lookup_line(lines, BytePos(16)), 0); - assert_eq!(lookup_line(lines, BytePos(17)), 1); - assert_eq!(lookup_line(lines, BytePos(18)), 1); + assert_eq!(sf.lookup_line(BytePos(16)), Some(0)); + assert_eq!(sf.lookup_line(BytePos(17)), Some(1)); + assert_eq!(sf.lookup_line(BytePos(18)), Some(1)); - assert_eq!(lookup_line(lines, BytePos(28)), 2); - assert_eq!(lookup_line(lines, BytePos(29)), 2); + assert_eq!(sf.lookup_line(BytePos(28)), Some(2)); + assert_eq!(sf.lookup_line(BytePos(29)), Some(2)); } #[test] diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 3df5f16131..53d4dc2922 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -12,7 +12,6 @@ tracing = "0.1" punycode = "0.4.0" rustc-demangle = "0.1.18" -rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 025eaffcbd..0c64fe6ea6 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -126,8 +126,9 @@ fn get_symbol_hash<'tcx>( substs.hash_stable(&mut hcx, &mut hasher); if let Some(instantiating_crate) = instantiating_crate { - tcx.crate_name(instantiating_crate).as_str().hash_stable(&mut hcx, &mut hasher); - tcx.crate_disambiguator(instantiating_crate).hash_stable(&mut hcx, &mut hasher); + tcx.def_path_hash(instantiating_crate.as_def_id()) + .stable_crate_id() + .hash_stable(&mut hcx, &mut hasher); } // We want to avoid accidental collision between different types of instances. diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index f716ce1efc..ba59ff96f6 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -165,12 +165,12 @@ fn compute_symbol_name( // FIXME(eddyb) Precompute a custom symbol name based on attributes. let is_foreign = if let Some(def_id) = def_id.as_local() { if tcx.plugin_registrar_fn(()) == Some(def_id) { - let disambiguator = tcx.sess.local_crate_disambiguator(); - return tcx.sess.generate_plugin_registrar_symbol(disambiguator); + let stable_crate_id = tcx.sess.local_stable_crate_id(); + return tcx.sess.generate_plugin_registrar_symbol(stable_crate_id); } if tcx.proc_macro_decls_static(()) == Some(def_id) { - let disambiguator = tcx.sess.local_crate_disambiguator(); - return tcx.sess.generate_proc_macro_decls_symbol(disambiguator); + let stable_crate_id = tcx.sess.local_stable_crate_id(); + return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); matches!(tcx.hir().get(hir_id), Node::ForeignItem(_)) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 828f1ac0a7..14442806fc 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -3,9 +3,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; 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, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; +use rustc_target::abi::Integer; use rustc_target::spec::abi::Abi; use std::fmt::Write; @@ -553,11 +555,9 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::Uint(_) | ty::Bool | ty::Char => { ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty) } - ty::Int(_) => { - let param_env = ty::ParamEnv::reveal_all(); - ct.try_eval_bits(self.tcx, param_env, ct.ty).and_then(|b| { - let sz = self.tcx.layout_of(param_env.and(ct.ty)).ok()?.size; - let val = sz.sign_extend(b) as i128; + ty::Int(ity) => { + ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty).and_then(|b| { + let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128; if val < 0 { neg = true; } @@ -592,8 +592,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { fn path_crate(mut self, cnum: CrateNum) -> Result { self.push("C"); - let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint(); - self.push_disambiguator(fingerprint.to_smaller_hash()); + let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); + self.push_disambiguator(stable_crate_id.to_u64()); let name = self.tcx.crate_name(cnum).as_str(); self.push_ident(&name); Ok(self) diff --git a/compiler/rustc_target/src/abi/call/msp430.rs b/compiler/rustc_target/src/abi/call/msp430.rs index 3004bb9ff5..0ba73657b5 100644 --- a/compiler/rustc_target/src/abi/call/msp430.rs +++ b/compiler/rustc_target/src/abi/call/msp430.rs @@ -1,5 +1,5 @@ // Reference: MSP430 Embedded Application Binary Interface -// http://www.ti.com/lit/an/slaa534/slaa534.pdf +// https://www.ti.com/lit/an/slaa534a/slaa534a.pdf use crate::abi::call::{ArgAbi, FnAbi}; diff --git a/compiler/rustc_target/src/abi/call/nvptx.rs b/compiler/rustc_target/src/abi/call/nvptx.rs index 693337f0e5..428dd95bbc 100644 --- a/compiler/rustc_target/src/abi/call/nvptx.rs +++ b/compiler/rustc_target/src/abi/call/nvptx.rs @@ -1,5 +1,5 @@ // Reference: PTX Writer's Guide to Interoperability -// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability +// https://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability use crate::abi::call::{ArgAbi, FnAbi}; diff --git a/compiler/rustc_target/src/abi/call/nvptx64.rs b/compiler/rustc_target/src/abi/call/nvptx64.rs index b9c9296dba..16f331b16d 100644 --- a/compiler/rustc_target/src/abi/call/nvptx64.rs +++ b/compiler/rustc_target/src/abi/call/nvptx64.rs @@ -1,5 +1,5 @@ // Reference: PTX Writer's Guide to Interoperability -// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability +// https://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability use crate::abi::call::{ArgAbi, FnAbi}; diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index 713b4100a3..ff8849e1cf 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -38,7 +38,7 @@ where // small structs are returned as integers. // // Some links: - // http://www.angelcode.com/dev/callconv/callconv.html + // https://www.angelcode.com/dev/callconv/callconv.html // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp let t = cx.target_spec(); if t.abi_return_struct_as_int { diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs index 5f154dc1bc..a55658b7a3 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/abi/call/x86_64.rs @@ -185,7 +185,7 @@ where if let Ok(cls) = cls_or_mem { let mut needed_int = 0; let mut needed_sse = 0; - for &c in &cls { + for c in cls { match c { Some(Class::Int) => needed_int += 1, Some(Class::Sse) => needed_sse += 1, diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 8e71ded3d1..9a24edf1a4 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -16,7 +16,7 @@ use rustc_span::Span; pub mod call; -/// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout) +/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout) /// for a target, which contains everything needed to compute layouts. pub struct TargetDataLayout { pub endian: Endian, @@ -590,7 +590,7 @@ impl Integer { pub fn for_align(cx: &C, wanted: Align) -> Option { let dl = cx.data_layout(); - for &candidate in &[I8, I16, I32, I64, I128] { + for candidate in [I8, I16, I32, I64, I128] { if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() { return Some(candidate); } @@ -603,7 +603,7 @@ impl Integer { let dl = cx.data_layout(); // FIXME(eddyb) maybe include I128 in the future, when it works everywhere. - for &candidate in &[I64, I32, I16] { + for candidate in [I64, I32, I16] { if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() { return candidate; } diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index f180eea01a..76e5067831 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -7,6 +7,7 @@ def_reg_class! { reg, vreg, vreg_low16, + preg, } } @@ -15,6 +16,7 @@ impl AArch64InlineAsmRegClass { match self { Self::reg => &['w', 'x'], Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v'], + Self::preg => &[], } } @@ -40,6 +42,7 @@ impl AArch64InlineAsmRegClass { 128 => Some(('q', "q0")), _ => None, }, + Self::preg => None, } } @@ -47,6 +50,7 @@ impl AArch64InlineAsmRegClass { match self { Self::reg => Some(('x', "x0")), Self::vreg | Self::vreg_low16 => Some(('v', "v0")), + Self::preg => None, } } @@ -61,6 +65,7 @@ impl AArch64InlineAsmRegClass { VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1), VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); }, + Self::preg => &[], } } } @@ -95,38 +100,55 @@ def_regs! { x27: reg = ["x27", "w27"], x28: reg = ["x28", "w28"], x30: reg = ["x30", "w30", "lr", "wlr"], - v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0"], - v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1"], - v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2"], - v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3"], - v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4"], - v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5"], - v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6"], - v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7"], - v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8"], - v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9"], - v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10"], - v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11"], - v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12"], - v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13"], - v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14"], - v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15"], - v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16"], - v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17"], - v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18"], - v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19"], - v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20"], - v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21"], - v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22"], - v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23"], - v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24"], - v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25"], - v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26"], - v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27"], - v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28"], - v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29"], - v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30"], - v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31"], + v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"], + v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"], + v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2", "z2"], + v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3", "z3"], + v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4", "z4"], + v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5", "z5"], + v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6", "z6"], + v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7", "z7"], + v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8", "z8"], + v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9", "z9"], + v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10", "z10"], + v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11", "z11"], + v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12", "z12"], + v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"], + v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"], + v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"], + v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"], + v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"], + v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"], + v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"], + v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"], + v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"], + v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"], + v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"], + v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"], + v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"], + v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"], + v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"], + v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"], + v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"], + v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"], + v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"], + p0: preg = ["p0"], + p1: preg = ["p1"], + p2: preg = ["p2"], + p3: preg = ["p3"], + p4: preg = ["p4"], + p5: preg = ["p5"], + p6: preg = ["p6"], + p7: preg = ["p7"], + p8: preg = ["p8"], + p9: preg = ["p9"], + p10: preg = ["p10"], + p11: preg = ["p11"], + p12: preg = ["p12"], + p13: preg = ["p13"], + p14: preg = ["p14"], + p15: preg = ["p15"], + ffr: preg = ["ffr"], #error = ["x18", "w18"] => "x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm", #error = ["x19", "w19"] => diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 305ea7d50e..b52fa5bbcb 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -533,6 +533,12 @@ impl InlineAsmRegClass { Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } + + /// Returns whether registers in this class can only be used as clobbers + /// and not as inputs/outputs. + pub fn is_clobber_only(self, arch: InlineAsmArch) -> bool { + self.supported_types(arch).is_empty() + } } #[derive( diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index e276a9175f..314bd01de1 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -7,6 +7,7 @@ def_reg_class! { RiscV RiscVInlineAsmRegClass { reg, freg, + vreg, } } @@ -44,6 +45,7 @@ impl RiscVInlineAsmRegClass { } } Self::freg => types! { "f": F32; "d": F64; }, + Self::vreg => &[], } } } @@ -120,6 +122,38 @@ def_regs! { f29: freg = ["f29", "ft9"], f30: freg = ["f30", "ft10"], f31: freg = ["f31", "ft11"], + v0: vreg = ["v0"], + v1: vreg = ["v1"], + v2: vreg = ["v2"], + v3: vreg = ["v3"], + v4: vreg = ["v4"], + v5: vreg = ["v5"], + v6: vreg = ["v6"], + v7: vreg = ["v7"], + v8: vreg = ["v8"], + v9: vreg = ["v9"], + v10: vreg = ["v10"], + v11: vreg = ["v11"], + v12: vreg = ["v12"], + v13: vreg = ["v13"], + v14: vreg = ["v14"], + v15: vreg = ["v15"], + v16: vreg = ["v16"], + v17: vreg = ["v17"], + v18: vreg = ["v18"], + v19: vreg = ["v19"], + v20: vreg = ["v20"], + v21: vreg = ["v21"], + v22: vreg = ["v22"], + v23: vreg = ["v23"], + v24: vreg = ["v24"], + v25: vreg = ["v25"], + v26: vreg = ["v26"], + v27: vreg = ["v27"], + v28: vreg = ["v28"], + v29: vreg = ["v29"], + v30: vreg = ["v30"], + v31: vreg = ["v31"], #error = ["x9", "s1"] => "s1 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["x8", "s0", "fp"] => diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 48f83ca7cd..5e3828d7d8 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -12,6 +12,8 @@ def_reg_class! { ymm_reg, zmm_reg, kreg, + mmx_reg, + x87_reg, } } @@ -35,6 +37,7 @@ impl X86InlineAsmRegClass { Self::reg_byte => &[], Self::xmm_reg | Self::ymm_reg | Self::zmm_reg => &['x', 'y', 'z'], Self::kreg => &[], + Self::mmx_reg | Self::x87_reg => &[], } } @@ -73,6 +76,7 @@ impl X86InlineAsmRegClass { _ => Some(('x', "xmm0")), }, Self::kreg => None, + Self::mmx_reg | Self::x87_reg => None, } } @@ -90,6 +94,7 @@ impl X86InlineAsmRegClass { Self::ymm_reg => Some(('y', "ymm0")), Self::zmm_reg => Some(('z', "zmm0")), Self::kreg => None, + Self::mmx_reg | Self::x87_reg => None, } } @@ -125,6 +130,7 @@ impl X86InlineAsmRegClass { "avx512f": I8, I16; "avx512bw": I32, I64; }, + Self::mmx_reg | Self::x87_reg => &[], } } } @@ -285,16 +291,28 @@ def_regs! { k5: kreg = ["k5"], k6: kreg = ["k6"], k7: kreg = ["k7"], + mm0: mmx_reg = ["mm0"], + mm1: mmx_reg = ["mm1"], + mm2: mmx_reg = ["mm2"], + mm3: mmx_reg = ["mm3"], + mm4: mmx_reg = ["mm4"], + mm5: mmx_reg = ["mm5"], + mm6: mmx_reg = ["mm6"], + mm7: mmx_reg = ["mm7"], + st0: x87_reg = ["st(0)", "st"], + st1: x87_reg = ["st(1)"], + st2: x87_reg = ["st(2)"], + st3: x87_reg = ["st(3)"], + st4: x87_reg = ["st(4)"], + st5: x87_reg = ["st(5)"], + st6: x87_reg = ["st(6)"], + st7: x87_reg = ["st(7)"], #error = ["bp", "bpl", "ebp", "rbp"] => "the frame pointer cannot be used as an operand for inline asm", #error = ["sp", "spl", "esp", "rsp"] => "the stack pointer cannot be used as an operand for inline asm", #error = ["ip", "eip", "rip"] => "the instruction pointer cannot be used as an operand for inline asm", - #error = ["st", "st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"] => - "x87 registers are not currently supported as operands for inline asm", - #error = ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"] => - "MMX registers are not currently supported as operands for inline asm", #error = ["k0"] => "the k0 AVX mask register cannot be used as an operand for inline asm", } diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index cb8f6b9656..d39e5a5aa2 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -27,6 +27,9 @@ pub mod abi; pub mod asm; pub mod spec; +#[cfg(test)] +mod tests; + /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index feadd4e891..bf3ec8f916 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); @@ -20,6 +20,10 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(), arch: arch.to_string(), - options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base }, + options: TargetOptions { + mcount: "\u{1}mcount".to_string(), + frame_pointer: FramePointer::NonLeaf, + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index 5682039b86..e5805d9e69 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -1,8 +1,7 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::Arm64); Target { llvm_target: "arm64-apple-ios".to_string(), pointer_width: 64, @@ -11,8 +10,8 @@ pub fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".to_string(), max_atomic_width: Some(128), - unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, + frame_pointer: FramePointer::NonLeaf, // Taken from a clang build on Xcode 11.4.1. // These arguments are not actually invoked - they just have // to look right to pass App Store validation. @@ -24,7 +23,7 @@ pub fn target() -> Target { darwinpcs\0\ -Os\0" .to_string(), - ..base + ..opts("ios", Arch::Arm64) }, } } 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 8a832546d0..d16328f00f 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -1,8 +1,7 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::Arm64_macabi); Target { llvm_target: "arm64-apple-ios14.0-macabi".to_string(), pointer_width: 64, @@ -11,8 +10,8 @@ pub fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".to_string(), max_atomic_width: Some(128), - unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, + frame_pointer: FramePointer::NonLeaf, // Taken from a clang build on Xcode 11.4.1. // These arguments are not actually invoked - they just have // to look right to pass App Store validation. @@ -22,7 +21,7 @@ pub fn target() -> Target { -disable-llvm-passes\0\ -Os\0" .to_string(), - ..base + ..opts("ios", Arch::Arm64_macabi) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs index 2187015b62..07b3453218 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -1,5 +1,5 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { let base = opts("ios", Arch::Arm64_sim); @@ -19,8 +19,8 @@ pub fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".to_string(), max_atomic_width: Some(128), - unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, + frame_pointer: FramePointer::NonLeaf, // Taken from a clang build on Xcode 11.4.1. // These arguments are not actually invoked - they just have // to look right to pass App Store validation. diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index cb6c06b371..b4bd72a082 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -1,8 +1,7 @@ use super::apple_sdk_base::{opts, Arch}; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { - let base = opts("tvos", Arch::Arm64); Target { llvm_target: "arm64-apple-tvos".to_string(), pointer_width: 64, @@ -11,9 +10,9 @@ pub fn target() -> Target { options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".to_string(), max_atomic_width: Some(128), - unsupported_abis: super::arm_base::unsupported_abis(), forces_embed_bitcode: true, - ..base + frame_pointer: FramePointer::NonLeaf, + ..opts("tvos", Arch::Arm64) }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs index 192c4661c7..71ee6deb07 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs @@ -2,19 +2,16 @@ use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); - base.max_atomic_width = Some(128); - Target { llvm_target: "aarch64_be-unknown-linux-gnu".to_string(), pointer_width: 64, data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { - unsupported_abis: super::arm_base::unsupported_abis(), + max_atomic_width: Some(128), mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs index 5b9e9c9519..e05360ea45 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { - unsupported_abis: super::arm_base::unsupported_abis(), + abi: "ilp32".to_string(), mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, ..base diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs index c9cb21f1eb..56d71df6bd 100644 --- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs @@ -1,15 +1,15 @@ use crate::spec::{SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::fuchsia_base::opts(); - base.max_atomic_width = Some(128); - base.supported_sanitizers = SanitizerSet::ADDRESS; - Target { llvm_target: "aarch64-fuchsia".to_string(), pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base }, + options: TargetOptions { + max_atomic_width: Some(128), + supported_sanitizers: SanitizerSet::ADDRESS, + ..super::fuchsia_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs index eaf3a2dbcf..409cab72ec 100644 --- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs @@ -4,17 +4,18 @@ use crate::spec::{SanitizerSet, Target, TargetOptions}; // for target ABI requirements. pub fn target() -> Target { - let mut base = super::android_base::opts(); - base.max_atomic_width = Some(128); - // As documented in http://developer.android.com/ndk/guides/cpu-features.html - // the neon (ASIMD) and FP must exist on all android aarch64 targets. - base.features = "+neon,+fp-armv8".to_string(); - base.supported_sanitizers = SanitizerSet::HWADDRESS; Target { llvm_target: "aarch64-linux-android".to_string(), pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base }, + options: TargetOptions { + max_atomic_width: Some(128), + // As documented in https://developer.android.com/ndk/guides/cpu-features.html + // the neon (ASIMD) and FP must exist on all android aarch64 targets. + features: "+neon,+fp-armv8".to_string(), + supported_sanitizers: SanitizerSet::HWADDRESS, + ..super::android_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs index d48389d4a3..09ea7d33cf 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs @@ -1,14 +1,11 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); - base.max_atomic_width = Some(128); - Target { llvm_target: "aarch64-unknown-freebsd".to_string(), pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base }, + options: TargetOptions { max_atomic_width: Some(128), ..super::freebsd_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs index a07cd7db88..3e92ecbae0 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs @@ -1,23 +1,20 @@ use crate::spec::{SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); - base.max_atomic_width = Some(128); - base.supported_sanitizers = SanitizerSet::ADDRESS - | SanitizerSet::LEAK - | SanitizerSet::MEMORY - | SanitizerSet::THREAD - | SanitizerSet::HWADDRESS; - Target { llvm_target: "aarch64-unknown-linux-gnu".to_string(), pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}_mcount".to_string(), - ..base + max_atomic_width: Some(128), + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD + | SanitizerSet::HWADDRESS, + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs index f2d7576280..8522405f61 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs @@ -1,18 +1,16 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); - base.max_atomic_width = Some(128); - Target { llvm_target: "aarch64-unknown-linux-gnu_ilp32".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), options: TargetOptions { - unsupported_abis: super::arm_base::unsupported_abis(), + abi: "ilp32".to_string(), + max_atomic_width: Some(128), mcount: "\u{1}_mcount".to_string(), - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs index 7bbfc8ec0f..6a16b4ce41 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs @@ -9,10 +9,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { - unsupported_abis: super::arm_base::unsupported_abis(), - mcount: "\u{1}_mcount".to_string(), - ..base - }, + options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs index 09efbdbb29..4042028e2d 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs @@ -1,15 +1,15 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); - base.max_atomic_width = Some(128); - base.unsupported_abis = super::arm_base::unsupported_abis(); - Target { llvm_target: "aarch64-unknown-netbsd".to_string(), pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { mcount: "__mcount".to_string(), ..base }, + options: TargetOptions { + mcount: "__mcount".to_string(), + max_atomic_width: Some(128), + ..super::netbsd_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs index de92b167f0..9d36527901 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs @@ -18,7 +18,6 @@ pub fn target() -> Target { disable_redzone: true, max_atomic_width: Some(128), panic_strategy: PanicStrategy::Abort, - unsupported_abis: super::arm_base::unsupported_abis(), ..Default::default() }; Target { 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 2566eeae14..fa93ca8054 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs @@ -10,6 +10,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp pub fn target() -> Target { let opts = TargetOptions { + abi: "softfloat".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), features: "+strict-align,-neon,-fp-armv8".to_string(), @@ -18,7 +19,6 @@ pub fn target() -> Target { disable_redzone: true, max_atomic_width: Some(128), panic_strategy: PanicStrategy::Abort, - unsupported_abis: super::arm_base::unsupported_abis(), ..Default::default() }; Target { diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs index 83ba1ecd1d..193f981421 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs @@ -1,15 +1,11 @@ -use crate::spec::Target; +use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); - base.max_atomic_width = Some(128); - base.unsupported_abis = super::arm_base::unsupported_abis(); - Target { llvm_target: "aarch64-unknown-openbsd".to_string(), pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: base, + options: TargetOptions { max_atomic_width: Some(128), ..super::openbsd_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs index beb8ce30cc..66140060f8 100644 --- a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs @@ -1,14 +1,11 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); - base.max_atomic_width = Some(128); - Target { llvm_target: "aarch64-unknown-linux-gnu".to_string(), pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), arch: "aarch64".to_string(), - options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base }, + options: TargetOptions { max_atomic_width: Some(128), ..super::vxworks_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index a026a623f7..ee36090c54 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -8,16 +8,11 @@ mod tests; #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)] #[derive(HashStable_Generic, Encodable, Decodable)] pub enum Abi { - // Multiplatform / generic ABIs - // - // These ABIs come first because every time we add a new ABI, we - // have to re-bless all the hashing tests. These are used in many - // places, so giving them stable values reduces test churn. The - // specific values are meaningless. + // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the + // hashing tests. These are used in many places, so giving them stable values reduces test + // churn. The specific values are meaningless. Rust, C { unwind: bool }, - - // Single platform ABIs Cdecl, Stdcall { unwind: bool }, Fastcall, @@ -35,8 +30,6 @@ pub enum Abi { AvrNonBlockingInterrupt, CCmseNonSecureCall, Wasm, - - // Multiplatform / generic ABIs System { unwind: bool }, RustIntrinsic, RustCall, @@ -50,48 +43,38 @@ pub struct AbiData { /// Name of this ABI as we like it called. name: &'static str, - - /// A generic ABI is supported on all platforms. - generic: bool, } #[allow(non_upper_case_globals)] const AbiDatas: &[AbiData] = &[ - // Cross-platform ABIs - AbiData { abi: Abi::Rust, name: "Rust", generic: true }, - AbiData { abi: Abi::C { unwind: false }, name: "C", generic: true }, - AbiData { abi: Abi::C { unwind: true }, name: "C-unwind", generic: true }, - // Platform-specific ABIs - AbiData { abi: Abi::Cdecl, name: "cdecl", generic: false }, - AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall", generic: false }, - AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind", generic: false }, - AbiData { abi: Abi::Fastcall, name: "fastcall", generic: false }, - AbiData { abi: Abi::Vectorcall, name: "vectorcall", generic: false }, - AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall", generic: false }, - AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind", generic: false }, - AbiData { abi: Abi::Aapcs, name: "aapcs", generic: false }, - AbiData { abi: Abi::Win64, name: "win64", generic: false }, - AbiData { abi: Abi::SysV64, name: "sysv64", generic: false }, - AbiData { abi: Abi::PtxKernel, name: "ptx-kernel", generic: false }, - AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false }, - AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false }, - AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false }, - AbiData { abi: Abi::EfiApi, name: "efiapi", generic: false }, - AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt", generic: false }, - AbiData { - abi: Abi::AvrNonBlockingInterrupt, - name: "avr-non-blocking-interrupt", - generic: false, - }, - AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false }, - AbiData { abi: Abi::Wasm, name: "wasm", generic: false }, - // Cross-platform ABIs - AbiData { abi: Abi::System { unwind: false }, name: "system", generic: true }, - AbiData { abi: Abi::System { unwind: true }, name: "system-unwind", generic: true }, - AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true }, - AbiData { abi: Abi::RustCall, name: "rust-call", generic: true }, - AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true }, - AbiData { abi: Abi::Unadjusted, name: "unadjusted", generic: true }, + AbiData { abi: Abi::Rust, name: "Rust" }, + AbiData { abi: Abi::C { unwind: false }, name: "C" }, + AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" }, + AbiData { abi: Abi::Cdecl, name: "cdecl" }, + AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" }, + AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" }, + AbiData { abi: Abi::Fastcall, name: "fastcall" }, + AbiData { abi: Abi::Vectorcall, name: "vectorcall" }, + AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" }, + AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" }, + AbiData { abi: Abi::Aapcs, name: "aapcs" }, + AbiData { abi: Abi::Win64, name: "win64" }, + AbiData { abi: Abi::SysV64, name: "sysv64" }, + AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" }, + AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" }, + AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" }, + AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel" }, + AbiData { abi: Abi::EfiApi, name: "efiapi" }, + AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" }, + AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" }, + AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" }, + AbiData { abi: Abi::Wasm, name: "wasm" }, + AbiData { abi: Abi::System { unwind: false }, name: "system" }, + AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" }, + AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" }, + AbiData { abi: Abi::RustCall, name: "rust-call" }, + AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" }, + AbiData { abi: Abi::Unadjusted, name: "unadjusted" }, ]; /// Returns the ABI with the given name (if any). @@ -163,10 +146,6 @@ impl Abi { pub fn name(self) -> &'static str { self.data().name } - - pub fn generic(self) -> bool { - self.data().generic - } } impl fmt::Display for Abi { diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 8530db179d..0c8a89210f 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -1,6 +1,6 @@ use std::env; -use crate::spec::{SplitDebuginfo, TargetOptions}; +use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions}; pub fn opts(os: &str) -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 @@ -27,7 +27,7 @@ pub fn opts(os: &str) -> TargetOptions { families: vec!["unix".to_string()], is_like_osx: true, dwarf_version: Some(2), - eliminate_frame_pointer: false, + frame_pointer: FramePointer::Always, has_rpath: true, dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs index e7f7bb343d..39bc699eef 100644 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs @@ -14,6 +14,15 @@ pub enum Arch { Arm64_sim, } +fn target_abi(arch: Arch) -> String { + match arch { + Armv7 | Armv7s | Arm64 | I386 | X86_64 => "", + X86_64_macabi | Arm64_macabi => "macabi", + Arm64_sim => "sim", + } + .to_string() +} + fn target_cpu(arch: Arch) -> String { match arch { Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher @@ -39,6 +48,7 @@ fn link_env_remove(arch: Arch) -> Vec { pub fn opts(os: &str, arch: Arch) -> TargetOptions { TargetOptions { + abi: target_abi(arch), cpu: target_cpu(arch), dynamic_linking: false, executables: true, diff --git a/compiler/rustc_target/src/spec/arm_base.rs b/compiler/rustc_target/src/spec/arm_base.rs deleted file mode 100644 index 01f573313c..0000000000 --- a/compiler/rustc_target/src/spec/arm_base.rs +++ /dev/null @@ -1,15 +0,0 @@ -use crate::spec::abi::Abi; - -// All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm -pub fn unsupported_abis() -> Vec { - vec![ - Abi::Stdcall { unwind: false }, - Abi::Stdcall { unwind: true }, - Abi::Fastcall, - Abi::Vectorcall, - Abi::Thiscall { unwind: false }, - Abi::Thiscall { unwind: true }, - Abi::Win64, - Abi::SysV64, - ] -} diff --git a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs index 43537569e7..9b5366c576 100644 --- a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs @@ -1,16 +1,17 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::android_base::opts(); - // https://developer.android.com/ndk/guides/abis.html#armeabi - base.features = "+strict-align,+v5te".to_string(); - base.max_atomic_width = Some(32); - Target { llvm_target: "arm-linux-androideabi".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base }, + options: TargetOptions { + abi: "eabi".to_string(), + // https://developer.android.com/ndk/guides/abis.html#armeabi + features: "+strict-align,+v5te".to_string(), + max_atomic_width: Some(32), + ..super::android_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs index c41cf6e521..442f56d4fb 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs @@ -1,19 +1,17 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); - base.max_atomic_width = Some(64); Target { llvm_target: "arm-unknown-linux-gnueabi".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabi".to_string(), features: "+strict-align,+v6".to_string(), - unsupported_abis: super::arm_base::unsupported_abis(), + max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".to_string(), - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs index f2143966c1..2c12a71e29 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs @@ -1,19 +1,17 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); - base.max_atomic_width = Some(64); Target { llvm_target: "arm-unknown-linux-gnueabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), features: "+strict-align,+v6,+vfp2,-d32".to_string(), - unsupported_abis: super::arm_base::unsupported_abis(), + max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".to_string(), - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs index 53ff1001c2..d187dfd918 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs @@ -1,12 +1,6 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); - - // Most of these settings are copied from the arm_unknown_linux_gnueabi - // target. - base.features = "+strict-align,+v6".to_string(); - base.max_atomic_width = Some(64); Target { // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it // to determine the calling convention and float ABI, and it doesn't @@ -16,9 +10,13 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), options: TargetOptions { - unsupported_abis: super::arm_base::unsupported_abis(), + abi: "eabi".to_string(), + // Most of these settings are copied from the arm_unknown_linux_gnueabi + // target. + features: "+strict-align,+v6".to_string(), + max_atomic_width: Some(64), mcount: "\u{1}mcount".to_string(), - ..base + ..super::linux_musl_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs index 6d8a5f9f88..3d72734f5f 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs @@ -1,12 +1,6 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); - - // Most of these settings are copied from the arm_unknown_linux_gnueabihf - // target. - base.features = "+strict-align,+v6,+vfp2,-d32".to_string(); - base.max_atomic_width = Some(64); Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and it @@ -16,9 +10,13 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), options: TargetOptions { - unsupported_abis: super::arm_base::unsupported_abis(), + abi: "eabihf".to_string(), + // Most of these settings are copied from the arm_unknown_linux_gnueabihf + // target. + features: "+strict-align,+v6,+vfp2,-d32".to_string(), + max_atomic_width: Some(64), mcount: "\u{1}mcount".to_string(), - ..base + ..super::linux_musl_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs index 255740cb9c..c98a12cfc4 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabi".to_string(), endian: Endian::Big, linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, @@ -19,7 +19,6 @@ pub fn target() -> Target { relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), emit_debug_gdb_scripts: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs index eb82e4d17b..292635403f 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs @@ -10,8 +10,8 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), endian: Endian::Big, linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, @@ -20,7 +20,6 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Abort, features: "+vfp3,-d32,-fp16".to_string(), max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), emit_debug_gdb_scripts: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs index e1ba72bf83..f1b193a384 100644 --- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs @@ -1,21 +1,19 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv4t-unknown-linux-gnueabi".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabi".to_string(), features: "+soft-float,+strict-align".to_string(), // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), has_thumb_interworking: true, - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs index 3ac8d53564..a6c4f2304c 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs @@ -1,21 +1,19 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv5te-unknown-linux-gnueabi".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabi".to_string(), features: "+soft-float,+strict-align".to_string(), // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), has_thumb_interworking: true, - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs index 40d405c30a..de2a350e23 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs @@ -1,8 +1,8 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::linux_musl_base::opts(); Target { + // FIXME: this comment below does not seem applicable? // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and LLVM // doesn't support the "musleabihf" value. @@ -10,15 +10,14 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabi".to_string(), features: "+soft-float,+strict-align".to_string(), // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), has_thumb_interworking: true, - ..base + ..super::linux_musl_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs index 3eb0f4db83..91b4bd27ca 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs @@ -7,13 +7,12 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), options: TargetOptions { + abi: "eabi".to_string(), features: "+soft-float,+strict-align".to_string(), // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), has_thumb_interworking: true, - ..super::linux_uclibc_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs index a149bd983b..ee2f8f6238 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs @@ -1,20 +1,19 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::freebsd_base::opts(); Target { llvm_target: "armv6-unknown-freebsd-gnueabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), + // FIXME: change env to "gnu" when cfg_target_abi becomes stable env: "gnueabihf".to_string(), features: "+v6,+vfp2,-d32".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), - ..base + ..super::freebsd_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs index 6c81a458b9..b046819d4d 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs @@ -1,20 +1,19 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); - base.max_atomic_width = Some(64); Target { llvm_target: "armv6-unknown-netbsdelf-eabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), + // FIXME: remove env when cfg_target_abi becomes stable env: "eabihf".to_string(), features: "+v6,+vfp2,-d32".to_string(), - unsupported_abis: super::arm_base::unsupported_abis(), + max_atomic_width: Some(64), mcount: "__mcount".to_string(), - ..base + ..super::netbsd_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs index 051a394657..2f228688f4 100644 --- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs @@ -2,7 +2,6 @@ use super::apple_sdk_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::Armv7); Target { llvm_target: "armv7-apple-ios".to_string(), pointer_width: 32, @@ -11,8 +10,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v7,+vfp3,+neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), - ..base + ..opts("ios", Arch::Armv7) }, } } diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs index 02a1191463..55956f3bad 100644 --- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs @@ -10,15 +10,17 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::android_base::opts(); - base.features = "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(); - base.max_atomic_width = Some(64); base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string()); - Target { llvm_target: "armv7-none-linux-android".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base }, + options: TargetOptions { + abi: "eabi".to_string(), + features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(), + max_atomic_width: Some(64), + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs index 6f24c6818f..fbfb1c2768 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs @@ -1,20 +1,19 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::freebsd_base::opts(); Target { llvm_target: "armv7-unknown-freebsd-gnueabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), + // FIXME: change env to "gnu" when cfg_target_abi becomes stable env: "gnueabihf".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), - ..base + ..super::freebsd_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs index f6fe88de37..0a3b8033dd 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs @@ -4,19 +4,17 @@ use crate::spec::{Target, TargetOptions}; // hardfloat. pub fn target() -> Target { - let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabi".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabi".to_string(), features: "+v7,+thumb2,+soft-float,-neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs index 5f0f47dd39..662b81cae3 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs @@ -4,20 +4,18 @@ use crate::spec::{Target, TargetOptions}; // thumb-mode. See the thumbv7neon variant for enabling both. pub fn target() -> Target { - let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}__gnu_mcount_nc".to_string(), - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs index c888fc2d4a..c0fd1de17c 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs @@ -4,7 +4,6 @@ use crate::spec::{Target, TargetOptions}; // hardfloat. pub fn target() -> Target { - let base = super::linux_musl_base::opts(); // Most of these settings are copied from the armv7_unknown_linux_gnueabi // target. Target { @@ -17,11 +16,11 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { + abi: "eabi".to_string(), features: "+v7,+thumb2,+soft-float,-neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), - ..base + ..super::linux_musl_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs index 2432ea519a..67ff7999de 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs @@ -3,7 +3,6 @@ use crate::spec::{Target, TargetOptions}; // This target is for musl Linux on ARMv7 without thumb-mode or NEON. pub fn target() -> Target { - let base = super::linux_musl_base::opts(); Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and LLVM @@ -16,11 +15,11 @@ pub fn target() -> Target { // Most of these settings are copied from the armv7_unknown_linux_gnueabihf // target. options: TargetOptions { + abi: "eabihf".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), - ..base + ..super::linux_musl_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs index 4fae3a8d0b..60a552b018 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs @@ -1,20 +1,19 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::netbsd_base::opts(); Target { llvm_target: "armv7-unknown-netbsdelf-eabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), + // FIXME: remove env when cfg_target_abi becomes stable env: "eabihf".to_string(), features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "__mcount".to_string(), - ..base + ..super::netbsd_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs index 9fe7098a85..27d404b101 100644 --- a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs @@ -1,18 +1,17 @@ use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = super::vxworks_base::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), options: TargetOptions { + abi: "eabihf".to_string(), // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), - ..base + ..super::vxworks_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs index 74deab0191..8bff60e9ed 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs @@ -18,6 +18,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp pub fn target() -> Target { let opts = TargetOptions { + abi: "eabi".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), features: "+v7,+thumb2,+soft-float,-neon,+strict-align".to_string(), @@ -26,7 +27,6 @@ pub fn target() -> Target { disable_redzone: true, max_atomic_width: Some(64), panic_strategy: PanicStrategy::Abort, - unsupported_abis: super::arm_base::unsupported_abis(), emit_debug_gdb_scripts: false, ..Default::default() }; diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs index c5c720f5fb..ea2751e375 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs @@ -9,6 +9,7 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOp pub fn target() -> Target { let opts = TargetOptions { + abi: "eabihf".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".to_string(), @@ -17,7 +18,6 @@ pub fn target() -> Target { disable_redzone: true, max_atomic_width: Some(64), panic_strategy: PanicStrategy::Abort, - unsupported_abis: super::arm_base::unsupported_abis(), emit_debug_gdb_scripts: false, ..Default::default() }; diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs index 3f49bd8786..c695542805 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs @@ -11,13 +11,13 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { + abi: "eabi".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), emit_debug_gdb_scripts: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs index 9b2e8a8058..50c37021b7 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs @@ -11,6 +11,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { + abi: "eabihf".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), @@ -18,7 +19,6 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Abort, features: "+vfp3,-d32,-fp16".to_string(), max_atomic_width: Some(32), - unsupported_abis: super::arm_base::unsupported_abis(), emit_debug_gdb_scripts: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs index be74136a2d..2a48e7b621 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs @@ -2,7 +2,6 @@ use super::apple_sdk_base::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let base = opts("ios", Arch::Armv7s); Target { llvm_target: "armv7s-apple-ios".to_string(), pointer_width: 32, @@ -11,8 +10,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v7,+vfp4,+neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), - ..base + ..opts("ios", Arch::Armv7s) }, } } diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/bpf_base.rs index 764cc735d7..4fa6e12f5b 100644 --- a/compiler/rustc_target/src/spec/bpf_base.rs +++ b/compiler/rustc_target/src/spec/bpf_base.rs @@ -1,5 +1,5 @@ +use crate::abi::Endian; use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions}; -use crate::{abi::Endian, spec::abi::Abi}; pub fn opts(endian: Endian) -> TargetOptions { TargetOptions { @@ -21,22 +21,6 @@ pub fn opts(endian: Endian) -> TargetOptions { requires_lto: false, singlethread: true, max_atomic_width: Some(64), - unsupported_abis: vec![ - Abi::Cdecl, - Abi::Stdcall { unwind: false }, - Abi::Stdcall { unwind: true }, - Abi::Fastcall, - Abi::Vectorcall, - Abi::Thiscall { unwind: false }, - Abi::Thiscall { unwind: true }, - Abi::Aapcs, - Abi::Win64, - Abi::SysV64, - Abi::PtxKernel, - Abi::Msp430Interrupt, - Abi::X86Interrupt, - Abi::AmdGpuKernel, - ], ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs index bef2fce7c8..998d6ffe0f 100644 --- a/compiler/rustc_target/src/spec/freebsd_base.rs +++ b/compiler/rustc_target/src/spec/freebsd_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{RelroLevel, TargetOptions}; +use crate::spec::{FramePointer, RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { TargetOptions { @@ -8,7 +8,7 @@ pub fn opts() -> TargetOptions { families: vec!["unix".to_string()], has_rpath: true, position_independent_executables: true, - eliminate_frame_pointer: false, // FIXME 43575 + frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit... relro_level: RelroLevel::Full, abi_return_struct_as_int: true, dwarf_version: Some(2), diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index 06d71db4af..f2635f0656 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions}; +use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); @@ -8,7 +8,7 @@ pub fn target() -> Target { base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; - base.eliminate_frame_pointer = false; + base.frame_pointer = FramePointer::Always; // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work diff --git a/compiler/rustc_target/src/spec/i686_linux_android.rs b/compiler/rustc_target/src/spec/i686_linux_android.rs index 19d7b3c95c..640f9e42f4 100644 --- a/compiler/rustc_target/src/spec/i686_linux_android.rs +++ b/compiler/rustc_target/src/spec/i686_linux_android.rs @@ -8,7 +8,7 @@ pub fn target() -> Target { base.max_atomic_width = Some(64); - // http://developer.android.com/ndk/guides/abis.html#x86 + // https://developer.android.com/ndk/guides/abis.html#x86 base.cpu = "pentiumpro".to_string(); base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".to_string(); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs index 7002d88c51..92c3a1554a 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::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); @@ -6,7 +6,7 @@ pub fn target() -> Target { base.pre_link_args .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]); base.max_atomic_width = Some(64); - base.eliminate_frame_pointer = false; // Required for backtraces + base.frame_pointer = FramePointer::Always; // Required for backtraces base.linker = Some("i686-w64-mingw32-gcc".to_string()); // Mark all dynamic libraries and executables as compatible with the larger 4GiB address 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 228976779f..d95cb6a82d 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, StackProbeType, Target}; +use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); @@ -21,7 +21,7 @@ pub fn target() -> Target { // // This may or may not be related to this bug: // https://llvm.org/bugs/show_bug.cgi?id=30879 - base.eliminate_frame_pointer = false; + base.frame_pointer = FramePointer::Always; Target { llvm_target: "i686-unknown-linux-musl".to_string(), 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 426df59882..27a0ac585e 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::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); @@ -6,7 +6,7 @@ pub fn target() -> Target { base.pre_link_args .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]); base.max_atomic_width = Some(64); - base.eliminate_frame_pointer = false; // Required for backtraces + base.frame_pointer = FramePointer::Always; // Required for backtraces // 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/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs index 9d9da50be7..f598f0f38f 100644 --- a/compiler/rustc_target/src/spec/illumos_base.rs +++ b/compiler/rustc_target/src/spec/illumos_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use crate::spec::{FramePointer, LinkArgs, LinkerFlavor, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { @@ -35,7 +35,7 @@ pub fn opts() -> TargetOptions { is_like_solaris: true, linker_is_gnu: false, limit_rdylib_exports: false, // Linker doesn't support this - eliminate_frame_pointer: false, + frame_pointer: FramePointer::Always, eh_frame_header: false, late_link_args, diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs index 145aa4a589..a332e3b847 100644 --- a/compiler/rustc_target/src/spec/linux_kernel_base.rs +++ b/compiler/rustc_target/src/spec/linux_kernel_base.rs @@ -1,4 +1,5 @@ -use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions}; +use crate::spec::TargetOptions; +use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType}; pub fn opts() -> TargetOptions { TargetOptions { @@ -7,7 +8,7 @@ pub fn opts() -> TargetOptions { panic_strategy: PanicStrategy::Abort, // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved stack_probes: StackProbeType::Call, - eliminate_frame_pointer: false, + frame_pointer: FramePointer::Always, position_independent_executables: true, needs_plt: true, relro_level: RelroLevel::Full, diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs index 53398539ac..161a27ab68 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs @@ -8,6 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { + abi: "abi64".to_string(), endian: Endian::Big, // NOTE(mips64r2) matches C toolchain cpu: "mips64r2".to_string(), diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs index 329fbd2272..a898464569 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs @@ -12,6 +12,11 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), - options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { + abi: "abi64".to_string(), + endian: Endian::Big, + mcount: "_mcount".to_string(), + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs index d767705b04..2f58560d45 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs @@ -7,6 +7,7 @@ pub fn target() -> Target { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { + abi: "abi64".to_string(), // NOTE(mips64r2) matches C toolchain cpu: "mips64r2".to_string(), features: "+mips64r2".to_string(), diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs index 766ed69df4..01c34bc399 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs @@ -11,6 +11,6 @@ pub fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), - options: TargetOptions { mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { abi: "abi64".to_string(), mcount: "_mcount".to_string(), ..base }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs index 110c8dd80e..5955baa31d 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs @@ -2,7 +2,6 @@ //! //! Can be used for MIPS M4K core (e.g. on PIC32MX devices) -use crate::spec::abi::Abi; use crate::spec::{LinkerFlavor, LldFlavor, RelocModel}; use crate::spec::{PanicStrategy, Target, TargetOptions}; @@ -22,16 +21,6 @@ pub fn target() -> Target { linker: Some("rust-lld".to_owned()), panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, - unsupported_abis: vec![ - Abi::Stdcall { unwind: false }, - Abi::Stdcall { unwind: true }, - Abi::Fastcall, - Abi::Vectorcall, - Abi::Thiscall { unwind: false }, - Abi::Thiscall { unwind: true }, - Abi::Win64, - Abi::SysV64, - ], emit_debug_gdb_scripts: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs index 3bf837fbb4..80a155a486 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -8,6 +8,7 @@ pub fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { + abi: "abi64".to_string(), endian: Endian::Big, // NOTE(mips64r6) matches C toolchain cpu: "mips64r6".to_string(), diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs index 589d7acba6..58f9862715 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -7,6 +7,7 @@ pub fn target() -> Target { data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), arch: "mips64".to_string(), options: TargetOptions { + abi: "abi64".to_string(), // NOTE(mips64r6) matches C toolchain cpu: "mips64r6".to_string(), features: "+mips64r6".to_string(), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0f2aaeb533..0185132ee3 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -25,7 +25,7 @@ //! //! # Defining a new target //! -//! Targets are defined using [JSON](http://json.org/). The `Target` struct in +//! Targets are defined using [JSON](https://json.org/). The `Target` struct in //! this module defines the format the JSON file should take, though each //! underscore in the field names should be replaced with a hyphen (`-`) in the //! JSON file. Some fields are required in every target specification, such as @@ -55,7 +55,6 @@ pub mod crt_objects; mod android_base; mod apple_base; mod apple_sdk_base; -mod arm_base; mod avr_gnu_base; mod bpf_base; mod dragonfly_base; @@ -75,7 +74,6 @@ mod msvc_base; mod netbsd_base; mod openbsd_base; mod redox_base; -mod riscv_base; mod solaris_base; mod thumb_base; mod uefi_msvc_base; @@ -671,6 +669,42 @@ impl ToJson for SanitizerSet { } } +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum FramePointer { + /// Forces the machine code generator to always preserve the frame pointers. + Always, + /// Forces the machine code generator to preserve the frame pointers except for the leaf + /// functions (i.e. those that don't call other functions). + NonLeaf, + /// Allows the machine code generator to omit the frame pointers. + /// + /// This option does not guarantee that the frame pointers will be omitted. + MayOmit, +} + +impl FromStr for FramePointer { + type Err = (); + fn from_str(s: &str) -> Result { + Ok(match s { + "always" => Self::Always, + "non-leaf" => Self::NonLeaf, + "may-omit" => Self::MayOmit, + _ => return Err(()), + }) + } +} + +impl ToJson for FramePointer { + fn to_json(&self) -> Json { + match *self { + Self::Always => "always", + Self::NonLeaf => "non-leaf", + Self::MayOmit => "may-omit", + } + .to_json() + } +} + macro_rules! supported_targets { ( $(($( $triple:literal, )+ $module:ident ),)+ ) => { $(mod $module;)+ @@ -769,6 +803,7 @@ supported_targets! { ("armv7-unknown-freebsd", armv7_unknown_freebsd), ("i686-unknown-freebsd", i686_unknown_freebsd), ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd), + ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd), ("x86_64-unknown-freebsd", x86_64_unknown_freebsd), ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly), @@ -905,6 +940,38 @@ supported_targets! { ("bpfel-unknown-none", bpfel_unknown_none), } +/// Warnings encountered when parsing the target `json`. +/// +/// Includes fields that weren't recognized and fields that don't have the expected type. +#[derive(Debug, PartialEq)] +pub struct TargetWarnings { + unused_fields: Vec, + incorrect_type: Vec, +} + +impl TargetWarnings { + pub fn empty() -> Self { + Self { unused_fields: Vec::new(), incorrect_type: Vec::new() } + } + + pub fn warning_messages(&self) -> Vec { + let mut warnings = vec![]; + if !self.unused_fields.is_empty() { + warnings.push(format!( + "target json file contains unused fields: {}", + self.unused_fields.join(", ") + )); + } + if !self.incorrect_type.is_empty() { + warnings.push(format!( + "target json file contains fields whose value doesn't have the correct json type: {}", + self.incorrect_type.join(", ") + )); + } + warnings + } +} + /// Everything `rustc` knows about how to compile for a specific target. /// /// Every field here must be specified, and has no default value. @@ -917,7 +984,7 @@ pub struct Target { /// Architecture to use for ABI considerations. Valid options include: "x86", /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others. pub arch: String, - /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM. + /// [Data layout](https://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM. pub data_layout: String, /// Optional settings with defaults. pub options: TargetOptions, @@ -958,6 +1025,9 @@ pub struct TargetOptions { pub os: String, /// Environment name to use for conditional compilation (`target_env`). Defaults to "". pub env: String, + /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"` + /// or `"eabihf"`. Defaults to "". + pub abi: String, /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown". pub vendor: String, /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed @@ -1035,8 +1105,8 @@ pub struct TargetOptions { pub tls_model: TlsModel, /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false. pub disable_redzone: bool, - /// Eliminate frame pointers from stack frames if possible. Defaults to true. - pub eliminate_frame_pointer: bool, + /// Frame pointer mode for this target. Defaults to `MayOmit`. + pub frame_pointer: FramePointer, /// Emit each function in its own section. Defaults to true. pub function_sections: bool, /// String to prepend to the name of every dynamic library. Defaults to "lib". @@ -1157,11 +1227,6 @@ pub struct TargetOptions { /// Panic strategy: "unwind" or "abort" pub panic_strategy: PanicStrategy, - /// A list of ABIs unsupported by the current target. Note that generic ABIs - /// are considered to be supported on all platforms and cannot be marked - /// unsupported. - pub unsupported_abis: Vec, - /// Whether or not linking dylibs to a static CRT is allowed. pub crt_static_allows_dylibs: bool, /// Whether or not the CRT is statically linked by default. @@ -1280,6 +1345,7 @@ impl Default for TargetOptions { c_int_width: "32".to_string(), os: "none".to_string(), env: String::new(), + abi: String::new(), vendor: "unknown".to_string(), linker_flavor: LinkerFlavor::Gcc, linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()), @@ -1297,7 +1363,7 @@ impl Default for TargetOptions { code_model: None, tls_model: TlsModel::GeneralDynamic, disable_redzone: false, - eliminate_frame_pointer: true, + frame_pointer: FramePointer::MayOmit, function_sections: true, dll_prefix: "lib".to_string(), dll_suffix: ".so".to_string(), @@ -1343,7 +1409,6 @@ impl Default for TargetOptions { max_atomic_width: None, atomic_cas: true, panic_strategy: PanicStrategy::Unwind, - unsupported_abis: vec![], crt_static_allows_dylibs: false, crt_static_default: false, crt_static_respected: false, @@ -1396,40 +1461,88 @@ impl Target { /// Given a function ABI, turn it into the correct ABI for this target. pub fn adjust_abi(&self, abi: Abi) -> Abi { match abi { - Abi::System { unwind } => { - if self.is_like_windows && self.arch == "x86" { - Abi::Stdcall { unwind } - } else { - Abi::C { unwind } - } - } - // These ABI kinds are ignored on non-x86 Windows targets. - // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions - // and the individual pages for __stdcall et al. - Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => { - if self.is_like_windows && self.arch != "x86" { Abi::C { unwind } } else { abi } - } - Abi::Fastcall | Abi::Vectorcall => { - if self.is_like_windows && self.arch != "x86" { - Abi::C { unwind: false } - } else { - abi - } - } - Abi::EfiApi => { - if self.arch == "x86_64" { - Abi::Win64 - } else { - Abi::C { unwind: false } - } + Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi), + Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => { + Abi::Stdcall { unwind } } + Abi::System { unwind } => Abi::C { unwind }, + Abi::EfiApi if self.arch == "x86_64" => Abi::Win64, + Abi::EfiApi => Abi::C { unwind: false }, - Abi::C { unwind } => self.default_adjusted_cabi.unwrap_or(Abi::C { unwind }), + // See commentary in `is_abi_supported`. + Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi, + Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind }, + Abi::Fastcall if self.arch == "x86" => abi, + Abi::Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => abi, + Abi::Fastcall | Abi::Vectorcall => Abi::C { unwind: false }, abi => abi, } } + /// Returns a None if the UNSUPPORTED_CALLING_CONVENTIONS lint should be emitted + pub fn is_abi_supported(&self, abi: Abi) -> Option { + use Abi::*; + Some(match abi { + Rust + | C { .. } + | System { .. } + | RustIntrinsic + | RustCall + | PlatformIntrinsic + | Unadjusted + | Cdecl + | EfiApi => true, + X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), + Aapcs | CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), + Win64 | SysV64 => self.arch == "x86_64", + PtxKernel => self.arch == "nvptx64", + Msp430Interrupt => self.arch == "msp430", + AmdGpuKernel => self.arch == "amdgcn", + AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr", + Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]), + // On windows these fall-back to platform native calling convention (C) when the + // architecture is not supported. + // + // This is I believe a historical accident that has occurred as part of Microsoft + // striving to allow most of the code to "just" compile when support for 64-bit x86 + // was added and then later again, when support for ARM architectures was added. + // + // This is well documented across MSDN. Support for this in Rust has been added in + // #54576. This makes much more sense in context of Microsoft's C++ than it does in + // Rust, but there isn't much leeway remaining here to change it back at the time this + // comment has been written. + // + // Following are the relevant excerpts from the MSDN documentation. + // + // > The __vectorcall calling convention is only supported in native code on x86 and + // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above. + // > ... + // > On ARM machines, __vectorcall is accepted and ignored by the compiler. + // + // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160 + // + // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler; + // + // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160 + // + // > In most cases, keywords or compiler switches that specify an unsupported + // > convention on a particular platform are ignored, and the platform default + // > convention is used. + // + // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions + Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall if self.is_like_windows => { + true + } + // Outside of Windows we want to only support these calling conventions for the + // architectures for which these calling conventions are actually well defined. + Stdcall { .. } | Fastcall | Thiscall { .. } if self.arch == "x86" => true, + Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true, + // Return a `None` for other cases so that we know to emit a future compat lint. + Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall => return None, + }) + } + /// Minimum integer size in bits that this target can perform atomic /// operations on. pub fn min_atomic_width(&self) -> u64 { @@ -1442,12 +1555,8 @@ impl Target { self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into()) } - pub fn is_abi_supported(&self, abi: Abi) -> bool { - abi.generic() || !self.unsupported_abis.contains(&abi) - } - /// Loads a target descriptor from a JSON object. - pub fn from_json(obj: Json) -> Result { + pub fn from_json(mut obj: Json) -> Result<(Target, TargetWarnings), String> { // While ugly, this code must remain this way to retain // compatibility with existing JSON fields and the internal // expected naming of the Target and TargetOptions structs. @@ -1455,10 +1564,9 @@ impl Target { // are round-tripped through this code to catch cases where // the JSON parser is not updated to match the structs. - let get_req_field = |name: &str| { - obj.find(name) - .and_then(Json::as_string) - .map(str::to_string) + let mut get_req_field = |name: &str| { + obj.remove_key(name) + .and_then(|j| Json::as_string(&j).map(str::to_string)) .ok_or_else(|| format!("Field {} in target specification is required", name)) }; @@ -1472,28 +1580,30 @@ impl Target { options: Default::default(), }; + let mut incorrect_type = vec![]; + macro_rules! key { ($key_name:ident) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.find(&name).and_then(Json::as_string) { - base.$key_name = s.to_string(); + if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) { + base.$key_name = s; } } ); ($key_name:ident = $json_name:expr) => ( { let name = $json_name; - if let Some(s) = obj.find(&name).and_then(Json::as_string) { - base.$key_name = s.to_string(); + if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) { + base.$key_name = s; } } ); ($key_name:ident, bool) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.find(&name).and_then(Json::as_boolean) { + if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_boolean(&j)) { base.$key_name = s; } } ); ($key_name:ident, Option) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.find(&name).and_then(Json::as_u64) { + if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) { if s < 1 || s > 5 { return Err("Not a valid DWARF version number".to_string()); } @@ -1502,13 +1612,13 @@ impl Target { } ); ($key_name:ident, Option) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.find(&name).and_then(Json::as_u64) { + if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) { base.$key_name = Some(s); } } ); ($key_name:ident, MergeFunctions) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::() { Ok(mergefunc) => base.$key_name = mergefunc, _ => return Some(Err(format!("'{}' is not a valid value for \ @@ -1521,7 +1631,7 @@ impl Target { } ); ($key_name:ident, RelocModel) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::() { Ok(relocation_model) => base.$key_name = relocation_model, _ => return Some(Err(format!("'{}' is not a valid relocation model. \ @@ -1533,7 +1643,7 @@ impl Target { } ); ($key_name:ident, CodeModel) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::() { Ok(code_model) => base.$key_name = Some(code_model), _ => return Some(Err(format!("'{}' is not a valid code model. \ @@ -1545,7 +1655,7 @@ impl Target { } ); ($key_name:ident, TlsModel) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::() { Ok(tls_model) => base.$key_name = tls_model, _ => return Some(Err(format!("'{}' is not a valid TLS model. \ @@ -1557,7 +1667,7 @@ impl Target { } ); ($key_name:ident, PanicStrategy) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s { "unwind" => base.$key_name = PanicStrategy::Unwind, "abort" => base.$key_name = PanicStrategy::Abort, @@ -1570,7 +1680,7 @@ impl Target { } ); ($key_name:ident, RelroLevel) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::() { Ok(level) => base.$key_name = level, _ => return Some(Err(format!("'{}' is not a valid value for \ @@ -1582,7 +1692,7 @@ impl Target { } ); ($key_name:ident, SplitDebuginfo) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::() { Ok(level) => base.$key_name = level, _ => return Some(Err(format!("'{}' is not a valid value for \ @@ -1594,23 +1704,31 @@ impl Target { } ); ($key_name:ident, list) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(v) = obj.find(&name).and_then(Json::as_array) { - base.$key_name = v.iter() - .map(|a| a.as_string().unwrap().to_string()) - .collect(); + if let Some(j) = obj.remove_key(&name){ + if let Some(v) = Json::as_array(&j) { + base.$key_name = v.iter() + .map(|a| a.as_string().unwrap().to_string()) + .collect(); + } else { + incorrect_type.push(name) + } } } ); ($key_name:ident, opt_list) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(v) = obj.find(&name).and_then(Json::as_array) { - base.$key_name = Some(v.iter() - .map(|a| a.as_string().unwrap().to_string()) - .collect()); + if let Some(j) = obj.remove_key(&name) { + if let Some(v) = Json::as_array(&j) { + base.$key_name = Some(v.iter() + .map(|a| a.as_string().unwrap().to_string()) + .collect()); + } else { + incorrect_type.push(name) + } } } ); ($key_name:ident, optional) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.find(&name[..]) { + if let Some(o) = obj.remove_key(&name[..]) { base.$key_name = o .as_string() .map(|s| s.to_string() ); @@ -1618,7 +1736,7 @@ impl Target { } ); ($key_name:ident, LldFlavor) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { if let Some(flavor) = LldFlavor::from_str(&s) { base.$key_name = flavor; } else { @@ -1632,7 +1750,7 @@ impl Target { } ); ($key_name:ident, LinkerFlavor) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match LinkerFlavor::from_str(s) { Some(linker_flavor) => base.$key_name = linker_flavor, _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \ @@ -1643,7 +1761,7 @@ impl Target { } ); ($key_name:ident, StackProbeType) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| match StackProbeType::from_json(o) { + obj.remove_key(&name[..]).and_then(|o| match StackProbeType::from_json(&o) { Ok(v) => { base.$key_name = v; Some(Ok(())) @@ -1655,25 +1773,29 @@ impl Target { } ); ($key_name:ident, SanitizerSet) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_array()).and_then(|a| { - for s in a { - base.$key_name |= match s.as_string() { - Some("address") => SanitizerSet::ADDRESS, - Some("leak") => SanitizerSet::LEAK, - Some("memory") => SanitizerSet::MEMORY, - Some("thread") => SanitizerSet::THREAD, - Some("hwaddress") => SanitizerSet::HWADDRESS, - Some(s) => return Some(Err(format!("unknown sanitizer {}", s))), - _ => return Some(Err(format!("not a string: {:?}", s))), - }; + if let Some(o) = obj.remove_key(&name[..]) { + if let Some(a) = o.as_array() { + for s in a { + base.$key_name |= match s.as_string() { + Some("address") => SanitizerSet::ADDRESS, + Some("leak") => SanitizerSet::LEAK, + Some("memory") => SanitizerSet::MEMORY, + Some("thread") => SanitizerSet::THREAD, + Some("hwaddress") => SanitizerSet::HWADDRESS, + Some(s) => return Err(format!("unknown sanitizer {}", s)), + _ => return Err(format!("not a string: {:?}", s)), + }; + } + } else { + incorrect_type.push(name) } - Some(Ok(())) - }).unwrap_or(Ok(())) + } + Ok::<(), String>(()) } ); ($key_name:ident, crt_objects_fallback) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match s.parse::() { Ok(fallback) => base.$key_name = Some(fallback), _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \ @@ -1684,7 +1806,7 @@ impl Target { } ); ($key_name:ident, link_objects) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(val) = obj.find(&name[..]) { + if let Some(val) = obj.remove_key(&name[..]) { let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ JSON object with fields per CRT object kind.", name))?; let mut args = CrtObjects::new(); @@ -1712,7 +1834,7 @@ impl Target { } ); ($key_name:ident, link_args) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(val) = obj.find(&name[..]) { + if let Some(val) = obj.remove_key(&name[..]) { let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ JSON object with fields per linker-flavor.", name))?; let mut args = LinkArgs::new(); @@ -1739,22 +1861,26 @@ impl Target { } ); ($key_name:ident, env) => ( { let name = (stringify!($key_name)).replace("_", "-"); - if let Some(a) = obj.find(&name[..]).and_then(|o| o.as_array()) { - for o in a { - if let Some(s) = o.as_string() { - let p = s.split('=').collect::>(); - if p.len() == 2 { - let k = p[0].to_string(); - let v = p[1].to_string(); - base.$key_name.push((k, v)); + if let Some(o) = obj.remove_key(&name[..]) { + if let Some(a) = o.as_array() { + for o in a { + if let Some(s) = o.as_string() { + let p = s.split('=').collect::>(); + if p.len() == 2 { + let k = p[0].to_string(); + let v = p[1].to_string(); + base.$key_name.push((k, v)); + } } } + } else { + incorrect_type.push(name) } } } ); ($key_name:ident, Option) => ( { let name = (stringify!($key_name)).replace("_", "-"); - obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| { match lookup_abi(s) { Some(abi) => base.$key_name = Some(abi), _ => return Some(Err(format!("'{}' is not a valid value for abi", s))), @@ -1763,24 +1889,41 @@ impl Target { })).unwrap_or(Ok(())) } ); ($key_name:ident, TargetFamilies) => ( { - let value = obj.find("target-family"); - if let Some(v) = value.and_then(Json::as_array) { - base.$key_name = v.iter() - .map(|a| a.as_string().unwrap().to_string()) - .collect(); - } else if let Some(v) = value.and_then(Json::as_string) { - base.$key_name = vec![v.to_string()]; + if let Some(value) = obj.remove_key("target-family") { + if let Some(v) = Json::as_array(&value) { + base.$key_name = v.iter() + .map(|a| a.as_string().unwrap().to_string()) + .collect(); + } else if let Some(v) = Json::as_string(&value) { + base.$key_name = vec![v.to_string()]; + } } } ); } - if let Some(s) = obj.find("target-endian").and_then(Json::as_string) { - base.endian = s.parse()?; + if let Some(j) = obj.remove_key("target-endian") { + if let Some(s) = Json::as_string(&j) { + base.endian = s.parse()?; + } else { + incorrect_type.push("target-endian".to_string()) + } } + + if let Some(fp) = obj.remove_key("frame-pointer") { + if let Some(s) = Json::as_string(&fp) { + base.frame_pointer = s + .parse() + .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?; + } else { + incorrect_type.push("frame-pointer".to_string()) + } + } + key!(is_builtin, bool); key!(c_int_width = "target-c-int-width"); key!(os); key!(env); + key!(abi); key!(vendor); key!(linker_flavor, LinkerFlavor)?; key!(linker, optional); @@ -1808,7 +1951,6 @@ impl Target { key!(code_model, CodeModel)?; key!(tls_model, TlsModel)?; key!(disable_redzone, bool); - key!(eliminate_frame_pointer, bool); key!(function_sections, bool); key!(dll_prefix); key!(dll_suffix); @@ -1873,35 +2015,16 @@ impl Target { key!(supported_sanitizers, SanitizerSet)?; key!(default_adjusted_cabi, Option)?; - // NB: The old name is deprecated, but support for it is retained for - // compatibility. - for name in ["abi-blacklist", "unsupported-abis"].iter() { - if let Some(array) = obj.find(name).and_then(Json::as_array) { - for name in array.iter().filter_map(|abi| abi.as_string()) { - match lookup_abi(name) { - Some(abi) => { - if abi.generic() { - return Err(format!( - "The ABI \"{}\" is considered to be supported on all \ - targets and cannot be marked unsupported", - abi - )); - } - - base.unsupported_abis.push(abi) - } - None => { - return Err(format!( - "Unknown ABI \"{}\" in target specification", - name - )); - } - } - } - } + if base.is_builtin { + // This can cause unfortunate ICEs later down the line. + return Err(format!("may not set is_builtin for targets not built-in")); } - - Ok(base) + // Each field should have been read using `Json::remove_key` so any keys remaining are unused. + let remaining_keys = obj.as_object().ok_or("Expected JSON object for target")?.keys(); + Ok(( + base, + TargetWarnings { unused_fields: remaining_keys.cloned().collect(), incorrect_type }, + )) } /// Search for a JSON file specifying the given target triple. @@ -1913,12 +2036,15 @@ impl Target { /// /// The error string could come from any of the APIs called, including filesystem access and /// JSON decoding. - pub fn search(target_triple: &TargetTriple, sysroot: &PathBuf) -> Result { + pub fn search( + target_triple: &TargetTriple, + sysroot: &PathBuf, + ) -> Result<(Target, TargetWarnings), String> { use rustc_serialize::json; use std::env; use std::fs; - fn load_file(path: &Path) -> Result { + fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> { let contents = fs::read(path).map_err(|e| e.to_string())?; let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?; Target::from_json(obj) @@ -1928,7 +2054,7 @@ impl Target { TargetTriple::TargetTriple(ref target_triple) => { // check if triple is in list of built-in targets if let Some(t) = load_builtin(target_triple) { - return Ok(t); + return Ok((t, TargetWarnings::empty())); } // search for a file named `target_triple`.json in RUST_TARGET_PATH @@ -2035,6 +2161,7 @@ impl ToJson for Target { target_option_val!(c_int_width, "target-c-int-width"); target_option_val!(os); target_option_val!(env); + target_option_val!(abi); target_option_val!(vendor); target_option_val!(linker_flavor); target_option_val!(linker); @@ -2062,7 +2189,7 @@ impl ToJson for Target { target_option_val!(code_model); target_option_val!(tls_model); target_option_val!(disable_redzone); - target_option_val!(eliminate_frame_pointer); + target_option_val!(frame_pointer); target_option_val!(function_sections); target_option_val!(dll_prefix); target_option_val!(dll_suffix); @@ -2130,17 +2257,6 @@ impl ToJson for Target { d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); } - if default.unsupported_abis != self.unsupported_abis { - d.insert( - "unsupported-abis".to_string(), - self.unsupported_abis - .iter() - .map(|&name| Abi::name(name).to_json()) - .collect::>() - .to_json(), - ); - } - Json::Object(d) } } diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs index 97960a75b0..083262cf35 100644 --- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs @@ -1,4 +1,3 @@ -use crate::spec::abi::Abi; use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { @@ -45,25 +44,6 @@ pub fn target() -> Target { // produce kernel functions that call other kernel functions. // This behavior is not supported by PTX ISA. merge_functions: MergeFunctions::Disabled, - - // FIXME: enable compilation tests for the target and - // create the tests for this. - unsupported_abis: vec![ - Abi::Cdecl, - Abi::Stdcall { unwind: false }, - Abi::Stdcall { unwind: true }, - Abi::Fastcall, - Abi::Vectorcall, - Abi::Thiscall { unwind: false }, - Abi::Thiscall { unwind: true }, - Abi::Aapcs, - Abi::Win64, - Abi::SysV64, - Abi::Msp430Interrupt, - Abi::X86Interrupt, - Abi::AmdGpuKernel, - ], - ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/openbsd_base.rs index 29b415e772..70e9e4aed9 100644 --- a/compiler/rustc_target/src/spec/openbsd_base.rs +++ b/compiler/rustc_target/src/spec/openbsd_base.rs @@ -1,4 +1,4 @@ -use crate::spec::{RelroLevel, TargetOptions}; +use crate::spec::{FramePointer, RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { TargetOptions { @@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, abi_return_struct_as_int: true, position_independent_executables: true, - eliminate_frame_pointer: false, // FIXME 43575 + frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit... relro_level: RelroLevel::Full, dwarf_version: Some(2), ..Default::default() diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs new file mode 100644 index 0000000000..283e9f744c --- /dev/null +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs @@ -0,0 +1,16 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions}; + +pub fn target() -> Target { + let mut base = super::freebsd_base::opts(); + base.cpu = "ppc64le".to_string(); + base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string()); + base.max_atomic_width = Some(64); + + Target { + llvm_target: "powerpc64le-unknown-freebsd".to_string(), + pointer_width: 64, + data_layout: "e-m:e-i64:64-n32:64".to_string(), + arch: "powerpc64".to_string(), + options: TargetOptions { mcount: "_mcount".to_string(), ..base }, + } +} 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 8d8f746f97..362d8a104e 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs @@ -11,6 +11,11 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), - options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, + options: TargetOptions { + abi: "spe".to_string(), + endian: Endian::Big, + mcount: "_mcount".to_string(), + ..base + }, } } 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 215f1a3622..a2b85f7dd8 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs @@ -13,6 +13,7 @@ pub fn target() -> Target { data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), arch: "powerpc".to_string(), options: TargetOptions { + abi: "spe".to_string(), endian: Endian::Big, // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2 features: "+secure-plt,+msync".to_string(), diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs index cf5e0201d0..a9cdad1a8b 100644 --- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs @@ -7,7 +7,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(), arch: "riscv32".to_string(), options: TargetOptions { - unsupported_abis: super::riscv_base::unsupported_abis(), code_model: Some(CodeModel::Medium), cpu: "generic-rv32".to_string(), features: "+m,+a,+f,+d,+c".to_string(), diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs index e5fbd09297..a64a82d55b 100644 --- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs @@ -7,7 +7,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(), arch: "riscv32".to_string(), options: TargetOptions { - unsupported_abis: super::riscv_base::unsupported_abis(), code_model: Some(CodeModel::Medium), cpu: "generic-rv32".to_string(), features: "+m,+a,+f,+d,+c".to_string(), 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 88a22f25ff..16d37218f4 100644 --- a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs @@ -18,7 +18,6 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, - unsupported_abis: super::riscv_base::unsupported_abis(), eh_frame_header: false, ..Default::default() }, 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 b406eec1e7..b53bae6cb5 100644 --- a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs @@ -18,7 +18,6 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, - unsupported_abis: super::riscv_base::unsupported_abis(), eh_frame_header: false, ..Default::default() }, 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 89d760e082..9a23def199 100644 --- a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs @@ -19,7 +19,6 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, emit_debug_gdb_scripts: false, - unsupported_abis: super::riscv_base::unsupported_abis(), eh_frame_header: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs index 84f28413fc..02d44b5ed7 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs @@ -7,7 +7,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(), arch: "riscv64".to_string(), options: TargetOptions { - unsupported_abis: super::riscv_base::unsupported_abis(), code_model: Some(CodeModel::Medium), cpu: "generic-rv64".to_string(), features: "+m,+a,+f,+d,+c".to_string(), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs index 0232b15e8c..3754750e48 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs @@ -7,7 +7,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(), arch: "riscv64".to_string(), options: TargetOptions { - unsupported_abis: super::riscv_base::unsupported_abis(), code_model: Some(CodeModel::Medium), cpu: "generic-rv64".to_string(), features: "+m,+a,+f,+d,+c".to_string(), 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 481bce05a0..f527a6cd26 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs @@ -20,7 +20,6 @@ pub fn target() -> Target { relocation_model: RelocModel::Static, code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, - unsupported_abis: super::riscv_base::unsupported_abis(), eh_frame_header: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs index 3e4afd446d..8b1ba88e67 100644 --- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs @@ -19,7 +19,6 @@ pub fn target() -> Target { relocation_model: RelocModel::Static, code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, - unsupported_abis: super::riscv_base::unsupported_abis(), eh_frame_header: false, ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/riscv_base.rs b/compiler/rustc_target/src/spec/riscv_base.rs deleted file mode 100644 index 5bcbb2e621..0000000000 --- a/compiler/rustc_target/src/spec/riscv_base.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::spec::abi::Abi; - -// All the calling conventions trigger an assertion(Unsupported calling -// convention) in llvm on RISCV -pub fn unsupported_abis() -> Vec { - vec![ - Abi::Cdecl, - Abi::Stdcall { unwind: false }, - Abi::Stdcall { unwind: true }, - Abi::Fastcall, - Abi::Vectorcall, - Abi::Thiscall { unwind: false }, - Abi::Thiscall { unwind: true }, - Abi::Aapcs, - Abi::Win64, - Abi::SysV64, - Abi::PtxKernel, - Abi::Msp430Interrupt, - Abi::X86Interrupt, - Abi::AmdGpuKernel, - ] -} diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index f4de8bc0a5..6730319dcf 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -3,7 +3,7 @@ use super::super::*; // Test target self-consistency and JSON encoding/decoding roundtrip. pub(super) fn test_target(target: Target) { target.check_consistency(); - assert_eq!(Target::from_json(target.to_json()), Ok(target)); + assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target)); } impl Target { diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs index ec24807fec..bac1203980 100644 --- a/compiler/rustc_target/src/spec/thumb_base.rs +++ b/compiler/rustc_target/src/spec/thumb_base.rs @@ -27,7 +27,8 @@ // differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of // build scripts / gcc flags. -use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions}; +use crate::spec::TargetOptions; +use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel}; pub fn opts() -> TargetOptions { // See rust-lang/rfcs#1645 for a discussion about these defaults @@ -42,7 +43,6 @@ pub fn opts() -> TargetOptions { // Similarly, one almost always never wants to use relocatable code because of the extra // costs it involves. relocation_model: RelocModel::Static, - unsupported_abis: super::arm_base::unsupported_abis(), // When this section is added a volatile load to its start address is also generated. This // volatile load is a footgun as it can end up loading an invalid memory address, depending // on how the user set up their linker scripts. This section adds pretty printer for stuff @@ -52,7 +52,7 @@ pub fn opts() -> TargetOptions { emit_debug_gdb_scripts: false, // LLVM is eager to trash the link register when calling `noreturn` functions, which // breaks debugging. Preserve LR by default to prevent that from happening. - eliminate_frame_pointer: false, + frame_pointer: FramePointer::Always, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs index f996009f83..f86efd5d0f 100644 --- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs @@ -26,6 +26,7 @@ pub fn target() -> Target { */ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), options: TargetOptions { + abi: "eabi".to_string(), linker_flavor: LinkerFlavor::Ld, linker: Some("arm-none-eabi-ld".to_string()), diff --git a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs index 11c8bf4634..40e3281060 100644 --- a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs @@ -10,6 +10,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { + abi: "eabi".to_string(), // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them // with +strict-align. features: "+strict-align".to_string(), 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 1232daa577..369e6cd5e9 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs @@ -2,7 +2,6 @@ use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions} pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); - // Prevent error LNK2013: BRANCH24(T) fixup overflow // The LBR optimization tries to eliminate branch islands, // but if the displacement is larger than can fit @@ -17,20 +16,17 @@ pub fn target() -> Target { .or_default() .push(pre_link_args_msvc); - // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is - // implemented for windows/arm in LLVM - base.panic_strategy = PanicStrategy::Abort; - Target { llvm_target: "thumbv7a-pc-windows-msvc".to_string(), pointer_width: 32, data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { features: "+vfp3,+neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), + // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is + // implemented for windows/arm in LLVM + panic_strategy: PanicStrategy::Abort, ..base }, } diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs index e6a59f015c..b44c008500 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs @@ -1,14 +1,6 @@ use crate::spec::{PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::windows_uwp_msvc_base::opts(); - base.max_atomic_width = Some(64); - base.has_elf_tls = true; - - // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is - // implemented for windows/arm in LLVM - base.panic_strategy = PanicStrategy::Abort; - Target { llvm_target: "thumbv7a-pc-windows-msvc".to_string(), pointer_width: 32, @@ -16,8 +8,12 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { features: "+vfp3,+neon".to_string(), - unsupported_abis: super::arm_base::unsupported_abis(), - ..base + max_atomic_width: Some(64), + has_elf_tls: true, + // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is + // implemented for windows/arm in LLVM + panic_strategy: PanicStrategy::Abort, + ..super::windows_uwp_msvc_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs index 141eb7e78b..107474a86b 100644 --- a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs @@ -18,6 +18,10 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { max_atomic_width: Some(32), ..super::thumb_base::opts() }, + options: TargetOptions { + abi: "eabi".to_string(), + max_atomic_width: Some(32), + ..super::thumb_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs index f5bd054f85..65fc0db652 100644 --- a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs @@ -18,6 +18,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { + abi: "eabihf".to_string(), // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the // Cortex-M7 (vfp5) // `-d32` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers diff --git a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs index 7af28cd9c9..ff939348c3 100644 --- a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs @@ -9,6 +9,10 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { max_atomic_width: Some(32), ..super::thumb_base::opts() }, + options: TargetOptions { + abi: "eabi".to_string(), + max_atomic_width: Some(32), + ..super::thumb_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs index 58b0a9d220..fcb7b5d718 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs @@ -10,15 +10,17 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions}; pub fn target() -> Target { let mut base = super::android_base::opts(); - base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(); - base.max_atomic_width = Some(64); base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string()); - Target { llvm_target: "armv7-none-linux-android".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base }, + options: TargetOptions { + abi: "eabi".to_string(), + features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), + max_atomic_width: Some(64), + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs index 12d816d095..9d34d9ac87 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs @@ -7,19 +7,17 @@ use crate::spec::{Target, TargetOptions}; // https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf pub fn target() -> Target { - let base = super::linux_gnu_base::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".to_string(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { + abi: "eabihf".to_string(), // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), - ..base + ..super::linux_gnu_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs index 020de87147..4e339cbd6b 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs @@ -7,7 +7,6 @@ use crate::spec::{Target, TargetOptions}; // https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf pub fn target() -> Target { - let base = super::linux_musl_base::opts(); Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and LLVM @@ -20,11 +19,11 @@ pub fn target() -> Target { // Most of these settings are copied from the thumbv7neon_unknown_linux_gnueabihf // target. options: TargetOptions { + abi: "eabihf".to_string(), features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(), max_atomic_width: Some(64), - unsupported_abis: super::arm_base::unsupported_abis(), mcount: "\u{1}mcount".to_string(), - ..base + ..super::linux_musl_base::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs index a2200bc64e..ef0f52d219 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs @@ -10,6 +10,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { + abi: "eabi".to_string(), // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them // with +strict-align. features: "+strict-align".to_string(), diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs index 67cdbab486..dbd184debc 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs @@ -10,6 +10,10 @@ pub fn target() -> Target { data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), arch: "arm".to_string(), - options: TargetOptions { max_atomic_width: Some(32), ..super::thumb_base::opts() }, + options: TargetOptions { + abi: "eabi".to_string(), + max_atomic_width: Some(32), + ..super::thumb_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs index 49748f5ec6..3caf705421 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs @@ -11,6 +11,7 @@ pub fn target() -> Target { arch: "arm".to_string(), options: TargetOptions { + abi: "eabihf".to_string(), // If the Floating Point extension is implemented in the Cortex-M33 // processor, the Cortex-M33 Technical Reference Manual states that // the FPU uses the FPv5 architecture, single-precision instructions 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 67d1be399b..86df816f10 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs @@ -25,6 +25,7 @@ pub fn opts() -> TargetOptions { late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs); TargetOptions { + abi: "uwp".to_string(), vendor: "uwp".to_string(), executables: false, limit_rdylib_exports: false, diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs index b3fa5c22f9..7b56b468c2 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs +++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs @@ -3,6 +3,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, TargetOptions}; pub fn opts() -> TargetOptions { let mut opts = super::windows_msvc_base::opts(); + opts.abi = "uwp".to_string(); opts.vendor = "uwp".to_string(); let pre_link_args_msvc = vec!["/APPCONTAINER".to_string(), "mincore.lib".to_string()]; opts.pre_link_args.entry(LinkerFlavor::Msvc).or_default().extend(pre_link_args_msvc.clone()); 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 dc7597fe7b..60fd42970c 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,10 +1,11 @@ -use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::TargetOptions; +use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); base.cpu = "core2".to_string(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b - base.eliminate_frame_pointer = false; + base.frame_pointer = FramePointer::Always; base.pre_link_args.insert( LinkerFlavor::Gcc, vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()], 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 06eb33d8d8..59cd56ebcd 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 @@ -55,6 +55,7 @@ pub fn target() -> Target { os: "unknown".into(), env: "sgx".into(), vendor: "fortanix".into(), + abi: "fortanix".into(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), executables: true, linker: Some("rust-lld".to_owned()), 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 7b77ad668c..1ffaa9b78c 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 @@ -3,6 +3,7 @@ use crate::spec::{LinkerFlavor, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); base.cpu = "x86-64".to_string(); + base.abi = "x32".to_string(); base.max_atomic_width = Some(64); base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs index b7dcce5f89..be0e62bea0 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs @@ -5,7 +5,7 @@ // The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features. -use crate::spec::{CodeModel, Target}; +use crate::spec::Target; pub fn target() -> Target { let mut base = super::uefi_msvc_base::opts(); @@ -19,15 +19,11 @@ pub fn target() -> Target { // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so // far. + // // If you initialize FP units yourself, you can override these flags with custom linker // arguments, thus giving you access to full MMX/SSE acceleration. base.features = "-mmx,-sse,+soft-float".to_string(); - // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell - // LLVM to expect code to reference any address in the address-space. The "large" code-model - // places no locality-restrictions, so it fits well here. - base.code_model = Some(CodeModel::Large); - Target { llvm_target: "x86_64-unknown-windows".to_string(), pointer_width: 64, diff --git a/compiler/rustc_target/src/tests.rs b/compiler/rustc_target/src/tests.rs new file mode 100644 index 0000000000..3a737b3355 --- /dev/null +++ b/compiler/rustc_target/src/tests.rs @@ -0,0 +1,59 @@ +use crate::spec::Target; +use rustc_serialize::json::Json; +use std::str::FromStr; + +#[test] +fn report_unused_fields() { + let json = Json::from_str( + r#" + { + "arch": "powerpc64", + "data-layout": "e-m:e-i64:64-n32:64", + "llvm-target": "powerpc64le-elf", + "target-pointer-width": "64", + "code-mode": "foo" + } + "#, + ) + .unwrap(); + let warnings = Target::from_json(json).unwrap().1; + assert_eq!(warnings.warning_messages().len(), 1); + assert!(warnings.warning_messages().join("\n").contains("code-mode")); +} + +#[test] +fn report_incorrect_json_type() { + let json = Json::from_str( + r#" + { + "arch": "powerpc64", + "data-layout": "e-m:e-i64:64-n32:64", + "llvm-target": "powerpc64le-elf", + "target-pointer-width": "64", + "link-env-remove": "foo" + } + "#, + ) + .unwrap(); + let warnings = Target::from_json(json).unwrap().1; + assert_eq!(warnings.warning_messages().len(), 1); + assert!(warnings.warning_messages().join("\n").contains("link-env-remove")); +} + +#[test] +fn no_warnings_for_valid_target() { + let json = Json::from_str( + r#" + { + "arch": "powerpc64", + "data-layout": "e-m:e-i64:64-n32:64", + "llvm-target": "powerpc64le-elf", + "target-pointer-width": "64", + "link-env-remove": ["foo"] + } + "#, + ) + .unwrap(); + let warnings = Target::from_json(json).unwrap().1; + assert_eq!(warnings.warning_messages().len(), 0); +} diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index ac2e0ebae3..969962e55b 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { } // If we have reached the recursion limit, error gracefully. - if !tcx.sess.recursion_limit().value_within_limit(self.state.steps.len()) { + if !tcx.recursion_limit().value_within_limit(self.state.steps.len()) { if !self.silence_errors { report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty); } @@ -217,7 +217,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { // We've reached the recursion limit, error gracefully. - let suggested_limit = tcx.sess.recursion_limit() * 2; + let suggested_limit = tcx.recursion_limit() * 2; let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty); let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg); let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index a9ffb5542b..ea074192d2 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,13 +1,18 @@ +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::outlives_bounds::InferCtxtExt as _; use crate::traits::{self, TraitEngine, TraitEngineExt}; use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::traits::ObligationCause; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse}; use rustc_middle::traits::query::Fallible; +use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::ToPredicate; +use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_span::{Span, DUMMY_SP}; @@ -25,15 +30,28 @@ pub trait InferCtxtExt<'tcx> { fn partially_normalize_associated_types_in( &self, - span: Span, - body_id: hir::HirId, + cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, value: T, ) -> InferOk<'tcx, T> where T: TypeFoldable<'tcx>; -} + /// Check whether a `ty` implements given trait(trait_def_id). + /// The inputs are: + /// + /// - the def-id of the trait + /// - the self type + /// - the *other* type parameters of the trait, excluding the self-type + /// - the parameter environment + fn type_implements_trait( + &self, + trait_def_id: DefId, + ty: Ty<'tcx>, + params: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> traits::EvaluationResult; +} impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { fn type_is_copy_modulo_regions( &self, @@ -60,8 +78,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// new obligations that must further be processed. fn partially_normalize_associated_types_in( &self, - span: Span, - body_id: hir::HirId, + cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, value: T, ) -> InferOk<'tcx, T> @@ -70,7 +87,6 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { { debug!("partially_normalize_associated_types_in(value={:?})", value); let mut selcx = traits::SelectionContext::new(self); - let cause = ObligationCause::misc(span, body_id); let traits::Normalized { value, obligations } = traits::normalize(&mut selcx, param_env, cause, value); debug!( @@ -79,6 +95,30 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { ); InferOk { value, obligations } } + + fn type_implements_trait( + &self, + trait_def_id: DefId, + ty: Ty<'tcx>, + params: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> traits::EvaluationResult { + debug!( + "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}", + trait_def_id, ty, params, param_env + ); + + let trait_ref = + ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) }; + + let obligation = traits::Obligation { + cause: traits::ObligationCause::dummy(), + param_env, + recursion_depth: 0, + predicate: trait_ref.without_const().to_predicate(self.tcx), + }; + self.evaluate_obligation_no_overflow(&obligation) + } } pub trait InferCtxtBuilderExt<'tcx> { diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 89ec211f26..95c81c5c72 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1,11 +1,10 @@ use crate::infer::InferCtxtExt as _; -use crate::traits::{self, PredicateObligation}; +use crate::traits::{self, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::Node; use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::free_regions::FreeRegionRelations; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -84,6 +83,7 @@ pub struct OpaqueTypeDecl<'tcx> { } /// Whether member constraints should be generated for all opaque types +#[derive(Debug)] pub enum GenerateMemberConstraints { /// The default, used by typeck WhenRequired, @@ -355,8 +355,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { opaque_types: &OpaqueTypeMap<'tcx>, free_region_relations: &FRR, ) { - debug!("constrain_opaque_types()"); - for &(opaque_type_key, opaque_defn) in opaque_types { self.constrain_opaque_type( opaque_type_key, @@ -368,6 +366,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } /// See `constrain_opaque_types` for documentation. + #[instrument(level = "debug", skip(self, free_region_relations))] fn constrain_opaque_type>( &self, opaque_type_key: OpaqueTypeKey<'tcx>, @@ -377,15 +376,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) { let def_id = opaque_type_key.def_id; - debug!("constrain_opaque_type()"); - debug!("constrain_opaque_type: def_id={:?}", def_id); - debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn); - let tcx = self.tcx; let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty); - debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty); + debug!(?concrete_ty); let first_own_region = match opaque_defn.origin { hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { @@ -398,14 +393,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // type foo::<'p0..'pn>::Foo<'q0..'qm> // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. // - // For these types we onlt iterate over `'l0..lm` below. + // For these types we only iterate over `'l0..lm` below. tcx.generics_of(def_id).parent_count } // These opaque type inherit all lifetime parameters from their // parent, so we have to check them all. - hir::OpaqueTyOrigin::Binding - | hir::OpaqueTyOrigin::TyAlias - | hir::OpaqueTyOrigin::Misc => 0, + hir::OpaqueTyOrigin::TyAlias => 0, }; let span = tcx.def_span(def_id); @@ -413,10 +406,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // If there are required region bounds, we can use them. if opaque_defn.has_required_region_bounds { let bounds = tcx.explicit_item_bounds(def_id); - debug!("constrain_opaque_type: predicates: {:#?}", bounds); + debug!("{:#?}", bounds); let bounds: Vec<_> = bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect(); - debug!("constrain_opaque_type: bounds={:#?}", bounds); + debug!("{:#?}", bounds); let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs); let required_region_bounds = @@ -455,8 +448,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; // Compute the least upper bound of it with the other regions. - debug!("constrain_opaque_types: least_region={:?}", least_region); - debug!("constrain_opaque_types: subst_region={:?}", subst_region); + debug!(?least_region); + debug!(?subst_region); match least_region { None => least_region = Some(subst_region), Some(lr) => { @@ -487,7 +480,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } let least_region = least_region.unwrap_or(tcx.lifetimes.re_static); - debug!("constrain_opaque_types: least_region={:?}", least_region); + debug!(?least_region); if let GenerateMemberConstraints::IfNoStaticBound = mode { if least_region != tcx.lifetimes.re_static { @@ -569,6 +562,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// - `substs`, the substs used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` + #[instrument(skip(self))] fn infer_opaque_definition_from_instantiation( &self, opaque_type_key: OpaqueTypeKey<'tcx>, @@ -577,11 +571,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let OpaqueTypeKey { def_id, substs } = opaque_type_key; - debug!( - "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})", - def_id, instantiated_ty - ); - // 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 @@ -589,6 +578,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // `impl Trait` return type, resulting in the parameters // shifting. let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); + debug!(?id_substs); let map: FxHashMap, GenericArg<'tcx>> = substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect(); @@ -603,7 +593,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { instantiated_ty, span, )); - debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty); + debug!(?definition_ty); definition_ty } @@ -858,7 +848,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { self.tcx.mk_generator(def_id, substs, movability) } - ty::Param(..) => { + 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 @@ -866,6 +856,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { 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( @@ -932,8 +923,8 @@ struct Instantiator<'a, 'tcx> { } impl<'a, 'tcx> Instantiator<'a, 'tcx> { + #[instrument(skip(self))] fn instantiate_opaque_types_in_map>(&mut self, value: T) -> T { - debug!("instantiate_opaque_types_in_map(value={:?})", value); let tcx = self.infcx.tcx; value.fold_with(&mut BottomUpFolder { tcx, @@ -982,8 +973,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) }; - let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) { - Some(Node::Item(item)) => match item.kind { + let (in_definition_scope, origin) = + match tcx.hir().expect_item(opaque_hir_id).kind { // Anonymous `impl Trait` hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(parent), @@ -999,13 +990,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id), origin, ), - _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc), - }, - _ => bug!( - "expected item, found {}", - tcx.hir().node_to_string(opaque_hir_id), - ), - }; + _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), + }; if in_definition_scope { let opaque_type_key = OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; @@ -1057,8 +1043,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); let param_env = tcx.param_env(def_id); - let InferOk { value: bounds, obligations } = - infcx.partially_normalize_associated_types_in(span, self.body_id, param_env, bounds); + let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in( + ObligationCause::misc(span, self.body_id), + param_env, + bounds, + ); self.obligations.extend(obligations); debug!("instantiate_opaque_types: bounds={:?}", bounds); diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index 026ab41444..7a690af0cc 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -58,6 +58,9 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { obligation: obligation.clone(), code: FulfillmentErrorCode::CodeAmbiguity, points_at_arg_span: false, + // FIXME - does Chalk have a notation of 'root obligation'? + // This is just for diagnostics, so it's okay if this is wrong + root_obligation: obligation.clone(), }) .collect(); Err(errors) @@ -105,11 +108,14 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { ), Err(_err) => errors.push(FulfillmentError { - obligation, + obligation: obligation.clone(), code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, ), points_at_arg_span: false, + // FIXME - does Chalk have a notation of 'root obligation'? + // This is just for diagnostics, so it's okay if this is wrong + root_obligation: obligation, }), } } else { @@ -119,11 +125,14 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { } Err(NoSolution) => errors.push(FulfillmentError { - obligation, + obligation: obligation.clone(), code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, ), points_at_arg_span: false, + // FIXME - does Chalk have a notation of 'root obligation'? + // This is just for diagnostics, so it's okay if this is wrong + root_obligation: obligation, }), } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 8961cdaebf..b1a938836b 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -97,6 +97,16 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } + Node::Cast(_, _, ty) => { + let ty = ty.subst(tcx, ct.substs); + if ty.has_infer_types_or_consts() { + failure_kind = FailureKind::MentionsInfer; + } else if ty.has_param_types_or_consts() { + failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam); + } + + ControlFlow::CONTINUE + } Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => { ControlFlow::CONTINUE } @@ -304,6 +314,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.nodes[func].used = true; nodes.iter().for_each(|&n| self.nodes[n].used = true); } + Node::Cast(_, operand, _) => { + self.nodes[operand].used = true; + } } // Nodes start as unused. @@ -408,11 +421,19 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span); Ok(()) } + Rvalue::Cast(cast_kind, ref operand, ty) => { + let operand = self.operand_to_node(span, operand)?; + self.locals[local] = + self.add_node(Node::Cast(cast_kind, operand, ty), span); + Ok(()) + } _ => self.error(Some(span), "unsupported rvalue")?, } } // These are not actually relevant for us here, so we can ignore them. - StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => Ok(()), + StatementKind::AscribeUserType(..) + | StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) => Ok(()), _ => self.error(Some(stmt.source_info.span), "unsupported statement")?, } } @@ -594,6 +615,7 @@ where recurse(tcx, ct.subtree(func), f)?; args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f)) } + Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f), } } @@ -676,6 +698,11 @@ pub(super) fn try_unify<'tcx>( && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } + (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty)) + if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) => + { + try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) + } _ => false, } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 19c3385dd4..713e06f91d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -55,9 +55,13 @@ pub trait InferCtxtExt<'tcx> { fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; + /// The `root_obligation` parameter should be the `root_obligation` field + /// from a `FulfillmentError`. If no `FulfillmentError` is available, + /// then it should be the same as `obligation`. fn report_selection_error( &self, - obligation: &PredicateObligation<'tcx>, + obligation: PredicateObligation<'tcx>, + root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, fallback_has_occurred: bool, points_at_arg: bool, @@ -225,16 +229,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { fn report_selection_error( &self, - obligation: &PredicateObligation<'tcx>, + mut obligation: PredicateObligation<'tcx>, + root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, fallback_has_occurred: bool, points_at_arg: bool, ) { let tcx = self.tcx; - let span = obligation.cause.span; + let mut span = obligation.cause.span; let mut err = match *error { SelectionError::Unimplemented => { + // If this obligation was generated as a result of well-formed checking, see if we + // can get a better error message by performing HIR-based well formed checking. + if let ObligationCauseCode::WellFormed(Some(wf_loc)) = + root_obligation.cause.code.peel_derives() + { + if let Some(cause) = self.tcx.diagnostic_hir_wf_check(( + tcx.erase_regions(obligation.predicate), + wf_loc.clone(), + )) { + obligation.cause = cause; + span = obligation.cause.span; + } + } if let ObligationCauseCode::CompareImplMethodObligation { item_name, impl_item_def_id, @@ -279,7 +297,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .unwrap_or_default(); let OnUnimplementedNote { message, label, note, enclosing_scope } = - self.on_unimplemented_note(trait_ref, obligation); + self.on_unimplemented_note(trait_ref, &obligation); let have_alt_message = message.is_some() || label.is_some(); let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_unsize = @@ -338,7 +356,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - if let Some(ret_span) = self.return_type_span(obligation) { + if let Some(ret_span) = self.return_type_span(&obligation) { err.span_label( ret_span, &format!( @@ -368,7 +386,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { points_at_arg, have_alt_message, ) { - self.note_obligation_cause(&mut err, obligation); + self.note_obligation_cause(&mut err, &obligation); err.emit(); return; } @@ -514,6 +532,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } + // Return early if the trait is Debug or Display and the invocation + // originates within a standard library macro, because the output + // is otherwise overwhelming and unhelpful (see #85844 for an + // example). + + let trait_is_debug = + self.tcx.is_diagnostic_item(sym::debug_trait, trait_ref.def_id()); + let trait_is_display = + self.tcx.is_diagnostic_item(sym::display_trait, trait_ref.def_id()); + + let in_std_macro = + match obligation.cause.span.ctxt().outer_expn_data().macro_def_id { + Some(macro_def_id) => { + let crate_name = tcx.crate_name(macro_def_id.krate); + crate_name == sym::std || crate_name == sym::core + } + None => false, + }; + + if in_std_macro && (trait_is_debug || trait_is_display) { + err.emit(); + return; + } + err } @@ -797,7 +839,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } }; - self.note_obligation_cause(&mut err, obligation); + self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); err.emit(); @@ -1144,7 +1186,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { match error.code { FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { self.report_selection_error( - &error.obligation, + error.obligation.clone(), + &error.root_obligation, selection_error, fallback_has_occurred, error.points_at_arg_span, 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 5c35b515f3..9a33875d6e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -28,6 +28,7 @@ use rustc_target::spec::abi; use std::fmt; use super::InferCtxtPrivExt; +use crate::infer::InferCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -687,15 +688,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; } - // Blacklist traits for which it would be nonsensical to suggest borrowing. + // List of traits for which it would be nonsensical to suggest borrowing. // For instance, immutable references are always Copy, so suggesting to // borrow would always succeed, but it's probably not what the user wanted. - let blacklist: Vec<_> = - [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized, LangItem::Send] + let mut never_suggest_borrow: Vec<_> = + [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized] .iter() .filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok()) .collect(); + never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap()); + let span = obligation.cause.span; let param_env = obligation.param_env; let trait_ref = trait_ref.skip_binder(); @@ -797,7 +800,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ty::TraitRef::new(trait_ref.def_id, imm_substs), trait_ref, false, - &blacklist[..], + &never_suggest_borrow[..], ) { return true; } else { @@ -805,7 +808,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ty::TraitRef::new(trait_ref.def_id, mut_substs), trait_ref, true, - &blacklist[..], + &never_suggest_borrow[..], ); } } else { @@ -1854,12 +1857,37 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } GeneratorInteriorOrUpvar::Upvar(upvar_span) => { + // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync` + let refers_to_non_sync = match target_ty.kind() { + ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) { + Ok(eval) if !eval.may_apply() => Some(ref_ty), + _ => None, + }, + _ => None, + }; + + let (span_label, span_note) = match refers_to_non_sync { + // if `target_ty` is `&T` and `T` fails to impl `Sync`, + // include suggestions to make `T: Sync` so that `&T: Send` + Some(ref_ty) => ( + format!( + "has type `{}` which {}, because `{}` is not `Sync`", + target_ty, trait_explanation, ref_ty + ), + format!( + "captured value {} because `&` references cannot be sent unless their referent is `Sync`", + trait_explanation + ), + ), + None => ( + format!("has type `{}` which {}", target_ty, trait_explanation), + format!("captured value {}", trait_explanation), + ), + }; + let mut span = MultiSpan::from_span(upvar_span); - span.push_span_label( - upvar_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note(span, &format!("captured value {}", trait_explanation)); + span.push_span_label(upvar_span, span_label); + err.span_note(span, &span_note); } } @@ -1899,7 +1927,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::UnifyReceiver(..) | ObligationCauseCode::OpaqueType - | ObligationCauseCode::MiscObligation => {} + | ObligationCauseCode::MiscObligation + | ObligationCauseCode::WellFormed(..) + | ObligationCauseCode::MatchImpl(..) => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } @@ -1924,12 +1954,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::ItemObligation(item_def_id) => { let item_name = tcx.def_path_str(item_def_id); let msg = format!("required by `{}`", item_name); - if let Some(sp) = tcx.hir().span_if_local(item_def_id) { - let sp = tcx.sess.source_map().guess_head_span(sp); - err.span_label(sp, &msg); - } else { - err.note(&msg); - } + let sp = tcx + .hir() + .span_if_local(item_def_id) + .unwrap_or_else(|| tcx.def_span(item_def_id)); + let sp = tcx.sess.source_map().guess_head_span(sp); + err.span_note(sp, &msg); } ObligationCauseCode::BindingObligation(item_def_id, span) => { let item_name = tcx.def_path_str(item_def_id); @@ -1948,7 +1978,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if span != DUMMY_SP { err.span_label(span, &msg); } else { - err.note(&msg); + err.span_note( + tcx.def_span(item_def_id), + &format!("required by a bound in `{}`", item_name), + ); } } ObligationCauseCode::ObjectCastObligation(object_ty) => { @@ -1975,9 +2008,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if self.tcx.sess.is_nightly_build() && is_const_fn { err.help( - "create an inline `const` block, see RFC \ - #2920 \ - for more information", + "create an inline `const` block, see RFC #2920 \ + for more information", ); } } @@ -2164,8 +2196,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.tcx.for_each_relevant_impl( parent_def_id, parent_trait_ref.self_ty().skip_binder(), - |impl_def_id| { - candidates.push(impl_def_id); + |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) { + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { .. }), + .. + })) => { + candidates.push(impl_def_id); + } + _ => {} }, ); match &candidates[..] { @@ -2310,7 +2348,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { - let current_limit = self.tcx.sess.recursion_limit(); + let current_limit = self.tcx.recursion_limit(); let suggested_limit = current_limit * 2; err.help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", @@ -2349,12 +2387,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } let self_ty = self.tcx.erase_regions(self_ty); - let impls_future = self.tcx.type_implements_trait(( + let impls_future = self.type_implements_trait( future_trait, self_ty.skip_binder(), ty::List::empty(), obligation.param_env, - )); + ); let item_def_id = self .tcx @@ -2396,7 +2434,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { normalized_ty, ); debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation); - if self.predicate_may_hold(&try_obligation) && impls_future { + if self.predicate_may_hold(&try_obligation) + && impls_future.must_apply_modulo_regions() + { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if snippet.ends_with('?') { err.span_suggestion_verbose( diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 120680092b..9ec1dd5c2e 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -167,6 +167,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { /// `SomeTrait` or a where-clause that lets us unify `$0` with /// something concrete. If this fails, we'll unify `$0` with /// `projection_ty` again. + #[tracing::instrument(level = "debug", skip(self, infcx, param_env, cause))] fn normalize_projection_type( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -174,8 +175,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>, ) -> Ty<'tcx> { - debug!(?projection_ty, "normalize_projection_type"); - debug_assert!(!projection_ty.has_escaping_bound_vars()); // FIXME(#20304) -- cache @@ -366,6 +365,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let project_obligation = obligation.with(binder.rebind(data)); self.process_projection_obligation( + obligation, project_obligation, &mut pending_obligation.stalled_on, ) @@ -420,6 +420,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let project_obligation = obligation.with(Binder::dummy(*data)); self.process_projection_obligation( + obligation, project_obligation, &mut pending_obligation.stalled_on, ) @@ -667,10 +668,22 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { fn process_projection_obligation( &mut self, + obligation: &PredicateObligation<'tcx>, project_obligation: PolyProjectionObligation<'tcx>, stalled_on: &mut Vec>, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let tcx = self.selcx.tcx(); + + if obligation.predicate.is_global() { + // no type variables present, can use evaluation for better caching. + // FIXME: consider caching errors too. + if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) { + return ProcessResult::Changed(vec![]); + } else { + tracing::debug!("Does NOT hold: {:?}", obligation); + } + } + match project::poly_project_and_unify_type(self.selcx, &project_obligation) { Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)), Ok(Ok(None)) => { @@ -717,6 +730,10 @@ fn substs_infer_vars<'a, 'tcx>( fn to_fulfillment_error<'tcx>( error: Error, FulfillmentErrorCode<'tcx>>, ) -> FulfillmentError<'tcx> { - let obligation = error.backtrace.into_iter().next().unwrap().obligation; - FulfillmentError::new(obligation, error.error) + let mut iter = error.backtrace.into_iter(); + let obligation = iter.next().unwrap().obligation; + // The root obligation is the last item in the backtrace - if there's only + // one item, then it's the same as the main obligation + let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation); + FulfillmentError::new(obligation, error.error, root_obligation) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index f26eb15910..3a80e720e8 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -31,7 +31,8 @@ use rustc_hir::def_id::DefId; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{ - self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, WithConstness, + self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness, + COMMON_VTABLE_ENTRIES, }; use rustc_span::Span; @@ -455,89 +456,89 @@ fn subst_and_check_impossible_predicates<'tcx>( /// Given a trait `trait_ref`, iterates the vtable entries /// that come from `trait_ref`, including its supertraits. -fn vtable_methods<'tcx>( +fn vtable_entries<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, -) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] { - debug!("vtable_methods({:?})", trait_ref); - - tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| { - let trait_methods = tcx - .associated_items(trait_ref.def_id()) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Fn); - - // Now list each method's DefId and InternalSubsts (for within its trait). - // If the method can never be called from this object, produce None. - trait_methods.map(move |trait_method| { - debug!("vtable_methods: trait_method={:?}", trait_method); - let def_id = trait_method.def_id; - - // Some methods cannot be called on an object; skip those. - if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) { - debug!("vtable_methods: not vtable safe"); - return None; - } +) -> &'tcx [VtblEntry<'tcx>] { + debug!("vtable_entries({:?})", trait_ref); + + let entries = COMMON_VTABLE_ENTRIES.iter().cloned().chain( + supertraits(tcx, trait_ref).flat_map(move |trait_ref| { + let trait_methods = tcx + .associated_items(trait_ref.def_id()) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Fn); + + // Now list each method's DefId and InternalSubsts (for within its trait). + // If the method can never be called from this object, produce `Vacant`. + trait_methods.map(move |trait_method| { + debug!("vtable_entries: trait_method={:?}", trait_method); + let def_id = trait_method.def_id; + + // Some methods cannot be called on an object; skip those. + if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) { + debug!("vtable_entries: not vtable safe"); + return VtblEntry::Vacant; + } - // The method may have some early-bound lifetimes; add regions for those. - let substs = trait_ref.map_bound(|trait_ref| { - InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { - GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - trait_ref.substs[param.index as usize] - } - }) - }); - - // The trait type may have higher-ranked lifetimes in it; - // erase them if they appear, so that we get the type - // at some particular call site. - let substs = - tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs); - - // It's possible that the method relies on where-clauses that - // do not hold for this particular set of type parameters. - // Note that this method could then never be called, so we - // do not want to try and codegen it, in that case (see #23435). - let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); - if impossible_predicates(tcx, predicates.predicates) { - debug!("vtable_methods: predicates do not hold"); - return None; - } + // The method may have some early-bound lifetimes; add regions for those. + let substs = trait_ref.map_bound(|trait_ref| { + InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { + GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + trait_ref.substs[param.index as usize] + } + }) + }); + + // The trait type may have higher-ranked lifetimes in it; + // erase them if they appear, so that we get the type + // at some particular call site. + let substs = + tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs); + + // It's possible that the method relies on where-clauses that + // do not hold for this particular set of type parameters. + // Note that this method could then never be called, so we + // do not want to try and codegen it, in that case (see #23435). + let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); + if impossible_predicates(tcx, predicates.predicates) { + debug!("vtable_entries: predicates do not hold"); + return VtblEntry::Vacant; + } - Some((def_id, substs)) - }) - })) + VtblEntry::Method(def_id, substs) + }) + }), + ); + + tcx.arena.alloc_from_iter(entries) } -/// Check whether a `ty` implements given trait(trait_def_id). -/// -/// NOTE: Always return `false` for a type which needs inference. -fn type_implements_trait<'tcx>( +/// Find slot base for trait methods within vtable entries of another trait +fn vtable_trait_first_method_offset<'tcx>( tcx: TyCtxt<'tcx>, key: ( - DefId, // trait_def_id, - Ty<'tcx>, // type - SubstsRef<'tcx>, - ParamEnv<'tcx>, + ty::PolyTraitRef<'tcx>, // trait_to_be_found + ty::PolyTraitRef<'tcx>, // trait_owning_vtable ), -) -> bool { - let (trait_def_id, ty, params, param_env) = key; - - debug!( - "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}", - trait_def_id, ty, params, param_env - ); - - let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) }; - - let obligation = Obligation { - cause: ObligationCause::dummy(), - param_env, - recursion_depth: 0, - predicate: trait_ref.without_const().to_predicate(tcx), - }; - tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation)) +) -> usize { + let (trait_to_be_found, trait_owning_vtable) = key; + + let mut supertraits = util::supertraits(tcx, trait_owning_vtable); + + // For each of the non-matching predicates that + // we pass over, we sum up the set of number of vtable + // entries, so that we can compute the offset for the selected + // trait. + let vtable_base = ty::COMMON_VTABLE_ENTRIES.len() + + supertraits + .by_ref() + .take_while(|t| *t != trait_to_be_found) + .map(|t| util::count_own_vtable_entries(tcx, t)) + .sum::(); + + vtable_base } pub fn provide(providers: &mut ty::query::Providers) { @@ -547,8 +548,7 @@ pub fn provide(providers: &mut ty::query::Providers) { specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, - vtable_methods, - type_implements_trait, + vtable_entries, subst_and_check_impossible_predicates, mir_abstract_const: |tcx, def_id| { let def_id = def_id.expect_local(); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index d5e1bd3f9e..7ebef7f888 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -838,6 +838,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( let leaf = leaf.subst(self.tcx, ct.substs); self.visit_const(leaf) } + Node::Cast(_, _, ty) => self.visit_ty(ty), Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { ControlFlow::CONTINUE } @@ -859,6 +860,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( let leaf = leaf.subst(self.tcx, ct.substs); self.visit_const(leaf) } + Node::Cast(_, _, ty) => self.visit_ty(ty), Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { ControlFlow::CONTINUE } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 388413ae06..d1ab9fa025 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -29,6 +29,8 @@ use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_span::symbol::sym; +use std::collections::BTreeMap; + pub use rustc_middle::traits::Reveal; pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>; @@ -271,7 +273,7 @@ where Normalized { value, obligations } } -#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] +#[instrument(level = "info", skip(selcx, param_env, cause, obligations))] pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -283,6 +285,7 @@ pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>( where T: TypeFoldable<'tcx>, { + debug!(obligations.len = obligations.len()); let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); let result = ensure_sufficient_stack(|| normalizer.fold(value)); debug!(?result, obligations.len = normalizer.obligations.len()); @@ -290,12 +293,25 @@ where result } +pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool { + match reveal { + Reveal::UserFacing => value + .has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION), + Reveal::All => value.has_type_flags( + ty::TypeFlags::HAS_TY_PROJECTION + | ty::TypeFlags::HAS_TY_OPAQUE + | ty::TypeFlags::HAS_CT_PROJECTION, + ), + } +} + struct AssocTypeNormalizer<'a, 'b, 'tcx> { selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, obligations: &'a mut Vec>, depth: usize, + universes: Vec>, } impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { @@ -306,13 +322,24 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { depth: usize, obligations: &'a mut Vec>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { - AssocTypeNormalizer { selcx, param_env, cause, obligations, depth } + AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes: vec![] } } fn fold>(&mut self, value: T) -> T { let value = self.selcx.infcx().resolve_vars_if_possible(value); + debug!(?value); + + assert!( + !value.has_escaping_bound_vars(), + "Normalizing {:?} without wrapping in a `Binder`", + value + ); - if !value.has_projections() { value } else { value.fold_with(self) } + if !needs_normalization(&value, self.param_env.reveal()) { + value + } else { + value.fold_with(self) + } } } @@ -321,8 +348,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { self.selcx.tcx() } + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.universes.push(None); + let t = t.super_fold_with(self); + self.universes.pop(); + t + } + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if !ty.has_projections() { + if !needs_normalization(&ty, self.param_env.reveal()) { return ty; } // We don't want to normalize associated types that occur inside of region @@ -344,7 +381,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { Reveal::UserFacing => ty, Reveal::All => { - let recursion_limit = self.tcx().sess.recursion_limit(); + let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { let obligation = Obligation::with_depth( self.cause.clone(), @@ -396,6 +433,52 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { normalized_ty } + ty::Projection(data) if !data.trait_ref(self.tcx()).has_escaping_bound_vars() => { + // Okay, so you thought the previous branch was hacky. Well, to + // extend upon this, when the *trait ref* doesn't have escaping + // bound vars, but the associated item *does* (can only occur + // with GATs), then we might still be able to project the type. + // For this, we temporarily replace the bound vars with + // placeholders. Note though, that in the case that we still + // can't project for whatever reason (e.g. self type isn't + // known enough), we *can't* register an obligation and return + // an inference variable (since then that obligation would have + // bound vars and that's a can of worms). Instead, we just + // give up and fall back to pretending like we never tried! + + let infcx = self.selcx.infcx(); + let (data, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); + let normalized_ty = opt_normalize_projection_type( + self.selcx, + self.param_env, + data, + self.cause.clone(), + self.depth, + &mut self.obligations, + ) + .ok() + .flatten() + .unwrap_or_else(|| ty); + + let normalized_ty = PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + normalized_ty, + ); + debug!( + ?self.depth, + ?ty, + ?normalized_ty, + obligations.len = ?self.obligations.len(), + "AssocTypeNormalizer: normalized type" + ); + normalized_ty + } + _ => ty, } } @@ -410,6 +493,279 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } } +pub struct BoundVarReplacer<'me, 'tcx> { + infcx: &'me InferCtxt<'me, '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). + mapped_regions: BTreeMap, + mapped_types: BTreeMap, + mapped_consts: BTreeMap, ty::BoundVar>, + // The current depth relative to *this* folding, *not* the entire normalization. In other words, + // the depth of binders we've passed here. + current_index: ty::DebruijnIndex, + // The `UniverseIndex` of the binding levels above us. These are optional, since we are lazy: + // we don't actually create a universe until we see a bound var we have to replace. + universe_indices: &'me mut Vec>, +} + +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>( + infcx: &'me InferCtxt<'me, 'tcx>, + universe_indices: &'me mut Vec>, + value: T, + ) -> ( + T, + BTreeMap, + BTreeMap, + BTreeMap, ty::BoundVar>, + ) { + let mapped_regions: BTreeMap = BTreeMap::new(); + let mapped_types: BTreeMap = BTreeMap::new(); + let mapped_consts: BTreeMap, ty::BoundVar> = BTreeMap::new(); + + let mut replacer = BoundVarReplacer { + infcx, + mapped_regions, + mapped_types, + mapped_consts, + current_index: ty::INNERMOST, + universe_indices, + }; + + let value = value.super_fold_with(&mut replacer); + + (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts) + } + + fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex { + let infcx = self.infcx; + let index = + self.universe_indices.len() - debruijn.as_usize() + self.current_index.as_usize() - 1; + let universe = self.universe_indices[index].unwrap_or_else(|| { + for i in self.universe_indices.iter_mut().take(index + 1) { + *i = i.or_else(|| Some(infcx.create_next_universe())) + } + self.universe_indices[index].unwrap() + }); + universe + } +} + +impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + ty::ReLateBound(debruijn, _) + if debruijn.as_usize() + 1 + > self.current_index.as_usize() + self.universe_indices.len() => + { + bug!("Bound vars outside of `self.universe_indices`"); + } + ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + let universe = self.universe_for(debruijn); + let p = ty::PlaceholderRegion { universe, name: br.kind }; + self.mapped_regions.insert(p.clone(), br); + self.infcx.tcx.mk_region(ty::RePlaceholder(p)) + } + _ => r, + } + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match *t.kind() { + ty::Bound(debruijn, _) + if debruijn.as_usize() + 1 + > self.current_index.as_usize() + self.universe_indices.len() => + { + bug!("Bound vars outside of `self.universe_indices`"); + } + ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { + let universe = self.universe_for(debruijn); + let p = ty::PlaceholderType { universe, name: bound_ty.var }; + self.mapped_types.insert(p.clone(), bound_ty); + self.infcx.tcx.mk_ty(ty::Placeholder(p)) + } + _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), + _ => t, + } + } + + fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + match *ct { + ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ } + if debruijn.as_usize() + 1 + > self.current_index.as_usize() + self.universe_indices.len() => + { + bug!("Bound vars outside of `self.universe_indices`"); + } + ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } + if debruijn >= self.current_index => + { + let universe = self.universe_for(debruijn); + let p = ty::PlaceholderConst { + universe, + name: ty::BoundConst { var: bound_const, ty }, + }; + self.mapped_consts.insert(p.clone(), bound_const); + self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty }) + } + _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self), + _ => ct, + } + } +} + +// The inverse of `BoundVarReplacer`: replaces placeholders with the bound vars from which they came. +pub struct PlaceholderReplacer<'me, 'tcx> { + infcx: &'me InferCtxt<'me, 'tcx>, + mapped_regions: BTreeMap, + mapped_types: BTreeMap, + mapped_consts: BTreeMap, ty::BoundVar>, + universe_indices: &'me Vec>, + current_index: ty::DebruijnIndex, +} + +impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { + pub fn replace_placeholders>( + infcx: &'me InferCtxt<'me, 'tcx>, + mapped_regions: BTreeMap, + mapped_types: BTreeMap, + mapped_consts: BTreeMap, ty::BoundVar>, + universe_indices: &'me Vec>, + value: T, + ) -> T { + let mut replacer = PlaceholderReplacer { + infcx, + mapped_regions, + mapped_types, + mapped_consts, + universe_indices, + current_index: ty::INNERMOST, + }; + value.super_fold_with(&mut replacer) + } +} + +impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + if !t.has_placeholders() && !t.has_infer_regions() { + return t; + } + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> { + let r1 = match r0 { + ty::ReVar(_) => self + .infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_region(self.infcx.tcx, r0), + _ => r0, + }; + + let r2 = match *r1 { + ty::RePlaceholder(p) => { + let replace_var = self.mapped_regions.get(&p); + match replace_var { + Some(replace_var) => { + let index = self + .universe_indices + .iter() + .position(|u| matches!(u, Some(pu) if *pu == p.universe)) + .unwrap_or_else(|| bug!("Unexpected placeholder universe.")); + let db = ty::DebruijnIndex::from_usize( + self.universe_indices.len() - index + self.current_index.as_usize() - 1, + ); + self.tcx().mk_region(ty::ReLateBound(db, *replace_var)) + } + None => r1, + } + } + _ => r1, + }; + + debug!(?r0, ?r1, ?r2, "fold_region"); + + r2 + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match *ty.kind() { + ty::Placeholder(p) => { + let replace_var = self.mapped_types.get(&p); + match replace_var { + Some(replace_var) => { + let index = self + .universe_indices + .iter() + .position(|u| matches!(u, Some(pu) if *pu == p.universe)) + .unwrap_or_else(|| bug!("Unexpected placeholder universe.")); + let db = ty::DebruijnIndex::from_usize( + self.universe_indices.len() - index + self.current_index.as_usize() - 1, + ); + self.tcx().mk_ty(ty::Bound(db, *replace_var)) + } + None => ty, + } + } + + _ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self), + _ => ty, + } + } + + fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + if let ty::Const { val: ty::ConstKind::Placeholder(p), ty } = *ct { + let replace_var = self.mapped_consts.get(&p); + match replace_var { + Some(replace_var) => { + let index = self + .universe_indices + .iter() + .position(|u| matches!(u, Some(pu) if *pu == p.universe)) + .unwrap_or_else(|| bug!("Unexpected placeholder universe.")); + let db = ty::DebruijnIndex::from_usize( + self.universe_indices.len() - index + self.current_index.as_usize() - 1, + ); + self.tcx() + .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty }) + } + None => ct, + } + } else { + ct.super_fold_with(self) + } + } +} + /// The guts of `normalize`: normalize a specific projection like `::Item`. The result is always a type (and possibly /// additional obligations). If ambiguity arises, which implies that @@ -487,7 +843,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key); match cache_result { - Ok(()) => {} + Ok(()) => debug!("no cache"), Err(ProjectionCacheEntry::Ambiguous) => { // If we found ambiguity the last time, that means we will continue // to do so until some type in the key changes (and we know it @@ -514,6 +870,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( return Err(InProgress); } Err(ProjectionCacheEntry::Recur) => { + debug!("recur cache"); return Err(InProgress); } Err(ProjectionCacheEntry::NormalizedTy(ty)) => { @@ -720,13 +1077,12 @@ impl<'tcx> Progress<'tcx> { /// /// IMPORTANT: /// - `obligation` must be fully normalized +#[tracing::instrument(level = "info", skip(selcx))] fn project_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, ) -> Result, ProjectionTyError<'tcx>> { - debug!(?obligation, "project_type"); - - if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) { + if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) { debug!("project: overflow!"); // This should really be an immediate error, but some existing code // relies on being able to recover from this. @@ -1301,7 +1657,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( ty: self_ty.ptr_metadata_ty(tcx), }; - confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false) + confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( 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 b83a4cd1e5..2dc48e47ef 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -64,8 +64,10 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { obligation: &PredicateObligation<'tcx>, ) -> Result { let mut _orig_values = OriginalQueryValues::default(); - let c_pred = self - .canonicalize_query(obligation.param_env.and(obligation.predicate), &mut _orig_values); + let c_pred = self.canonicalize_query_keep_static( + obligation.param_env.and(obligation.predicate), + &mut _orig_values, + ); // Run canonical query. If overflow occurs, rerun from scratch but this time // in standard trait query mode so that overflow is handled appropriately // within `SelectionContext`. diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index eb7ea8715c..3f6efa03b3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -6,6 +6,7 @@ use crate::infer::at::At; use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; use crate::traits::error_reporting::InferCtxtExt; +use crate::traits::project::needs_normalization; use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -49,7 +50,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { value, self.param_env, ); - if !value.has_projections() { + if !needs_normalization(&value, self.param_env.reveal()) { return Ok(Normalized { value, obligations: vec![] }); } @@ -61,10 +62,11 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { error: false, cache: SsoHashMap::new(), anon_depth: 0, + universes: vec![], }; let result = value.fold_with(&mut normalizer); - debug!( + info!( "normalize::<{}>: result={:?} with {} obligations", std::any::type_name::(), result, @@ -91,6 +93,7 @@ struct QueryNormalizer<'cx, 'tcx> { cache: SsoHashMap, Ty<'tcx>>, error: bool, anon_depth: usize, + universes: Vec>, } impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { @@ -98,9 +101,19 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { self.infcx.tcx } + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.universes.push(None); + let t = t.super_fold_with(self); + self.universes.pop(); + t + } + #[instrument(level = "debug", skip(self))] fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if !ty.has_projections() { + if !needs_normalization(&ty, self.param_env.reveal()) { return ty; } @@ -116,7 +129,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { Reveal::UserFacing => ty, Reveal::All => { - let recursion_limit = self.tcx().sess.recursion_limit(); + let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { let obligation = Obligation::with_depth( self.cause.clone(), @@ -167,7 +180,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { // so we cannot canonicalize it. let c_data = self .infcx - .canonicalize_hr_query_hack(self.param_env.and(data), &mut orig_values); + .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); match tcx.normalize_projection_ty(c_data) { @@ -204,6 +217,80 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } } } + ty::Projection(data) if !data.trait_ref(self.infcx.tcx).has_escaping_bound_vars() => { + // See note in `rustc_trait_selection::traits::project` + + // One other point mentioning: In `traits::project`, if a + // projection can't be normalized, we return an inference variable + // and register an obligation to later resolve that. Here, the query + // will just return ambiguity. In both cases, the effect is the same: we only want + // to return `ty` because there are bound vars that we aren't yet handling in a more + // complete way. + + // `BoundVarReplacer` can't handle escaping bound vars. Ideally, we want this before even calling + // `QueryNormalizer`, but some const-generics tests pass escaping bound vars. + // Also, use `ty` so we get that sweet `outer_exclusive_binder` optimization + assert!(!ty.has_vars_bound_at_or_above(ty::DebruijnIndex::from_usize( + self.universes.len() + ))); + + let tcx = self.infcx.tcx; + let infcx = self.infcx; + let (data, mapped_regions, mapped_types, mapped_consts) = + crate::traits::project::BoundVarReplacer::replace_bound_vars( + infcx, + &mut self.universes, + data, + ); + let data = data.super_fold_with(self); + + let mut orig_values = OriginalQueryValues::default(); + // HACK(matthewjasper) `'static` is special-cased in selection, + // so we cannot canonicalize it. + let c_data = self + .infcx + .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); + debug!("QueryNormalizer: c_data = {:#?}", c_data); + debug!("QueryNormalizer: orig_values = {:#?}", orig_values); + let normalized_ty = match tcx.normalize_projection_ty(c_data) { + Ok(result) => { + // We don't expect ambiguity. + if result.is_ambiguous() { + self.error = true; + return ty; + } + match self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + ) { + Ok(InferOk { value: result, obligations }) => { + debug!("QueryNormalizer: result = {:#?}", result); + debug!("QueryNormalizer: obligations = {:#?}", obligations); + self.obligations.extend(obligations); + result.normalized_ty + } + Err(_) => { + self.error = true; + ty + } + } + } + Err(NoSolution) => { + self.error = true; + ty + } + }; + crate::traits::project::PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + normalized_ty, + ) + } _ => ty, })(); 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 130ffa1a33..fbff86618a 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 @@ -77,12 +77,13 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx { } // FIXME(#33684) -- We need to use - // `canonicalize_hr_query_hack` here because of things + // `canonicalize_query_keep_static` here because of things // like the subtype query, which go awry around // `'static` otherwise. let mut canonical_var_values = OriginalQueryValues::default(); let old_param_env = query_key.param_env; - let canonical_self = infcx.canonicalize_hr_query_hack(query_key, &mut canonical_var_values); + let canonical_self = + infcx.canonicalize_query_keep_static(query_key, &mut canonical_var_values); let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?; let InferOk { value, obligations } = infcx diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e338a21b60..f8297ee3a0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -396,19 +396,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut nested = vec![]; let mut supertraits = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref)); - - // For each of the non-matching predicates that - // we pass over, we sum up the set of number of vtable - // entries, so that we can compute the offset for the selected - // trait. - let vtable_base = supertraits - .by_ref() - .take(index) - .map(|t| super::util::count_own_vtable_entries(tcx, t)) - .sum(); - let unnormalized_upcast_trait_ref = - supertraits.next().expect("supertraits iterator no longer has as many elements"); + supertraits.nth(index).expect("supertraits iterator no longer has as many elements"); let upcast_trait_ref = normalize_with_depth_to( self, @@ -490,6 +479,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } debug!(?nested, "object nested obligations"); + + let vtable_base = super::super::vtable_trait_first_method_offset( + tcx, + (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)), + ); + Ok(ImplSourceObjectData { upcast_trait_ref, vtable_base, nested }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ea5eb2b686..95611ebc81 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -28,6 +28,7 @@ use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectionCacheKeyExt; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -48,7 +49,6 @@ use std::cell::{Cell, RefCell}; use std::cmp; use std::fmt::{self, Display}; use std::iter; -use std::rc::Rc; pub use rustc_middle::traits::select::*; @@ -216,7 +216,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx, - freshener: infcx.freshener(), + freshener: infcx.freshener_keep_static(), intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, @@ -227,7 +227,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx, - freshener: infcx.freshener(), + freshener: infcx.freshener_keep_static(), intercrate: true, intercrate_ambiguity_causes: None, allow_negative_impls: false, @@ -242,7 +242,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?allow_negative_impls, "with_negative"); SelectionContext { infcx, - freshener: infcx.freshener(), + freshener: infcx.freshener_keep_static(), intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls, @@ -257,7 +257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?query_mode, "with_query_mode"); SelectionContext { infcx, - freshener: infcx.freshener(), + freshener: infcx.freshener_keep_static(), intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, @@ -492,7 +492,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => Ok(EvaluatedToAmbig), }, - ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => { + ty::PredicateKind::TypeOutlives(pred) => { + if pred.0.is_global() { + Ok(EvaluatedToOk) + } else { + Ok(EvaluatedToOkModuloRegions) + } + } + + ty::PredicateKind::RegionOutlives(..) => { // We do not consider region relationships when evaluating trait matches. Ok(EvaluatedToOkModuloRegions) } @@ -985,7 +993,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &Obligation<'tcx, T>, error_obligation: &Obligation<'tcx, V>, ) -> Result<(), OverflowError> { - if !self.infcx.tcx.sess.recursion_limit().value_within_limit(obligation.recursion_depth) { + if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) { match self.query_mode { TraitQueryMode::Standard => { self.infcx().report_overflow_error(error_obligation, true); @@ -1857,12 +1865,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + #[tracing::instrument(level = "debug", skip(self))] fn match_impl( &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, ) -> Result>, ()> { - debug!(?impl_def_id, ?obligation, "match_impl"); let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); // Before we create the substitutions and everything, first @@ -1880,6 +1888,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs); + debug!(?impl_trait_ref); + let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( @@ -1893,9 +1903,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?impl_trait_ref, ?placeholder_obligation_trait_ref); + let cause = ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + ObligationCauseCode::MatchImpl(Lrc::new(obligation.cause.code.clone()), impl_def_id), + ); + let InferOk { obligations, .. } = self .infcx - .at(&obligation.cause, obligation.param_env) + .at(&cause, obligation.param_env) .eq(placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); @@ -1907,7 +1923,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - debug!(?impl_substs, "match_impl: success"); + debug!(?impl_substs, ?nested_obligations, "match_impl: success"); Ok(Normalized { value: impl_substs, obligations: nested_obligations }) } @@ -2060,6 +2076,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// impl or trait. The obligations are substituted and fully /// normalized. This is used when confirming an impl or default /// impl. + #[tracing::instrument(level = "debug", skip(self, cause, param_env))] fn impl_or_trait_obligations( &mut self, cause: ObligationCause<'tcx>, @@ -2068,7 +2085,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { def_id: DefId, // of impl or trait substs: SubstsRef<'tcx>, // for impl or trait ) -> Vec> { - debug!(?def_id, "impl_or_trait_obligations"); let tcx = self.tcx(); // To allow for one-pass evaluation of the nested obligation, @@ -2086,9 +2102,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `$1: Copy`, so we must ensure the obligations are emitted in // that order. let predicates = tcx.predicates_of(def_id); + debug!(?predicates); assert_eq!(predicates.parent, None); let mut obligations = Vec::with_capacity(predicates.predicates.len()); for (predicate, _) in predicates.predicates { + debug!(?predicate); let predicate = normalize_with_depth_to( self, param_env, @@ -2160,7 +2178,7 @@ impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> { // by using -Z verbose or just a CLI argument. let derived_cause = DerivedObligationCause { parent_trait_ref: obligation.predicate.to_poly_trait_ref(), - parent_code: Rc::new(obligation.cause.code.clone()), + parent_code: Lrc::new(obligation.cause.code.clone()), }; let derived_code = variant(derived_cause); ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code) diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 3d20a8d5cf..a6323a65aa 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -19,7 +19,6 @@ pub enum NonStructuralMatchTy<'tcx> { Opaque, Generator, Projection, - Closure, } /// This method traverses the structure of `ty`, trying to find an @@ -155,9 +154,6 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { ty::Generator(..) | ty::GeneratorWitness(..) => { return ControlFlow::Break(NonStructuralMatchTy::Generator); } - ty::Closure(..) => { - return ControlFlow::Break(NonStructuralMatchTy::Closure); - } ty::RawPtr(..) => { // structural-match ignores substructure of // `*const _`/`*mut _`, so skip `super_visit_with`. @@ -198,7 +194,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { // First check all contained types and then tell the caller to continue searching. return ty.super_visit_with(self); } - ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => { + ty::Closure(..) | ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => { bug!("unexpected type during structural-match checking: {:?}", ty); } ty::Error(_) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f592cf1cd2..27c8e00c55 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1,6 +1,7 @@ use crate::infer::InferCtxt; use crate::opaque_types::required_region_bounds; use crate::traits; +use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -9,7 +10,6 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstnes use rustc_span::Span; use std::iter; -use std::rc::Rc; /// Returns the set of obligations needed to make `arg` well-formed. /// If `arg` contains unresolved inference variables, this may include /// further WF obligations. However, if `arg` IS an unresolved @@ -85,6 +85,7 @@ pub fn trait_obligations<'a, 'tcx>( let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item }; wf.compute_trait_ref(trait_ref, Elaborate::All); + debug!(obligations = ?wf.out); wf.normalize() } @@ -295,7 +296,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { let derived_cause = traits::DerivedObligationCause { parent_trait_ref: parent_trait_ref.value, - parent_code: Rc::new(obligation.cause.code.clone()), + parent_code: Lrc::new(obligation.cause.code.clone()), }; cause.make_mut().code = traits::ObligationCauseCode::DerivedObligation(derived_cause); diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 39890fd5b0..a838172d66 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -8,7 +8,7 @@ //! ## `Ty` lowering //! Much of the `Ty` lowering is 1:1 with Chalk. (Or will be eventually). A //! helpful table for what types lower to what can be found in the -//! [Chalk book](http://rust-lang.github.io/chalk/book/types/rust_types.html). +//! [Chalk book](https://rust-lang.github.io/chalk/book/types/rust_types.html). //! The most notable difference lies with `Param`s. To convert from rustc to //! Chalk, we eagerly and deeply convert `Param`s to placeholders (in goals) or //! bound variables (for clause generation through functions in `db`). diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 9d5b9d7357..4a41dfe014 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>( ) -> Result<(), NoSolution> { debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty); - if !tcx.sess.recursion_limit().value_within_limit(depth) { + if !tcx.recursion_limit().value_within_limit(depth) { constraints.overflows.push(ty); return Ok(()); } diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 7b688cd3e2..d0b05beb4e 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -4,7 +4,6 @@ #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(control_flow_enum)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 6304f696b0..2c55ea7f5c 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -67,8 +67,7 @@ impl AscribeUserTypeCx<'me, 'tcx> { { self.infcx .partially_normalize_associated_types_in( - DUMMY_SP, - hir::CRATE_HIR_ID, + ObligationCause::misc(DUMMY_SP, hir::CRATE_HIR_ID), self.param_env, value, ) diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 874289d029..469ac04e54 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -2,14 +2,114 @@ use rustc_errors::ErrorReported; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Binder, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_span::{sym, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; +use rustc_data_structures::sso::SsoHashSet; +use std::collections::btree_map::Entry; +use std::collections::BTreeMap; +use std::ops::ControlFlow; + use tracing::debug; +// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used +// outside of `resolve_associated_item`. It's just to address #64494, +// #83765, and #85848 which are creating bound types/regions that lose +// their `Binder` *unintentionally*. +// It's ideal to remove `BoundVarsCollector` and just use +// `ty::Binder::*` methods but we use this stopgap until we figure out +// the "real" fix. +struct BoundVarsCollector<'tcx> { + binder_index: ty::DebruijnIndex, + vars: BTreeMap, + // We may encounter the same variable at different levels of binding, so + // this can't just be `Ty` + visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, +} + +impl<'tcx> BoundVarsCollector<'tcx> { + fn new() -> Self { + BoundVarsCollector { + binder_index: ty::INNERMOST, + vars: BTreeMap::new(), + visited: SsoHashSet::default(), + } + } + + fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List { + let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or(0); + for i in 0..max { + if let None = self.vars.get(&i) { + panic!("Unknown variable: {:?}", i); + } + } + + tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v)) + } +} + +impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { + type BreakTy = (); + + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + self.binder_index.shift_in(1); + let result = t.super_visit_with(self); + self.binder_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if t.outer_exclusive_binder() < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::CONTINUE; + } + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + match self.vars.entry(bound_ty.var.as_u32()) { + Entry::Vacant(entry) => { + entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind)); + } + Entry::Occupied(entry) => match entry.get() { + ty::BoundVariableKind::Ty(_) => {} + _ => bug!("Conflicting bound vars"), + }, + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match r { + ty::ReLateBound(index, br) if *index == self.binder_index => { + match self.vars.entry(br.var.as_u32()) { + Entry::Vacant(entry) => { + entry.insert(ty::BoundVariableKind::Region(br.kind)); + } + Entry::Occupied(entry) => match entry.get() { + ty::BoundVariableKind::Region(_) => {} + _ => bug!("Conflicting bound vars"), + }, + } + } + + _ => (), + }; + + r.super_visit_with(self) + } +} + #[instrument(level = "debug", skip(tcx))] fn resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, @@ -115,7 +215,12 @@ fn resolve_associated_item<'tcx>( ); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?; + + // See FIXME on `BoundVarsCollector`. + let mut bound_vars_collector = BoundVarsCollector::new(); + trait_ref.visit_with(&mut bound_vars_collector); + let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx)); + let vtbl = tcx.codegen_fulfill_obligation((param_env, trait_binder))?; // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 67a692ecea..313571274c 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,6 +5,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(control_flow_enum)] #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] #![feature(nll)] diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index bc8f10e15d..d837af85d5 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -63,7 +63,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { seen_tys, query_ty: ty, unchecked_tys: vec![(ty, 0)], - recursion_limit: tcx.sess.recursion_limit(), + recursion_limit: tcx.recursion_limit(), adt_components, } } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index ebc7b0d0d9..b0d644ae02 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,12 +1,11 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::hir::map as hir_map; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{ self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, }; -use rustc_session::CrateDisambiguator; use rustc_span::Span; use rustc_trait_selection::traits; @@ -169,6 +168,16 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { } } +fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let item = tcx.hir().expect_item(hir_id); + if let hir::ItemKind::Impl(impl_) = &item.kind { + impl_.constness + } else { + bug!("`impl_constness` called on {:?}", item); + } +} + /// Calculates the `Sized` constraint. /// /// In fact, there are only a few options for the types in the constraint: @@ -388,11 +397,6 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE tcx.param_env(def_id).with_reveal_all_normalized(tcx) } -fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator { - assert_eq!(crate_num, LOCAL_CRATE); - tcx.sess.local_crate_disambiguator() -} - fn instance_def_size_estimate<'tcx>( tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>, @@ -402,7 +406,7 @@ fn instance_def_size_estimate<'tcx>( match instance_def { InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { let mir = tcx.instance_mir(instance_def); - mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum() + mir.basic_blocks().iter().map(|bb| bb.statements.len() + 1).sum() } // Estimate the size of other compiler-generated shims to be 1. _ => 1, @@ -538,10 +542,10 @@ pub fn provide(providers: &mut ty::query::Providers) { param_env, param_env_reveal_all_normalized, trait_of_item, - crate_disambiguator, instance_def_size_estimate, issue33140_self_ty, impl_defaultness, + impl_constness, conservative_is_privately_uninhabited: conservative_is_privately_uninhabited_raw, ..*providers }; diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index ef19562104..f55e274ef8 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -838,6 +838,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { this does nothing because the given bound is not \ a default; only `?Sized` is supported", ); + return false; } } } @@ -1694,7 +1695,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; self.one_bound_for_assoc_type( - || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)), + || traits::supertraits(tcx, ty::Binder::dummy(trait_ref)), || "Self".to_string(), assoc_ident, span, @@ -2418,6 +2419,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { visitor.0, true, hir_ty, + "function", ); } diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index cb8f336721..d101551085 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -205,7 +205,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_arg_exprs: Option<&'tcx [hir::Expr<'tcx>]>, ) -> Option<(Option>, MethodCallee<'tcx>)> { // Try the options that are least restrictive on the caller first. - for &(opt_trait_def_id, method_name, borrow) in &[ + for (opt_trait_def_id, method_name, borrow) in [ (self.tcx.lang_items().fn_trait(), Ident::with_dummy_span(sym::call), true), (self.tcx.lang_items().fn_mut_trait(), Ident::with_dummy_span(sym::call_mut), true), (self.tcx.lang_items().fn_once_trait(), Ident::with_dummy_span(sym::call_once), false), @@ -588,10 +588,17 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { fcx.write_method_call(self.call_expr.hir_id, method_callee); } None => { - span_bug!( + // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` + // lang items are not defined (issue #86238). + let mut err = fcx.inh.tcx.sess.struct_span_err( self.call_expr.span, - "failed to find an overloaded call trait for closure call" + "failed to find an overloaded call trait for closure call", ); + err.help( + "make sure the `fn`/`fn_mut`/`fn_once` lang items are defined \ + and have associated `call`/`call_mut`/`call_once` functions", + ); + err.emit(); } } } diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 3cbc3d231f..b3808eae1a 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -45,6 +45,7 @@ use rustc_session::lint; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::report_object_safety_error; @@ -440,16 +441,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); let expr_ty = fcx.tcx.erase_regions(expr_ty); let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]); - // Check for infer types because cases like `Option<{integer}>` would - // panic otherwise. - if !expr_ty.has_infer_types() - && !ty.has_infer_types() - && fcx.tcx.type_implements_trait(( - from_trait, - ty, - ty_params, - fcx.param_env, - )) + if fcx + .infcx + .type_implements_trait(from_trait, ty, ty_params, fcx.param_env) + .must_apply_modulo_regions() { label = false; err.span_suggestion( diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 70d85796d0..b5db3331d0 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::layout::MAX_SIMD_LANES; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt}; -use rustc_session::lint::builtin::UNINHABITED_STATIC; +use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; use rustc_target::spec::abi::Abi; @@ -34,16 +34,22 @@ pub fn check_wf_new(tcx: TyCtxt<'_>) { tcx.hir().krate().par_visit_all_item_likes(&visit); } -pub(super) fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) { - if !tcx.sess.target.is_abi_supported(abi) { - struct_span_err!( +pub(super) 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) => struct_span_err!( tcx.sess, span, E0570, - "The ABI `{}` is not supported for the current target", + "`{}` is not a supported ABI for the current target", abi ) - .emit() + .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() + }); + } } // This ABI is only allowed on function pointers @@ -215,9 +221,7 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.resume_yield_tys = Some((resume_ty, yield_ty)); } - let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local(); - let outer_hir_id = hir.local_def_id_to_hir_id(outer_def_id); - GatherLocalsVisitor::new(&fcx, outer_hir_id).visit_body(body); + 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). @@ -659,13 +663,9 @@ pub(super) fn check_opaque_for_cycles<'tcx>( span: Span, origin: &hir::OpaqueTyOrigin, ) -> Result<(), ErrorReported> { - if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs) - { + if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { match origin { hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span), - hir::OpaqueTyOrigin::Binding => { - binding_opaque_type_cycle_error(tcx, def_id, span, partially_expanded_type) - } _ => opaque_type_cycle_error(tcx, def_id, span), } Err(ErrorReported) @@ -698,8 +698,7 @@ fn check_opaque_meets_bounds<'tcx>( // Checked when type checking the function containing them. hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, // Can have different predicates to their defining use - hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias => { - } + hir::OpaqueTyOrigin::TyAlias => {} } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -828,7 +827,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { check_type_params_are_used(tcx, &generics, pty_ty); } hir::ItemKind::ForeignMod { abi, items } => { - check_abi(tcx, it.span, abi); + check_abi(tcx, it.hir_id(), it.span, abi); if abi == Abi::RustIntrinsic { for item in items { @@ -1382,7 +1381,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: &'tcx ty let non_zst_fields = field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None }); let non_zst_count = non_zst_fields.clone().count(); - if non_zst_count != 1 { + if non_zst_count >= 2 { bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp); } for (span, zst, align1) in field_infos { diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 236fec94bd..ba76b9c8dd 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -640,7 +640,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Object safety violations or miscellaneous. Err(err) => { - self.report_selection_error(&obligation, &err, false, false); + self.report_selection_error( + obligation.clone(), + &obligation, + &err, + false, + 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. @@ -1456,11 +1462,15 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected.is_unit(), pointing_at_return_type, ) { - // If the block is from an external macro, then do not suggest - // adding a semicolon, because there's nowhere to put it. - // See issue #81943. + // If the block is from an external macro or try (`?`) desugaring, then + // do not suggest adding a semicolon, because there's nowhere to put it. + // See issues #81943 and #87051. if cond_expr.span.desugaring_kind().is_none() && !in_external_macro(fcx.tcx.sess, cond_expr.span) + && !matches!( + cond_expr.kind, + hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) + ) { err.span_label(cond_expr.span, "expected this to be `()`"); if expr.can_have_side_effects() { @@ -1481,6 +1491,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, can_suggest, + fcx.tcx.hir().get_parent_item(id), ); } if !pointing_at_return_type { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 60ca562f99..d358688815 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -66,6 +66,10 @@ crate fn compare_impl_method<'tcx>( { return; } + + if let Err(ErrorReported) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) { + return; + } } fn compare_predicate_entailment<'tcx>( @@ -222,12 +226,7 @@ fn compare_predicate_entailment<'tcx>( let mut selcx = traits::SelectionContext::new(&infcx); let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs); - let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars( - impl_m_span, - infer::HigherRankedType, - ty::Binder::bind(impl_m_own_bounds.predicates, tcx), - ); - for predicate in impl_m_own_bounds { + for predicate in impl_m_own_bounds.predicates { let traits::Normalized { value: predicate, obligations } = traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate); @@ -258,14 +257,14 @@ fn compare_predicate_entailment<'tcx>( ); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig); - let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); - let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx)); + let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -579,7 +578,7 @@ fn compare_number_of_generics<'tcx>( let item_kind = assoc_item_kind_str(impl_); let mut err_occurred = false; - for &(kind, trait_count, impl_count) in &matchings { + for (kind, trait_count, impl_count) in matchings { if impl_count != trait_count { err_occurred = true; @@ -934,6 +933,68 @@ fn compare_synthetic_generics<'tcx>( if error_found { Err(ErrorReported) } else { Ok(()) } } +fn compare_const_param_types<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: &ty::AssocItem, + trait_m: &ty::AssocItem, + trait_item_span: Option, +) -> Result<(), ErrorReported> { + let const_params_of = |def_id| { + tcx.generics_of(def_id).params.iter().filter_map(|param| match param.kind { + GenericParamDefKind::Const { .. } => Some(param.def_id), + _ => None, + }) + }; + let const_params_impl = const_params_of(impl_m.def_id); + let const_params_trait = const_params_of(trait_m.def_id); + + for (const_param_impl, const_param_trait) in iter::zip(const_params_impl, const_params_trait) { + let impl_ty = tcx.type_of(const_param_impl); + let trait_ty = tcx.type_of(const_param_trait); + if impl_ty != trait_ty { + let (impl_span, impl_ident) = match tcx.hir().get_if_local(const_param_impl) { + Some(hir::Node::GenericParam(hir::GenericParam { span, name, .. })) => ( + span, + match name { + hir::ParamName::Plain(ident) => Some(ident), + _ => None, + }, + ), + other => bug!( + "expected GenericParam, found {:?}", + other.map_or_else(|| "nothing".to_string(), |n| format!("{:?}", n)) + ), + }; + let trait_span = match tcx.hir().get_if_local(const_param_trait) { + Some(hir::Node::GenericParam(hir::GenericParam { span, .. })) => Some(span), + _ => None, + }; + let mut err = struct_span_err!( + tcx.sess, + *impl_span, + E0053, + "method `{}` has an incompatible const parameter type for trait", + trait_m.ident + ); + err.span_note( + trait_span.map_or_else(|| trait_item_span.unwrap_or(*impl_span), |span| *span), + &format!( + "the const parameter{} has type `{}`, but the declaration \ + in trait `{}` has type `{}`", + &impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{}`", ident)), + impl_ty, + tcx.def_path_str(trait_m.def_id), + trait_ty + ), + ); + err.emit(); + return Err(ErrorReported); + } + } + + Ok(()) +} + crate fn compare_const_impl<'tcx>( tcx: TyCtxt<'tcx>, impl_c: &ty::AssocItem, diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 33bc25accb..3ea59906d3 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::AllowTwoPhase; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -201,7 +202,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sole_field = &variant.fields[0]; let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { - let variant_path = self.tcx.def_path_str(variant.def_id); + let variant_path = + with_no_trimmed_paths(|| self.tcx.def_path_str(variant.def_id)); // FIXME #56861: DRYer prelude filtering if let Some(path) = variant_path.strip_prefix("std::prelude::") { if let Some((_, path)) = path.split_once("::") { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index d0cbb58fb1..cfe1d1c687 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -466,7 +466,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span); + let (res, opt_ty, segs) = + self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); let ty = match res { Res::Err => { self.set_tainted_by_errors(); @@ -674,7 +675,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { if self.ret_coercion.is_none() { - self.tcx.sess.emit_err(ReturnStmtOutsideOfFnBody { span: expr.span }); + let mut err = ReturnStmtOutsideOfFnBody { + span: expr.span, + encl_body_span: None, + encl_fn_span: None, + }; + + let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); + + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(..), + span: encl_fn_span, + .. + })) + | Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), + span: encl_fn_span, + .. + })) + | Some(hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(..), + span: encl_fn_span, + .. + })) = self.tcx.hir().find(encl_item_id) + { + // We are inside a function body, so reporting "return statement + // outside of function body" needs an explanation. + + let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id); + + // 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); + + let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); + let encl_body = self.tcx.hir().body(encl_body_id); + + err.encl_body_span = Some(encl_body.value.span); + err.encl_fn_span = Some(*encl_fn_span); + } + + self.tcx.sess.emit_err(err); + + if let Some(e) = expr_opt { + // We still have to type-check `e` (issue #86188), but calling + // `check_return_expr` only works inside fn bodies. + self.check_expr(e); + } } else if let Some(e) = expr_opt { if self.ret_coercion_span.get().is_none() { self.ret_coercion_span.set(Some(e.span)); @@ -940,7 +987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // no need to check for bot/err -- callee does that let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t); - let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) { + let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) { Ok(method) => { // We could add a "consider `foo::`" suggestion here, but I wasn't able to // trigger this codepath causing `structuraly_resolved_type` to emit an error. diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 96569ae0e7..865e4ccc0b 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -39,7 +39,8 @@ use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::opaque_types::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ - self, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt, + self, ObligationCause, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt, + WellFormedLoc, }; use std::collections::hash_map::Entry; @@ -408,6 +409,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { value } + /// Convenience method which tracks extra diagnostic information for normalization + /// that occurs as a result of WF checking. The `hir_id` is the `HirId` of the hir item + /// whose type is being wf-checked - this is used to construct a more precise span if + /// an error occurs. + /// + /// It is never necessary to call this method - calling `normalize_associated_types_in` will + /// just result in a slightly worse diagnostic span, and will still be sound. + pub(in super::super) fn normalize_associated_types_in_wf( + &self, + span: Span, + value: T, + loc: WellFormedLoc, + ) -> T + where + T: TypeFoldable<'tcx>, + { + self.inh.normalize_associated_types_in_with_cause( + ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(Some(loc))), + self.param_env, + value, + ) + } + pub(in super::super) fn normalize_associated_types_in(&self, span: Span, value: T) -> T where T: TypeFoldable<'tcx>, @@ -423,7 +447,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { where T: TypeFoldable<'tcx>, { - self.inh.partially_normalize_associated_types_in(span, self.body_id, self.param_env, value) + self.inh.partially_normalize_associated_types_in( + ObligationCause::misc(span, self.body_id), + self.param_env, + value, + ) } pub fn require_type_meets( @@ -906,13 +934,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Resolves an associated value path into a base type and associated constant, or method /// resolution. The newly resolved definition is written into `type_dependent_defs`. - pub fn resolve_ty_and_res_ufcs( + pub fn resolve_ty_and_res_fully_qualified_call( &self, qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { - debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span); + debug!( + "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", + qpath, hir_id, span + ); let (ty, qself, item_segment) = match *qpath { QPath::Resolved(ref opt_qself, ref path) => { return ( @@ -922,7 +953,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment), - QPath::LangItem(..) => bug!("`resolve_ty_and_res_ufcs` called on `LangItem`"), + QPath::LangItem(..) => { + bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") + } }; if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id) { @@ -932,25 +965,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return (def, Some(ty), slice::from_ref(&**item_segment)); } let item_name = item_segment.ident; - let result = self.resolve_ufcs(span, item_name, ty, hir_id).or_else(|error| { - let result = match error { - method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), - _ => Err(ErrorReported), - }; - if item_name.name != kw::Empty { - if let Some(mut e) = self.report_method_error( - span, - ty, - item_name, - SelfSource::QPath(qself), - error, - None, - ) { - e.emit(); + let result = self + .resolve_fully_qualified_call(span, item_name, ty, qself.span, hir_id) + .or_else(|error| { + let result = match error { + method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), + _ => Err(ErrorReported), + }; + if item_name.name != kw::Empty { + if let Some(mut e) = self.report_method_error( + span, + ty, + item_name, + SelfSource::QPath(qself), + error, + None, + ) { + e.emit(); + } } - } - result - }); + result + }); if result.is_ok() { self.maybe_lint_bare_trait(qpath, hir_id); @@ -1544,6 +1579,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Add all the obligations that are required, substituting and normalized appropriately. + #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) { let (bounds, spans) = self.instantiate_bounds(span, def_id, &substs); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 49aea19c8d..f65cc429fb 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -11,7 +11,7 @@ use crate::check::{ use rustc_ast as ast; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ExprKind, Node, QPath}; use rustc_middle::ty::adjustment::AllowTwoPhase; @@ -120,8 +120,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error_code: &str, c_variadic: bool, sugg_unit: bool| { - let (span, start_span, args) = match &expr.kind { - hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]), + let (span, start_span, args, ctor_of) = match &expr.kind { + hir::ExprKind::Call( + hir::Expr { + span, + kind: + hir::ExprKind::Path(hir::QPath::Resolved( + _, + hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. }, + )), + .. + }, + args, + ) => (*span, *span, &args[..], Some(of)), + hir::ExprKind::Call(hir::Expr { span, .. }, args) => { + (*span, *span, &args[..], None) + } hir::ExprKind::MethodCall(path_segment, span, args, _) => ( *span, // `sp` doesn't point at the whole `foo.bar()`, only at `bar`. @@ -137,6 +151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .unwrap_or(*span), &args[1..], // Skip the receiver. + None, // methods are never ctors ), k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k), }; @@ -157,7 +172,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = tcx.sess.struct_span_err_with_code( span, &format!( - "this function takes {}{} but {} {} supplied", + "this {} takes {}{} but {} {} supplied", + match ctor_of { + Some(CtorOf::Struct) => "struct", + Some(CtorOf::Variant) => "enum variant", + None => "function", + }, if c_variadic { "at least " } else { "" }, potentially_plural_count(expected_count, "argument"), potentially_plural_count(arg_count, "argument"), @@ -291,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // that are not closures, then we type-check the closures. This is so // that we have more information about the types of arguments when we // type-check the functions. This isn't really the right way to do this. - for &check_closures in &[false, true] { + for check_closures in [false, true] { debug!("check_closures={}", check_closures); // More awful hacks: before we check argument types, try to do diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 4da4835f7c..13686cfec8 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -15,7 +15,6 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; -use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; @@ -175,13 +174,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { } fn default_constness_for_trait_bounds(&self) -> hir::Constness { - // FIXME: refactor this into a method - let node = self.tcx.hir().get(self.body_id); - if let Some(fn_like) = FnLikeNode::from_node(node) { - fn_like.constness() - } else { - hir::Constness::NotConst - } + self.tcx.hir().get(self.body_id).constness() } fn get_type_parameter_bounds( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index d6b1e56316..54aab271fd 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -52,9 +52,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut pointing_at_return_type = false; if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { - pointing_at_return_type = - self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); + pointing_at_return_type = self.suggest_missing_return_type( + err, + &fn_decl, + expected, + found, + can_suggest, + fn_id, + ); self.suggest_missing_break_or_return_expr( err, expr, &fn_decl, expected, found, blk_id, fn_id, ); @@ -433,6 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, can_suggest: bool, + fn_id: hir::HirId, ) -> bool { // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()` or an impl). @@ -465,7 +472,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = >::ast_ty_to_ty(self, ty); debug!("suggest_missing_return_type: return type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty); - if ty.kind() == expected.kind() { + let bound_vars = self.tcx.late_bound_vars(fn_id); + let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); + let ty = self.normalize_associated_types_in(sp, ty); + if self.can_coerce(expected, ty) { err.span_label(sp, format!("expected `{}` because of return type", expected)); return true; } diff --git a/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_typeck/src/check/gather_locals.rs index 2683e886ee..4ebfd7fd21 100644 --- a/compiler/rustc_typeck/src/check/gather_locals.rs +++ b/compiler/rustc_typeck/src/check/gather_locals.rs @@ -4,12 +4,11 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::PatKind; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::Ty; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_trait_selection::traits; pub(super) struct GatherLocalsVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, - parent_id: hir::HirId, // parameters are special cases of patterns, but we want to handle them as // *distinct* cases. so track when we are hitting a pattern *within* an fn // parameter. @@ -17,8 +16,8 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> { } impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { - pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self { - Self { fcx, parent_id, outermost_fn_param_pat: None } + pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>) -> Self { + Self { fcx, outermost_fn_param_pat: None } } fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option>) -> Ty<'tcx> { @@ -57,26 +56,15 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { Some(ref ty) => { let o_ty = self.fcx.to_ty(&ty); - let revealed_ty = self.fcx.instantiate_opaque_types_from_value( - self.parent_id, - o_ty, - ty.span, - Some(sym::impl_trait_in_bindings), - ); - - let c_ty = - self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(revealed_ty)); - debug!( - "visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}", - ty.hir_id, o_ty, revealed_ty, c_ty - ); + let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty)); + debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx .typeck_results .borrow_mut() .user_provided_types_mut() .insert(ty.hir_id, c_ty); - Some(LocalTy { decl_ty: o_ty, revealed_ty }) + Some(LocalTy { decl_ty: o_ty, revealed_ty: o_ty }) } None => None, }; diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 2e9bef15f9..7e43e36fe5 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::{self, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::opaque_types::OpaqueTypeDecl; -use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt}; +use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt}; use std::cell::RefCell; use std::ops::Deref; @@ -162,7 +162,24 @@ impl Inherited<'a, 'tcx> { where T: TypeFoldable<'tcx>, { - let ok = self.partially_normalize_associated_types_in(span, body_id, param_env, value); + self.normalize_associated_types_in_with_cause( + ObligationCause::misc(span, body_id), + param_env, + value, + ) + } + + pub(super) fn normalize_associated_types_in_with_cause( + &self, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: T, + ) -> T + where + T: TypeFoldable<'tcx>, + { + let ok = self.partially_normalize_associated_types_in(cause, param_env, value); + debug!(?ok); self.register_infer_ok_obligations(ok) } } diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 5741b6824b..6661df21ed 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -3,11 +3,11 @@ use crate::errors::{ SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, - WrongNumberOfTypeArgumentsToInstrinsic, + WrongNumberOfGenericArgumentsToIntrinsic, }; use crate::require_same_types; -use rustc_errors::struct_span_err; +use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::Subst; @@ -21,41 +21,54 @@ fn equate_intrinsic_type<'tcx>( tcx: TyCtxt<'tcx>, it: &hir::ForeignItem<'_>, n_tps: usize, + n_lts: usize, sig: ty::PolyFnSig<'tcx>, ) { - match it.kind { - hir::ForeignItemKind::Fn(..) => {} + 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(); + (own_counts, generics.span) + } _ => { struct_span_err!(tcx.sess, it.span, E0622, "intrinsic must be a function") .span_label(it.span, "expected a function") .emit(); return; } - } + }; - let i_n_tps = tcx.generics_of(it.def_id).own_counts().types; - if i_n_tps != n_tps { - let span = match it.kind { - hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span, - _ => bug!(), - }; + let gen_count_ok = |found: usize, expected: usize, descr: &str| -> bool { + if found != expected { + tcx.sess.emit_err(WrongNumberOfGenericArgumentsToIntrinsic { + span, + found, + expected, + expected_pluralize: pluralize!(expected), + descr, + }); + false + } else { + true + } + }; - tcx.sess.emit_err(WrongNumberOfTypeArgumentsToInstrinsic { - span, - found: i_n_tps, - expected: n_tps, - }); - return; + if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime") + && gen_count_ok(own_counts.types, n_tps, "type") + && gen_count_ok(own_counts.consts, 0, "const") + { + let fty = tcx.mk_fn_ptr(sig); + let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); } - - 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); } -/// Returns `true` if the given intrinsic is unsafe to call or not. +/// Returns the unsafety of the given intrinsic. pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety { match intrinsic { + // 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 + // safe extern fns are otherwise unprecedented. sym::abort | sym::size_of | sym::min_align_of @@ -121,7 +134,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }) }; - let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") { + let (n_tps, n_lts, inputs, output, unsafety) = if name_str.starts_with("atomic_") { let split: Vec<&str> = name_str.split('_').collect(); assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format"); @@ -143,7 +156,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { return; } }; - (n_tps, inputs, output, hir::Unsafety::Unsafe) + (n_tps, 0, inputs, output, hir::Unsafety::Unsafe) } else { let unsafety = intrinsic_operation_unsafety(intrinsic_name); let (n_tps, inputs, output) = match intrinsic_name { @@ -367,16 +380,23 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), + sym::raw_eq => { + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; + let param_ty = + tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)); + (1, vec![param_ty; 2], tcx.types.bool) + } + other => { tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other }); return; } }; - (n_tps, inputs, output, unsafety) + (n_tps, 0, inputs, output, unsafety) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, n_lts, sig) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -472,5 +492,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) Abi::PlatformIntrinsic, ); let sig = ty::Binder::dummy(sig); - equate_intrinsic_type(tcx, it, n_tps, sig) + equate_intrinsic_type(tcx, it, n_tps, 0, sig) } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index f546a0d896..75299bae5d 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -101,6 +101,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let (method_sig, method_predicates) = self.normalize_associated_types_in(self.span, (method_sig, method_predicates)); + let method_sig = ty::Binder::dummy(method_sig); // Make sure nobody calls `drop()` explicitly. self.enforce_illegal_method_limitations(&pick); @@ -119,12 +120,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We won't add these if we encountered an illegal sized bound, so that we can use // a custom error in that case. if illegal_sized_bound.is_none() { - let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx)); - self.add_obligations(method_ty, all_substs, method_predicates); + self.add_obligations(self.tcx.mk_fn_ptr(method_sig), all_substs, method_predicates); } // Create the final `MethodCallee`. - let callee = MethodCallee { def_id: pick.item.def_id, substs: all_substs, sig: method_sig }; + let callee = MethodCallee { + def_id: pick.item.def_id, + substs: all_substs, + sig: method_sig.skip_binder(), + }; ConfirmResult { callee, illegal_sized_bound } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 427102afee..2136d92542 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -3,6 +3,7 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/method-lookup.html mod confirm; +mod prelude2021; pub mod probe; mod suggest; @@ -173,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// # Arguments /// - /// Given a method call like `foo.bar::(...)`: + /// Given a method call like `foo.bar::(a, b + 1, ...)`: /// /// * `self`: the surrounding `FnCtxt` (!) /// * `self_ty`: the (unadjusted) type of the self expression (`foo`) @@ -181,6 +182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// * `span`: the span for the method call /// * `call_expr`: the complete method call: (`foo.bar::(...)`) /// * `self_expr`: the self expression (`foo`) + /// * `args`: the expressions of the arguments (`a, b + 1, ...`) #[instrument(level = "debug", skip(self, call_expr, self_expr))] pub fn lookup_method( &self, @@ -189,6 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, + args: &'tcx [hir::Expr<'tcx>], ) -> Result, MethodError<'tcx>> { debug!( "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})", @@ -198,6 +201,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let pick = self.lookup_probe(span, segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?; + self.lint_dot_call_from_2018(self_ty, segment, span, call_expr, self_expr, &pick, args); + for import_id in &pick.import_ids { debug!("used_trait_import: {:?}", import_id); Lrc::get_mut(&mut self.typeck_results.borrow_mut().used_trait_imports) @@ -399,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); // Also add an obligation for the method type being well-formed. - let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx)); + let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig)); debug!( "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation @@ -417,16 +422,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(InferOk { obligations, value: callee }) } + /// Performs a [full-qualified function call] (formerly "universal function call") lookup. If + /// lookup is successful, it will return the type of definition and the [`DefId`] of the found + /// function definition. + /// + /// [full-qualified function call]: https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls + /// + /// # Arguments + /// + /// Given a function call like `Foo::bar::(...)`: + /// + /// * `self`: the surrounding `FnCtxt` (!) + /// * `span`: the span of the call, excluding arguments (`Foo::bar::`) + /// * `method_name`: the identifier of the function within the container type (`bar`) + /// * `self_ty`: the type to search within (`Foo`) + /// * `self_ty_span` the span for the type being searched within (span of `Foo`) + /// * `expr_id`: the [`hir::HirId`] of the expression composing the entire call #[instrument(level = "debug", skip(self))] - pub fn resolve_ufcs( + pub fn resolve_fully_qualified_call( &self, span: Span, method_name: Ident, self_ty: Ty<'tcx>, + self_ty_span: Span, expr_id: hir::HirId, ) -> Result<(DefKind, DefId), MethodError<'tcx>> { debug!( - "resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", + "resolve_fully_qualified_call: method_name={:?} self_ty={:?} expr_id={:?}", method_name, self_ty, expr_id, ); @@ -463,18 +485,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_id, ProbeScope::TraitsInScope, )?; - debug!("resolve_ufcs: pick={:?}", pick); + + self.lint_fully_qualified_call_from_2018( + span, + method_name, + self_ty, + self_ty_span, + expr_id, + &pick, + ); + + debug!("resolve_fully_qualified_call: pick={:?}", pick); { let mut typeck_results = self.typeck_results.borrow_mut(); let used_trait_imports = Lrc::get_mut(&mut typeck_results.used_trait_imports).unwrap(); for import_id in pick.import_ids { - debug!("resolve_ufcs: used_trait_import: {:?}", import_id); + debug!("resolve_fully_qualified_call: used_trait_import: {:?}", import_id); used_trait_imports.insert(import_id); } } let def_kind = pick.item.kind.as_def_kind(); - debug!("resolve_ufcs: def_kind={:?}, def_id={:?}", def_kind, pick.item.def_id); + debug!( + "resolve_fully_qualified_call: def_kind={:?}, def_id={:?}", + def_kind, pick.item.def_id + ); tcx.check_stability(pick.item.def_id, Some(expr_id), span, Some(method_name.span)); Ok((def_kind, pick.item.def_id)) } diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs new file mode 100644 index 0000000000..f13e23914f --- /dev/null +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -0,0 +1,358 @@ +use hir::def_id::DefId; +use hir::HirId; +use hir::ItemKind; +use rustc_ast::Mutability; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::{Ref, Ty}; +use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS; +use rustc_span::symbol::kw::Underscore; +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, + self_ty: Ty<'tcx>, + segment: &hir::PathSegment<'_>, + span: Span, + call_expr: &'tcx hir::Expr<'tcx>, + self_expr: &'tcx hir::Expr<'tcx>, + pick: &Pick<'tcx>, + args: &'tcx [hir::Expr<'tcx>], + ) { + debug!( + "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})", + segment.ident, self_ty, call_expr, self_expr + ); + + // Rust 2021 and later is already using the new prelude + if span.rust_2021() { + return; + } + + // These are the method names that were added to prelude in Rust 2021 + if !matches!(segment.ident.name, sym::try_into) { + return; + } + + // No need to lint if method came from std/core, as that will now be in the prelude + if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) { + return; + } + + if matches!(pick.kind, probe::PickKind::InherentImplPick | probe::PickKind::ObjectPick) { + // avoid repeatedly adding unneeded `&*`s + if pick.autoderefs == 1 + && matches!( + pick.autoref_or_ptr_adjustment, + Some(probe::AutorefOrPtrAdjustment::Autoref { .. }) + ) + && matches!(self_ty.kind(), Ref(..)) + { + return; + } + + // if it's an inherent `self` method (not `&self` or `&mut self`), it will take + // precedence over the `TryInto` impl, and thus won't break in 2021 edition + if pick.autoderefs == 0 && pick.autoref_or_ptr_adjustment.is_none() { + return; + } + + // Inherent impls only require not relying on autoref and autoderef in order to + // ensure that the trait implementation won't be used + self.tcx.struct_span_lint_hir( + RUST_2021_PRELUDE_COLLISIONS, + self_expr.hir_id, + self_expr.span, + |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 { + Some(probe::AutorefOrPtrAdjustment::Autoref { + mutbl: Mutability::Mut, + .. + }) => "&mut ", + Some(probe::AutorefOrPtrAdjustment::Autoref { + mutbl: Mutability::Not, + .. + }) => "&", + Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "", + }; + if let Ok(self_expr) = self.sess().source_map().span_to_snippet(self_expr.span) + { + let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) = + pick.autoref_or_ptr_adjustment + { + format!("{}{} as *const _", derefs, self_expr) + } else { + format!("{}{}{}", autoref, derefs, self_expr) + }; + + lint.span_suggestion( + sp, + "disambiguate the method call", + format!("({})", self_adjusted), + Applicability::MachineApplicable, + ); + } else { + let self_adjusted = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) = + pick.autoref_or_ptr_adjustment + { + format!("{}(...) as *const _", derefs) + } else { + format!("{}{}...", autoref, derefs) + }; + lint.span_help( + sp, + &format!("disambiguate the method call with `({})`", self_adjusted,), + ); + } + + lint.emit(); + }, + ); + } else { + // trait implementations require full disambiguation to not clash with the new prelude + // additions (i.e. convert from dot-call to fully-qualified call) + self.tcx.struct_span_lint_hir( + RUST_2021_PRELUDE_COLLISIONS, + call_expr.hir_id, + call_expr.span, + |lint| { + let sp = call_expr.span; + let trait_name = self.trait_path_or_bare_name( + span, + call_expr.hir_id, + pick.item.container.id(), + ); + + 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); + if precise { + let args = args + .iter() + .skip(1) + .map(|arg| { + format!( + ", {}", + self.sess().source_map().span_to_snippet(arg.span).unwrap() + ) + }) + .collect::(); + + lint.span_suggestion( + sp, + "disambiguate the associated function", + format!( + "{}::{}({}{})", + trait_name, segment.ident.name, self_adjusted, args + ), + Applicability::MachineApplicable, + ); + } else { + lint.span_help( + sp, + &format!( + "disambiguate the associated function with `{}::{}(...)`", + trait_name, segment.ident, + ), + ); + } + + lint.emit(); + }, + ); + } + } + + pub(super) fn lint_fully_qualified_call_from_2018( + &self, + span: Span, + method_name: Ident, + self_ty: Ty<'tcx>, + self_ty_span: Span, + expr_id: hir::HirId, + pick: &Pick<'tcx>, + ) { + // Rust 2021 and later is already using the new prelude + if span.rust_2021() { + return; + } + + // These are the fully qualified methods added to prelude in Rust 2021 + if !matches!(method_name.name, sym::try_into | sym::try_from | sym::from_iter) { + return; + } + + // No need to lint if method came from std/core, as that will now be in the prelude + if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) { + return; + } + + // For from_iter, check if the type actually implements FromIterator. + // If we know it does not, we don't need to warn. + if method_name.name == sym::from_iter { + if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) { + if !self + .infcx + .type_implements_trait( + trait_def_id, + self_ty, + InternalSubsts::empty(), + self.param_env, + ) + .may_apply() + { + return; + } + } + } + + // No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`, + // since such methods take precedence over trait methods. + if matches!(pick.kind, probe::PickKind::InherentImplPick) { + 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 trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id()); + let trait_generics = self.tcx.generics_of(pick.item.container.id()); + + let parameter_count = trait_generics.count() - (trait_generics.has_self as usize); + let trait_name = if parameter_count == 0 { + trait_path + } else { + format!( + "{}<{}>", + trait_path, + std::iter::repeat("_").take(parameter_count).collect::>().join(", ") + ) + }; + + let mut lint = lint.build(&format!( + "trait-associated function `{}` will become ambiguous in Rust 2021", + method_name.name + )); + + let self_ty = self + .sess() + .source_map() + .span_to_snippet(self_ty_span) + .unwrap_or_else(|_| self_ty.to_string()); + + lint.span_suggestion( + span, + "disambiguate the associated function", + format!("<{} as {}>::{}", self_ty, trait_name, method_name.name,), + Applicability::MachineApplicable, + ); + + lint.emit(); + }); + } + + fn trait_path_or_bare_name( + &self, + span: Span, + expr_hir_id: HirId, + trait_def_id: DefId, + ) -> String { + self.trait_path(span, expr_hir_id, trait_def_id).unwrap_or_else(|| { + let key = self.tcx.def_key(trait_def_id); + format!("{}", key.disambiguated_data.data) + }) + } + + fn trait_path(&self, span: Span, expr_hir_id: HirId, trait_def_id: DefId) -> Option { + let applicable_traits = self.tcx.in_scope_traits(expr_hir_id)?; + let applicable_trait = applicable_traits.iter().find(|t| t.def_id == trait_def_id)?; + if applicable_trait.import_ids.is_empty() { + // The trait was declared within the module, we only need to use its name. + return None; + } + + let import_items: Vec<_> = applicable_trait + .import_ids + .iter() + .map(|&import_id| { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id); + self.tcx.hir().expect_item(hir_id) + }) + .collect(); + + // Find an identifier with which this trait was imported (note that `_` doesn't count). + let any_id = import_items + .iter() + .filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None }) + .next(); + if let Some(any_id) = any_id { + return Some(format!("{}", any_id)); + } + + // All that is left is `_`! We need to use the full path. It doesn't matter which one we pick, + // so just take the first one. + match import_items[0].kind { + ItemKind::Use(path, _) => Some( + path.segments + .iter() + .map(|segment| segment.ident.to_string()) + .collect::>() + .join("::"), + ), + _ => { + span_bug!(span, "unexpected item kind, expected a use: {:?}", import_items[0].kind); + } + } + } + + /// Creates a string version of the `expr` that includes explicit adjustments. + /// Returns the string and also a bool indicating whther this is a *precise* + /// suggestion. + fn adjust_expr(&self, pick: &Pick<'tcx>, expr: &hir::Expr<'tcx>) -> (String, bool) { + let derefs = "*".repeat(pick.autoderefs); + + let autoref = match pick.autoref_or_ptr_adjustment { + Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl: Mutability::Mut, .. }) => "&mut ", + Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl: Mutability::Not, .. }) => "&", + Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "", + }; + + let (expr_text, precise) = + if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { + (expr_text, true) + } else { + (format!("(..)"), false) + }; + + let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) = + pick.autoref_or_ptr_adjustment + { + format!("{}{} as *const _", derefs, expr_text) + } else { + format!("{}{}{}", autoref, derefs, expr_text) + }; + + (adjusted_text, precise) + } +} diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 440e0f4e1a..9037ffe49a 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -668,7 +668,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::Slice(_) => { - for &lang_def_id in &[ + for lang_def_id in [ lang_items.slice_impl(), lang_items.slice_u8_impl(), lang_items.slice_alloc_impl(), diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 16382c7e7a..77586ce485 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -933,6 +933,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name ); err.span_label(item_name.span, &format!("private {}", kind)); + let sp = self + .tcx + .hir() + .span_if_local(def_id) + .unwrap_or_else(|| self.tcx.def_span(def_id)); + err.span_label(sp, &format!("private {} defined here", kind)); self.suggest_valid_traits(&mut err, out_of_scope_traits); err.emit(); } @@ -1591,7 +1597,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { _ => {} } } - for &cnum in tcx.crates().iter() { + for &cnum in tcx.crates(()).iter() { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id)); } @@ -1650,16 +1656,16 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { _ => { if self.span.map_or(true, |span| item.span < span) { if !item.span.from_expansion() { + self.span = Some(item.span.shrink_to_lo()); // Don't insert between attributes and an item. let attrs = self.tcx.hir().attrs(item.hir_id()); - if attrs.is_empty() { - self.span = Some(item.span.shrink_to_lo()); - } else { - // Find the first attribute on the item. - for attr in attrs { - if self.span.map_or(true, |span| attr.span < span) { - self.span = Some(attr.span.shrink_to_lo()); - } + // Find the first attribute on the item. + // FIXME: This is broken for active attributes. + for attr in attrs { + if !attr.span.is_dummy() + && self.span.map_or(true, |span| attr.span < span) + { + self.span = Some(attr.span.shrink_to_lo()); } } } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index ad7853b7cd..d30b057e26 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -112,17 +112,15 @@ use rustc_hir::{HirIdMap, ImplicitSelfKind, Node}; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{self, RegionKind, Ty, TyCtxt, UserType}; +use rustc_middle::ty::{self, Ty, TyCtxt, UserType}; use rustc_session::config; 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, MultiSpan, Span}; -use rustc_span::{source_map::DUMMY_SP, sym}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; @@ -174,13 +172,12 @@ impl Needs { pub struct UnsafetyState { pub def: hir::HirId, pub unsafety: hir::Unsafety, - pub unsafe_push_count: u32, from_fn: bool, } impl UnsafetyState { pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState { - UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true } + UnsafetyState { def, unsafety, from_fn: true } } pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState { @@ -193,19 +190,11 @@ impl UnsafetyState { hir::Unsafety::Unsafe if self.from_fn => self, unsafety => { - let (unsafety, def, count) = match blk.rules { - BlockCheckMode::PushUnsafeBlock(..) => { - (unsafety, blk.hir_id, self.unsafe_push_count.checked_add(1).unwrap()) - } - BlockCheckMode::PopUnsafeBlock(..) => { - (unsafety, blk.hir_id, self.unsafe_push_count.checked_sub(1).unwrap()) - } - BlockCheckMode::UnsafeBlock(..) => { - (hir::Unsafety::Unsafe, blk.hir_id, self.unsafe_push_count) - } - BlockCheckMode::DefaultBlock => (unsafety, self.def, self.unsafe_push_count), + let (unsafety, def) = match blk.rules { + BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id), + BlockCheckMode::DefaultBlock => (unsafety, self.def), }; - UnsafetyState { def, unsafety, unsafe_push_count: count, from_fn: false } + UnsafetyState { def, unsafety, from_fn: false } } } } @@ -330,117 +319,6 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet Self::MyItem -/// } -/// impl MyTrait for T where T: Iterator { -/// type MyItem = impl Iterator; -/// fn use_it(self) -> Self::MyItem { -/// self -/// } -/// } -/// ``` -/// -/// When we normalize the signature of `use_it` from the impl block, -/// we will normalize `Self::MyItem` to the opaque type `impl Iterator` -/// However, this projection result may contain inference variables, due -/// to the way that projection works. We didn't have any inference variables -/// in the signature to begin with - leaving them in will cause us to incorrectly -/// conclude that we don't have a defining use of `MyItem`. By mapping inference -/// variables back to the actual generic parameters, we will correctly see that -/// we have a defining use of `MyItem` -fn fixup_opaque_types<'tcx, T>(tcx: TyCtxt<'tcx>, val: T) -> T -where - T: TypeFoldable<'tcx>, -{ - struct FixupFolder<'tcx> { - tcx: TyCtxt<'tcx>, - } - - impl<'tcx> TypeFolder<'tcx> for FixupFolder<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Opaque(def_id, substs) => { - debug!("fixup_opaque_types: found type {:?}", ty); - // Here, we replace any inference variables that occur within - // the substs of an opaque type. By definition, any type occurring - // in the substs has a corresponding generic parameter, which is what - // we replace it with. - // This replacement is only run on the function signature, so any - // inference variables that we come across must be the rust of projection - // (there's no other way for a user to get inference variables into - // a function signature). - if ty.needs_infer() { - let new_substs = InternalSubsts::for_item(self.tcx, def_id, |param, _| { - let old_param = substs[param.index as usize]; - match old_param.unpack() { - GenericArgKind::Type(old_ty) => { - if let ty::Infer(_) = old_ty.kind() { - // Replace inference type with a generic parameter - self.tcx.mk_param_from_def(param) - } else { - old_param.fold_with(self) - } - } - GenericArgKind::Const(old_const) => { - if let ty::ConstKind::Infer(_) = old_const.val { - // This should never happen - we currently do not support - // 'const projections', e.g.: - // `impl MyTrait for T where ::MyConst == 25` - // which should be the only way for us to end up with a const inference - // variable after projection. If Rust ever gains support for this kind - // of projection, this should *probably* be changed to - // `self.tcx.mk_param_from_def(param)` - bug!( - "Found infer const: `{:?}` in opaque type: {:?}", - old_const, - ty - ); - } else { - old_param.fold_with(self) - } - } - GenericArgKind::Lifetime(old_region) => { - if let RegionKind::ReVar(_) = old_region { - self.tcx.mk_param_from_def(param) - } else { - old_param.fold_with(self) - } - } - } - }); - let new_ty = self.tcx.mk_opaque(def_id, new_substs); - debug!("fixup_opaque_types: new type: {:?}", new_ty); - new_ty - } else { - ty - } - } - _ => ty.super_fold_with(self), - } - } - } - - debug!("fixup_opaque_types({:?})", val); - val.fold_with(&mut FixupFolder { tcx }) -} - fn typeck_const_arg<'tcx>( tcx: TyCtxt<'tcx>, (did, param_did): (LocalDefId, DefId), @@ -508,7 +386,7 @@ fn typeck_with_fallback<'tcx>( tcx.fn_sig(def_id) }; - check_abi(tcx, span, fn_sig.abi()); + check_abi(tcx, id, span, fn_sig.abi()); // Compute the fty from point of view of inside the fn. let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); @@ -519,8 +397,6 @@ fn typeck_with_fallback<'tcx>( fn_sig, ); - let fn_sig = fixup_opaque_types(tcx, fn_sig); - let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0; fcx } else { @@ -565,19 +441,12 @@ fn typeck_with_fallback<'tcx>( 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); - let revealed_ty = fcx.instantiate_opaque_types_from_value( - id, - expected_type, - body.value.span, - Some(sym::impl_trait_in_bindings), - ); - // Gather locals in statics (because of block expressions). - GatherLocalsVisitor::new(&fcx, id).visit_body(body); + GatherLocalsVisitor::new(&fcx).visit_body(body); - fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None); + fcx.check_expr_coercable_to_type(&body.value, expected_type, None); - fcx.write_ty(id, revealed_ty); + fcx.write_ty(id, expected_type); fcx }; @@ -697,66 +566,6 @@ fn get_owner_return_paths( }) } -/// Emit an error for recursive opaque types in a `let` binding. -fn binding_opaque_type_cycle_error( - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, - span: Span, - partially_expanded_type: Ty<'tcx>, -) { - let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type"); - err.span_label(span, "cannot resolve opaque type"); - // Find the owner that declared this `impl Trait` type. - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let mut prev_hir_id = hir_id; - let mut hir_id = tcx.hir().get_parent_node(hir_id); - while let Some(node) = tcx.hir().find(hir_id) { - match node { - hir::Node::Local(hir::Local { - pat, - init: None, - ty: Some(ty), - source: hir::LocalSource::Normal, - .. - }) => { - err.span_label(pat.span, "this binding might not have a concrete type"); - err.span_suggestion_verbose( - ty.span.shrink_to_hi(), - "set the binding to a value for a concrete type to be resolved", - " = /* value */".to_string(), - Applicability::HasPlaceholders, - ); - } - hir::Node::Local(hir::Local { - init: Some(expr), - source: hir::LocalSource::Normal, - .. - }) => { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let typeck_results = - tcx.typeck(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id))); - if let Some(ty) = typeck_results.node_type_opt(expr.hir_id) { - err.span_label( - expr.span, - &format!( - "this is of type `{}`, which doesn't constrain \ - `{}` enough to arrive to a concrete type", - ty, partially_expanded_type - ), - ); - } - } - _ => {} - } - if prev_hir_id == hir_id { - break; - } - prev_hir_id = hir_id; - hir_id = tcx.hir().get_parent_node(hir_id); - } - err.emit(); -} - // 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) { @@ -858,7 +667,7 @@ fn missing_items_err( // Obtain the level of indentation ending in `sugg_sp`. let indentation = tcx.sess.source_map().span_to_margin(sugg_sp).unwrap_or(0); // Make the whitespace that will make the suggestion have the right indentation. - let padding: String = std::iter::repeat(" ").take(indentation).collect(); + let padding: String = " ".repeat(indentation); for trait_item in missing_items { let snippet = suggestion_signature(&trait_item, tcx); @@ -1029,7 +838,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String { } } -/// Emit an error when encountering more or less than one variant in a transparent enum. +/// Emit an error when encountering two or more variants in a transparent enum. fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) { let variant_spans: Vec<_> = adt .variants @@ -1048,7 +857,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d err.emit(); } -/// Emit an error when encountering more or less than one non-zero-sized field in a transparent +/// Emit an error when encountering two or more non-zero-sized fields in a transparent /// enum. fn bad_non_zero_sized_fields<'tcx>( tcx: TyCtxt<'tcx>, @@ -1057,7 +866,7 @@ fn bad_non_zero_sized_fields<'tcx>( field_spans: impl Iterator, sp: Span, ) { - let msg = format!("needs exactly one non-zero-sized field, but has {}", field_count); + let msg = format!("needs at most one non-zero-sized field, but has {}", field_count); let mut err = struct_span_err!( tcx.sess, sp, diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 3ac760e236..981a040e66 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -160,7 +160,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ti: TopInfo<'tcx>, ) { let path_res = match &pat.kind { - PatKind::Path(qpath) => Some(self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span)), + PatKind::Path(qpath) => { + Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) + } _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); @@ -862,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &'tcx Pat<'tcx>, qpath: &'tcx hir::QPath<'tcx>, - subpats: &'tcx [&'tcx Pat<'tcx>], + subpats: &'tcx [Pat<'tcx>], ddpos: Option, expected: Ty<'tcx>, def_bm: BindingMode, @@ -904,7 +906,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Resolve the path and check the definition for errors. - let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span); + let (res, opt_ty, segments) = + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); if res == Res::Err { self.set_tainted_by_errors(); on_error(); @@ -979,7 +982,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_span: Span, res: Res, qpath: &hir::QPath<'_>, - subpats: &'tcx [&'tcx Pat<'tcx>], + subpats: &'tcx [Pat<'tcx>], fields: &'tcx [ty::FieldDef], expected: Ty<'tcx>, had_err: bool, @@ -1109,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_tuple( &self, span: Span, - elements: &'tcx [&'tcx Pat<'tcx>], + elements: &'tcx [Pat<'tcx>], ddpos: Option, expected: Ty<'tcx>, def_bm: BindingMode, @@ -1743,9 +1746,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_slice( &self, span: Span, - before: &'tcx [&'tcx Pat<'tcx>], + before: &'tcx [Pat<'tcx>], slice: Option<&'tcx Pat<'tcx>>, - after: &'tcx [&'tcx Pat<'tcx>], + after: &'tcx [Pat<'tcx>], expected: Ty<'tcx>, def_bm: BindingMode, ti: TopInfo<'tcx>, diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 652b82f106..055072d3a1 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr, base_expr, adjusted_ty, index_ty ); - for &unsize in &[false, true] { + for unsize in [false, true] { let mut self_ty = adjusted_ty; if unsize { // We only unsize arrays here. diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 6baa185406..39874f48eb 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -42,12 +42,15 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts}; +use rustc_middle::ty::{ + self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarCapture, UpvarSubsts, +}; use rustc_session::lint; use rustc_span::sym; use rustc_span::{MultiSpan, Span, Symbol}; -use rustc_trait_selection::traits::{Obligation, ObligationCause}; +use rustc_trait_selection::infer::InferCtxtExt; +use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::stable_set::FxHashSet; use rustc_index::vec::Idx; use rustc_target::abi::VariantIdx; @@ -79,6 +82,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } +/// Intermediate format to store the hir_id pointing to the use that resulted in the +/// corresponding place being captured and a String which contains the captured value's +/// name (i.e: a.b.c) +type CapturesInfo = (Option, String); + +/// Intermediate format to store information needed to generate migration lint. The tuple +/// contains the hir_id pointing to the use that resulted in the +/// corresponding place being captured, a String which contains the captured value's +/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that +/// capture +type MigrationNeededForCapture = (Option, String, String); + +/// Intermediate format to store the hir id of the root variable and a HashSet containing +/// information on why the root variable should be fully captured +type MigrationDiagnosticInfo = (hir::HirId, Vec); + struct InferBorrowKindVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, } @@ -146,9 +165,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fcx: self, closure_def_id, closure_span: span, - capture_clause, - current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM, - current_origin: None, capture_information: Default::default(), fake_reads: Default::default(), }; @@ -165,19 +181,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "For closure={:?}, capture_information={:#?}", closure_def_id, delegate.capture_information ); + self.log_capture_analysis_first_pass(closure_def_id, &delegate.capture_information, span); - self.compute_min_captures(closure_def_id, delegate.capture_information); + let (capture_information, closure_kind, origin) = self + .process_collected_capture_information(capture_clause, delegate.capture_information); + + self.compute_min_captures(closure_def_id, capture_information); let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); - if should_do_disjoint_capture_migration_analysis(self.tcx, closure_hir_id) { + if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) { self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span); } + let after_feature_tys = self.final_upvar_tys(closure_def_id); + // We now fake capture information for all variables that are mentioned within the closure // We do this after handling migrations so that min_captures computes before - if !self.tcx.features().capture_disjoint_fields { + if !enable_precise_capture(self.tcx, span) { let mut capture_information: InferredCaptureInformation<'tcx> = Default::default(); if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { @@ -203,17 +225,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.compute_min_captures(closure_def_id, capture_information); } + let before_feature_tys = self.final_upvar_tys(closure_def_id); + if let Some(closure_substs) = infer_kind { // Unify the (as yet unbound) type variable in the closure // substs with the kind we inferred. - let inferred_kind = delegate.current_closure_kind; let closure_kind_ty = closure_substs.as_closure().kind_ty(); - self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty); + self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty); // If we have an origin, store it. - if let Some(origin) = delegate.current_origin.clone() { - let origin = if self.tcx.features().capture_disjoint_fields { - (origin.0, restrict_capture_precision(origin.1)) + if let Some(origin) = origin { + let origin = if enable_precise_capture(self.tcx, span) { + (origin.0, origin.1) } else { (origin.0, Place { projections: vec![], ..origin.1 }) }; @@ -258,6 +281,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); self.typeck_results.borrow_mut().closure_fake_reads.insert(closure_def_id, fake_reads); + if self.tcx.sess.opts.debugging_opts.profile_closures { + self.typeck_results.borrow_mut().closure_size_eval.insert( + closure_def_id, + ClosureSizeProfileData { + before_feature_tys: self.tcx.mk_tup(before_feature_tys.into_iter()), + after_feature_tys: self.tcx.mk_tup(after_feature_tys.into_iter()), + }, + ); + } + // If we are also inferred the closure kind here, // process any deferred resolutions. let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id); @@ -285,17 +318,90 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { captured_place.place, upvar_ty, capture, captured_place.mutability, ); - match capture { - ty::UpvarCapture::ByValue(_) => upvar_ty, - ty::UpvarCapture::ByRef(borrow) => self.tcx.mk_ref( - borrow.region, - ty::TypeAndMut { ty: upvar_ty, mutbl: borrow.kind.to_mutbl_lossy() }, - ), - } + apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture) }) .collect() } + /// Adjusts the closure capture information to ensure that the operations aren't unsafe, + /// 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 + /// associated with the closure kind inference. + /// + /// Note that we *always* infer a minimal kind, even if + /// we don't always *use* that in the final result (i.e., sometimes + /// we've taken the closure kind from the expectations instead, and + /// for generators we don't even implement the closure traits + /// really). + /// + /// If we inferred that the closure needs to be FnMut/FnOnce, last element of the returned tuple + /// contains a `Some()` with the `Place` that caused us to do so. + fn process_collected_capture_information( + &self, + capture_clause: hir::CaptureBy, + capture_information: InferredCaptureInformation<'tcx>, + ) -> (InferredCaptureInformation<'tcx>, ty::ClosureKind, Option<(Span, Place<'tcx>)>) { + let mut processed: InferredCaptureInformation<'tcx> = Default::default(); + + let mut closure_kind = ty::ClosureKind::LATTICE_BOTTOM; + let mut origin: Option<(Span, Place<'tcx>)> = None; + + for (place, mut capture_info) in capture_information { + // Apply rules for safety before inferring closure kind + let place = restrict_capture_precision(place); + + let place = truncate_capture_for_optimization(&place); + + let usage_span = if let Some(usage_expr) = capture_info.path_expr_id { + self.tcx.hir().span(usage_expr) + } else { + unreachable!() + }; + + let updated = match capture_info.capture_kind { + ty::UpvarCapture::ByValue(..) => match closure_kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { + (ty::ClosureKind::FnOnce, Some((usage_span, place.clone()))) + } + // If closure is already FnOnce, don't update + ty::ClosureKind::FnOnce => (closure_kind, origin), + }, + + ty::UpvarCapture::ByRef(ty::UpvarBorrow { + kind: ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow, + .. + }) => { + match closure_kind { + ty::ClosureKind::Fn => { + (ty::ClosureKind::FnMut, Some((usage_span, place.clone()))) + } + // Don't update the origin + ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce => (closure_kind, origin), + } + } + + _ => (closure_kind, origin), + }; + + closure_kind = updated.0; + origin = updated.1; + + let (place, capture_kind) = match capture_clause { + hir::CaptureBy::Value => adjust_for_move_closure(place, capture_info.capture_kind), + hir::CaptureBy::Ref => { + adjust_for_non_move_closure(place, capture_info.capture_kind) + } + }; + + capture_info.capture_kind = capture_kind; + processed.insert(place, capture_info); + } + + (processed, closure_kind, origin) + } + /// Analyzes the information collected by `InferBorrowKind` to compute the min number of /// Places (and corresponding capture kind) that we need to keep track of to support all /// the required captured paths. @@ -385,8 +491,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base => bug!("Expected upvar, found={:?}", base), }; - let place = restrict_capture_precision(place); - let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) { None => { let mutability = self.determine_capture_mutability(&typeck_results, &place); @@ -487,18 +591,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let local_def_id = closure_def_id.expect_local(); let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); + let closure_span = self.tcx.hir().span(closure_hir_id); + let closure_head_span = self.tcx.sess.source_map().guess_head_span(closure_span); self.tcx.struct_span_lint_hir( - lint::builtin::DISJOINT_CAPTURE_MIGRATION, + lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_hir_id, - span, + closure_head_span, |lint| { let mut diagnostics_builder = lint.build( format!( - "{} affected for closure because of `capture_disjoint_fields`", + "changes to closure capture in Rust 2021 will affect {}", reasons ) .as_str(), ); + for (var_hir_id, diagnostics_info) in need_migrations.iter() { + // Labels all the usage of the captured variable and why they are responsible + // for migration being needed + for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() { + if let Some(captured_hir_id) = captured_hir_id { + let cause_span = self.tcx.hir().span(*captured_hir_id); + diagnostics_builder.span_label(cause_span, format!("in Rust 2018, closure captures all of `{}`, but in Rust 2021, it only captures `{}`", + self.tcx.hir().name(*var_hir_id), + captured_name, + )); + } + + // Add a label pointing to where a captured variable affected by drop order + // is dropped + if reasons.contains("drop order") { + let drop_location_span = drop_location_span(self.tcx, &closure_hir_id); + + diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` would be dropped here, but in Rust 2021, only `{}` would be dropped here alongside the closure", + self.tcx.hir().name(*var_hir_id), + captured_name, + )); + } + + // Add a label explaining why a closure no longer implements a trait + if reasons.contains("trait implementation") { + let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1]; + + diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure would implement {} as `{}` implements {}, but in Rust 2021, this closure would no longer implement {} as `{}` does not implement {}", + missing_trait, + self.tcx.hir().name(*var_hir_id), + missing_trait, + missing_trait, + captured_name, + missing_trait, + )); + } + } + } + diagnostics_builder.note("for more information, see "); let closure_body_span = self.tcx.hir().span(body_id.hir_id); let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(closure_body_span) { @@ -544,13 +689,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if auto_trait_reasons.len() > 0 { reasons = format!( - "{} trait implementation", + "{} trait implementation for closure", auto_trait_reasons.clone().into_iter().collect::>().join(", ") ); } if auto_trait_reasons.len() > 0 && drop_reason { - reasons = format!("{}, and ", reasons); + reasons = format!("{} and ", reasons); } if drop_reason { @@ -560,141 +705,121 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { reasons } - /// Returns true if `ty` may implement `trait_def_id` - fn ty_impls_trait( - &self, - ty: Ty<'tcx>, - cause: &ObligationCause<'tcx>, - trait_def_id: DefId, - ) -> bool { - use crate::rustc_middle::ty::ToPredicate; - use crate::rustc_middle::ty::WithConstness; - use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; - let tcx = self.infcx.tcx; - - let trait_ref = TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) }; - - let obligation = Obligation::new( - cause.clone(), - self.param_env, - trait_ref.without_const().to_predicate(tcx), - ); - - self.infcx.predicate_may_hold(&obligation) - } - - /// Returns true if migration is needed for trait for the provided var_hir_id - fn need_2229_migrations_for_trait( + /// Figures out the list of root variables (and their types) that aren't completely + /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits + /// differ between the root variable and the captured paths. + /// + /// Returns a tuple containing a HashMap of CapturesInfo that maps to a HashSet of trait names + /// if migration is needed for traits for the provided var_hir_id, otherwise returns None + fn compute_2229_migrations_for_trait( &self, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, var_hir_id: hir::HirId, - check_trait: Option, - ) -> bool { + closure_clause: hir::CaptureBy, + ) -> Option>> { + let auto_traits_def_id = vec![ + self.tcx.lang_items().clone_trait(), + self.tcx.lang_items().sync_trait(), + self.tcx.get_diagnostic_item(sym::send_trait), + self.tcx.lang_items().unpin_trait(), + self.tcx.get_diagnostic_item(sym::unwind_safe_trait), + self.tcx.get_diagnostic_item(sym::ref_unwind_safe_trait), + ]; + let auto_traits = + vec!["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"]; + let root_var_min_capture_list = if let Some(root_var_min_capture_list) = min_captures.and_then(|m| m.get(&var_hir_id)) { root_var_min_capture_list } else { - return false; + return None; }; let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); - let cause = ObligationCause::misc(self.tcx.hir().span(var_hir_id), self.body_id); - - let obligation_should_hold = check_trait - .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait)) - .unwrap_or(false); - - // Check whether catpured fields also implement the trait - - for capture in root_var_min_capture_list.iter() { - let ty = capture.place.ty(); - - let obligation_holds_for_capture = check_trait - .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait)) - .unwrap_or(false); + let ty = match closure_clause { + hir::CaptureBy::Value => ty, // For move closure the capture kind should be by value + hir::CaptureBy::Ref => { + // For non move closure the capture kind is the max capture kind of all captures + // according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue + let mut max_capture_info = root_var_min_capture_list.first().unwrap().info; + for capture in root_var_min_capture_list.iter() { + max_capture_info = determine_capture_info(max_capture_info, capture.info); + } - if !obligation_holds_for_capture && obligation_should_hold { - return true; + apply_capture_kind_on_capture_ty(self.tcx, ty, max_capture_info.capture_kind) } - } - false - } + }; - /// Figures out the list of root variables (and their types) that aren't completely - /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits - /// differ between the root variable and the captured paths. - /// - /// The output list would include a root variable if: - /// - It would have been captured into the closure when `capture_disjoint_fields` wasn't - /// enabled, **and** - /// - It wasn't completely captured by the closure, **and** - /// - One of the paths captured does not implement all the auto-traits its root variable - /// implements. - fn compute_2229_migrations_for_trait( - &self, - min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, - var_hir_id: hir::HirId, - ) -> Option> { - let tcx = self.infcx.tcx; - - // Check whether catpured fields also implement the trait - let mut auto_trait_reasons = FxHashSet::default(); - - if self.need_2229_migrations_for_trait( - min_captures, - var_hir_id, - tcx.lang_items().clone_trait(), - ) { - auto_trait_reasons.insert("`Clone`"); + let mut obligations_should_hold = Vec::new(); + // Checks if a root variable implements any of the auto traits + for check_trait in auto_traits_def_id.iter() { + obligations_should_hold.push( + check_trait + .map(|check_trait| { + self.infcx + .type_implements_trait( + check_trait, + ty, + self.tcx.mk_substs_trait(ty, &[]), + self.param_env, + ) + .must_apply_modulo_regions() + }) + .unwrap_or(false), + ); } - if self.need_2229_migrations_for_trait( - min_captures, - var_hir_id, - tcx.lang_items().sync_trait(), - ) { - auto_trait_reasons.insert("`Sync`"); - } + let mut problematic_captures = FxHashMap::default(); + // Check whether captured fields also implement the trait + for capture in root_var_min_capture_list.iter() { + let ty = apply_capture_kind_on_capture_ty( + self.tcx, + capture.place.ty(), + capture.info.capture_kind, + ); - if self.need_2229_migrations_for_trait( - min_captures, - var_hir_id, - tcx.lang_items().send_trait(), - ) { - auto_trait_reasons.insert("`Send`"); - } + // Checks if a capture implements any of the auto traits + let mut obligations_holds_for_capture = Vec::new(); + for check_trait in auto_traits_def_id.iter() { + obligations_holds_for_capture.push( + check_trait + .map(|check_trait| { + self.infcx + .type_implements_trait( + check_trait, + ty, + self.tcx.mk_substs_trait(ty, &[]), + self.param_env, + ) + .must_apply_modulo_regions() + }) + .unwrap_or(false), + ); + } - if self.need_2229_migrations_for_trait( - min_captures, - var_hir_id, - tcx.lang_items().unpin_trait(), - ) { - auto_trait_reasons.insert("`Unpin`"); - } + let mut capture_problems = FxHashSet::default(); - if self.need_2229_migrations_for_trait( - min_captures, - var_hir_id, - tcx.lang_items().unwind_safe_trait(), - ) { - auto_trait_reasons.insert("`UnwindSafe`"); - } + // Checks if for any of the auto traits, one or more trait is implemented + // by the root variable but not by the capture + for (idx, _) in obligations_should_hold.iter().enumerate() { + if !obligations_holds_for_capture[idx] && obligations_should_hold[idx] { + capture_problems.insert(auto_traits[idx]); + } + } - if self.need_2229_migrations_for_trait( - min_captures, - var_hir_id, - tcx.lang_items().ref_unwind_safe_trait(), - ) { - auto_trait_reasons.insert("`RefUnwindSafe`"); + if capture_problems.len() > 0 { + problematic_captures.insert( + (capture.info.path_expr_id, capture.to_string(self.tcx)), + capture_problems, + ); + } } - - if auto_trait_reasons.len() > 0 { - return Some(auto_trait_reasons); + if problematic_captures.len() > 0 { + return Some(problematic_captures); } - - return None; + None } /// Figures out the list of root variables (and their types) that aren't completely @@ -707,8 +832,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - It wasn't completely captured by the closure, **and** /// - One of the paths starting at this root variable, that is not captured needs Drop. /// - /// This function only returns true for significant drops. A type is considerent to have a - /// significant drop if it's Drop implementation is not annotated by `rustc_insignificant_dtor`. + /// This function only returns a HashSet of CapturesInfo for significant drops. If there + /// are no significant drops than None is returned fn compute_2229_migrations_for_drop( &self, closure_def_id: DefId, @@ -716,11 +841,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, closure_clause: hir::CaptureBy, var_hir_id: hir::HirId, - ) -> bool { + ) -> Option> { let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { - return false; + return None; } let root_var_min_capture_list = if let Some(root_var_min_capture_list) = @@ -733,21 +858,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match closure_clause { // Only migrate if closure is a move closure - hir::CaptureBy::Value => return true, + hir::CaptureBy::Value => return Some(FxHashSet::default()), hir::CaptureBy::Ref => {} } - return false; + return None; }; - let projections_list = root_var_min_capture_list - .iter() - .filter_map(|captured_place| match captured_place.info.capture_kind { + let mut projections_list = Vec::new(); + let mut diagnostics_info = FxHashSet::default(); + + for captured_place in root_var_min_capture_list.iter() { + match captured_place.info.capture_kind { // Only care about captures that are moved into the closure - ty::UpvarCapture::ByValue(..) => Some(captured_place.place.projections.as_slice()), - ty::UpvarCapture::ByRef(..) => None, - }) - .collect::>(); + ty::UpvarCapture::ByValue(..) => { + projections_list.push(captured_place.place.projections.as_slice()); + diagnostics_info.insert(( + captured_place.info.path_expr_id, + captured_place.to_string(self.tcx), + )); + } + ty::UpvarCapture::ByRef(..) => {} + } + } let is_moved = !projections_list.is_empty(); @@ -763,10 +896,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { projections_list, ) { - return true; + return Some(diagnostics_info); } - return false; + return None; } /// Figures out the list of root variables (and their types) that aren't completely @@ -782,15 +915,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - One of the paths captured does not implement all the auto-traits its root variable /// implements. /// - /// Returns a tuple containing a vector of HirIds as well as a String containing the reason - /// why root variables whose HirId is contained in the vector should be fully captured. + /// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String + /// containing the reason why root variables whose HirId is contained in the vector should + /// be captured fn compute_2229_migrations( &self, closure_def_id: DefId, closure_span: Span, closure_clause: hir::CaptureBy, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, - ) -> (Vec, String) { + ) -> (Vec, String) { let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { upvars } else { @@ -798,38 +932,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut need_migrations = Vec::new(); - let mut auto_trait_reasons = FxHashSet::default(); - let mut drop_reorder_reason = false; + let mut auto_trait_migration_reasons = FxHashSet::default(); + let mut drop_migration_needed = false; // Perform auto-trait analysis for (&var_hir_id, _) in upvars.iter() { - let mut need_migration = false; - if let Some(trait_migration_cause) = - self.compute_2229_migrations_for_trait(min_captures, var_hir_id) + let mut responsible_captured_hir_ids = Vec::new(); + + let auto_trait_diagnostic = if let Some(diagnostics_info) = + self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause) { - need_migration = true; - auto_trait_reasons.extend(trait_migration_cause); + diagnostics_info + } else { + FxHashMap::default() + }; + + let drop_reorder_diagnostic = if let Some(diagnostics_info) = self + .compute_2229_migrations_for_drop( + closure_def_id, + closure_span, + min_captures, + closure_clause, + var_hir_id, + ) { + drop_migration_needed = true; + diagnostics_info + } else { + FxHashSet::default() + }; + + // Combine all the captures responsible for needing migrations into one HashSet + let mut capture_diagnostic = drop_reorder_diagnostic.clone(); + for key in auto_trait_diagnostic.keys() { + capture_diagnostic.insert(key.clone()); } - if self.compute_2229_migrations_for_drop( - closure_def_id, - closure_span, - min_captures, - closure_clause, - var_hir_id, - ) { - need_migration = true; - drop_reorder_reason = true; + let mut capture_diagnostic = capture_diagnostic.into_iter().collect::>(); + capture_diagnostic.sort(); + for captured_info in capture_diagnostic.iter() { + // Get the auto trait reasons of why migration is needed because of that capture, if there are any + let capture_trait_reasons = + if let Some(reasons) = auto_trait_diagnostic.get(captured_info) { + reasons.clone() + } else { + FxHashSet::default() + }; + + // Check if migration is needed because of drop reorder as a result of that capture + let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info); + + // Combine all the reasons of why the root variable should be captured as a result of + // auto trait implementation issues + auto_trait_migration_reasons.extend(capture_trait_reasons.clone()); + + responsible_captured_hir_ids.push(( + captured_info.0, + captured_info.1.clone(), + self.compute_2229_migrations_reasons( + capture_trait_reasons, + capture_drop_reorder_reason, + ), + )); } - if need_migration { - need_migrations.push(var_hir_id); + if capture_diagnostic.len() > 0 { + need_migrations.push((var_hir_id, responsible_captured_hir_ids)); } } - ( need_migrations, - self.compute_2229_migrations_reasons(auto_trait_reasons, drop_reorder_reason), + self.compute_2229_migrations_reasons( + auto_trait_migration_reasons, + drop_migration_needed, + ), ) } @@ -943,12 +1118,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_drop_defined_for_ty = |ty: Ty<'tcx>| { let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span)); let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]); - self.tcx.type_implements_trait(( - drop_trait, - ty, - ty_params, - self.tcx.param_env(closure_def_id.expect_local()), - )) + self.infcx + .type_implements_trait( + drop_trait, + ty, + ty_params, + self.tcx.param_env(closure_def_id.expect_local()), + ) + .must_apply_modulo_regions() }; let is_drop_defined_for_ty = is_drop_defined_for_ty(base_path_ty); @@ -1275,6 +1452,39 @@ fn restrict_repr_packed_field_ref_capture<'tcx>( place } +/// Returns a Ty that applies the specified capture kind on the provided capture Ty +fn apply_capture_kind_on_capture_ty( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + capture_kind: UpvarCapture<'tcx>, +) -> Ty<'tcx> { + match capture_kind { + ty::UpvarCapture::ByValue(_) => ty, + ty::UpvarCapture::ByRef(borrow) => tcx + .mk_ref(borrow.region, ty::TypeAndMut { ty: ty, mutbl: borrow.kind.to_mutbl_lossy() }), + } +} + +/// Returns the Span of where the value with the provided HirId would be dropped +fn drop_location_span(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span { + let owner_id = tcx.hir().get_enclosing_scope(*hir_id).unwrap(); + + let owner_node = tcx.hir().get(owner_id); + let owner_span = match owner_node { + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id), + _ => { + bug!("Drop location span error: need to handle more ItemKind {:?}", item.kind); + } + }, + hir::Node::Block(block) => tcx.hir().span(block.hir_id), + _ => { + bug!("Drop location span error: need to handle more Node {:?}", owner_node); + } + }; + tcx.sess.source_map().end_point(owner_span) +} + struct InferBorrowKind<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -1283,20 +1493,6 @@ struct InferBorrowKind<'a, 'tcx> { closure_span: Span, - capture_clause: hir::CaptureBy, - - // The kind that we have inferred that the current closure - // requires. Note that we *always* infer a minimal kind, even if - // we don't always *use* that in the final result (i.e., sometimes - // we've taken the closure kind from the expectations instead, and - // for generators we don't even implement the closure traits - // really). - current_closure_kind: ty::ClosureKind, - - // If we modified `current_closure_kind`, this field contains a `Some()` with the - // variable access that caused us to do so. - current_origin: Option<(Span, Place<'tcx>)>, - /// For each Place that is captured by the closure, we track the minimal kind of /// access we need (ref, ref mut, move, etc) and the expression that resulted in such access. /// @@ -1332,34 +1528,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { &mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId, - mode: euv::ConsumeMode, ) { debug!( - "adjust_upvar_borrow_kind_for_consume(place_with_id={:?}, diag_expr_id={:?}, mode={:?})", - place_with_id, diag_expr_id, mode + "adjust_upvar_borrow_kind_for_consume(place_with_id={:?}, diag_expr_id={:?})", + place_with_id, diag_expr_id ); - - match (self.capture_clause, mode) { - // In non-move closures, we only care about moves - (hir::CaptureBy::Ref, euv::Copy) => return, - - // We want to capture Copy types that read through a ref via a reborrow - (hir::CaptureBy::Value, euv::Copy) - if place_with_id.place.deref_tys().any(ty::TyS::is_ref) => - { - return; - } - - (hir::CaptureBy::Ref, euv::Move) | (hir::CaptureBy::Value, euv::Move | euv::Copy) => {} - }; - - let place = truncate_capture_for_move(place_with_id.place.clone()); - let place_with_id = PlaceWithHirId { place: place.clone(), hir_id: place_with_id.hir_id }; - - if !self.capture_information.contains_key(&place) { - self.init_capture_info_for_place(&place_with_id, diag_expr_id); - } - let tcx = self.fcx.tcx; let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { upvar_id @@ -1371,16 +1544,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { let usage_span = tcx.hir().span(diag_expr_id); - if matches!(mode, euv::Move) { - // To move out of an upvar, this must be a FnOnce closure - self.adjust_closure_kind( - upvar_id.closure_expr_id, - ty::ClosureKind::FnOnce, - usage_span, - place.clone(), - ); - } - let capture_info = ty::CaptureInfo { capture_kind_expr_id: Some(diag_expr_id), path_expr_id: Some(diag_expr_id), @@ -1458,22 +1621,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { ty::ImmBorrow => false, }); - let tcx = self.fcx.tcx; - // if this is an implicit deref of an // upvar, then we need to modify the // borrow_kind of the upvar to make sure it // is inferred to mutable if necessary self.adjust_upvar_borrow_kind(place_with_id, diag_expr_id, borrow_kind); - - if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { - self.adjust_closure_kind( - upvar_id.closure_expr_id, - ty::ClosureKind::FnMut, - tcx.hir().span(diag_expr_id), - place_with_id.place.clone(), - ); - } } /// We infer the borrow_kind with which to borrow upvars in a stack closure. @@ -1512,48 +1664,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { }; } - fn adjust_closure_kind( - &mut self, - closure_id: LocalDefId, - new_kind: ty::ClosureKind, - upvar_span: Span, - place: Place<'tcx>, - ) { - debug!( - "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, place={:?})", - closure_id, new_kind, upvar_span, place - ); - - // Is this the closure whose kind is currently being inferred? - if closure_id.to_def_id() != self.closure_def_id { - debug!("adjust_closure_kind: not current closure"); - return; - } - - // closures start out as `Fn`. - let existing_kind = self.current_closure_kind; - - debug!( - "adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}", - closure_id, existing_kind, new_kind - ); - - match (existing_kind, new_kind) { - (ty::ClosureKind::Fn, ty::ClosureKind::Fn) - | (ty::ClosureKind::FnMut, ty::ClosureKind::Fn | ty::ClosureKind::FnMut) - | (ty::ClosureKind::FnOnce, _) => { - // no change needed - } - - (ty::ClosureKind::Fn, ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce) - | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { - // new kind is stronger than the old kind - self.current_closure_kind = new_kind; - self.current_origin = Some((upvar_span, place)); - } - } - } - fn init_capture_info_for_place( &mut self, place_with_id: &PlaceWithHirId<'tcx>, @@ -1562,12 +1672,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { assert_eq!(self.closure_def_id.expect_local(), upvar_id.closure_expr_id); - let capture_kind = self.fcx.init_capture_kind_for_place( - &place_with_id.place, - self.capture_clause, - upvar_id, - self.closure_span, - ); + // Initialize to ImmBorrow + // We will escalate the CaptureKind based on any uses we see or in `process_collected_capture_information`. + let origin = UpvarRegion(upvar_id, self.closure_span); + let upvar_region = self.fcx.next_region_var(origin); + let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: upvar_region }; + let capture_kind = ty::UpvarCapture::ByRef(upvar_borrow); let expr_id = Some(diag_expr_id); let capture_info = ty::CaptureInfo { @@ -1597,21 +1707,14 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } - fn consume( - &mut self, - place_with_id: &PlaceWithHirId<'tcx>, - diag_expr_id: hir::HirId, - mode: euv::ConsumeMode, - ) { - debug!( - "consume(place_with_id={:?}, diag_expr_id={:?}, mode={:?})", - place_with_id, diag_expr_id, mode - ); + fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) { + debug!("consume(place_with_id={:?}, diag_expr_id={:?})", place_with_id, diag_expr_id); + if !self.capture_information.contains_key(&place_with_id.place) { - self.init_capture_info_for_place(place_with_id, diag_expr_id); + self.init_capture_info_for_place(&place_with_id, diag_expr_id); } - self.adjust_upvar_borrow_kind_for_consume(place_with_id, diag_expr_id, mode); + self.adjust_upvar_borrow_kind_for_consume(&place_with_id, diag_expr_id); } fn borrow( @@ -1625,11 +1728,15 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { place_with_id, diag_expr_id, bk ); + // We only want repr packed restriction to be applied to reading references into a packed + // struct, and not when the data is being moved. Therefore we call this method here instead + // of in `restrict_capture_precision`. let place = restrict_repr_packed_field_ref_capture( self.fcx.tcx, self.fcx.param_env, &place_with_id.place, ); + let place_with_id = PlaceWithHirId { place, ..*place_with_id }; if !self.capture_information.contains_key(&place_with_id.place) { @@ -1696,15 +1803,65 @@ fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> { place } -/// Truncates a place so that the resultant capture doesn't move data out of a reference -fn truncate_capture_for_move(mut place: Place<'tcx>) -> Place<'tcx> { - if let Some(i) = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref) { - // We only drop Derefs in case of move closures - // There might be an index projection or raw ptr ahead, so we don't stop here. - place.projections.truncate(i); +/// Take ownership if data being accessed is owned by the variable used to access it +/// (or if closure attempts to move data that it doesn’t own). +/// Note: When taking ownership, only capture data found on the stack. +fn adjust_for_move_closure<'tcx>( + mut place: Place<'tcx>, + kind: ty::UpvarCapture<'tcx>, +) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { + let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref()); + let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref); + + match kind { + ty::UpvarCapture::ByRef(..) if contains_deref_of_ref => (place, kind), + + // If there's any Deref and the data needs to be moved into the closure body, + // or it's a Deref of a Box, truncate the path to the first deref + _ if first_deref.is_some() => { + let place = match first_deref { + Some(idx) => { + place.projections.truncate(idx); + place + } + None => place, + }; + + // AMAN: I think we don't need the span inside the ByValue anymore + // we have more detailed span in CaptureInfo + (place, ty::UpvarCapture::ByValue(None)) + } + + _ => (place, ty::UpvarCapture::ByValue(None)), } +} - place +/// Adjust closure capture just that if taking ownership of data, only move data +/// from enclosing stack frame. +fn adjust_for_non_move_closure<'tcx>( + mut place: Place<'tcx>, + kind: ty::UpvarCapture<'tcx>, +) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { + let contains_deref = + place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref); + + match kind { + ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => { + let place = match contains_deref { + Some(idx) => { + place.projections.truncate(idx); + place + } + // Because of the if guard on the match on `kind`, we should never get here. + None => unreachable!(), + }; + + (place, kind) + } + + ty::UpvarCapture::ByValue(..) => (place, kind), + ty::UpvarCapture::ByRef(..) => (place, kind), + } } fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { @@ -1769,8 +1926,12 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { tcx.hir().name(var_hir_id) } -fn should_do_disjoint_capture_migration_analysis(tcx: TyCtxt<'_>, closure_id: hir::HirId) -> bool { - let (level, _) = tcx.lint_level_at_node(lint::builtin::DISJOINT_CAPTURE_MIGRATION, closure_id); +fn should_do_rust_2021_incompatible_closure_captures_analysis( + tcx: TyCtxt<'_>, + closure_id: hir::HirId, +) -> bool { + let (level, _) = + tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id); !matches!(level, lint::Level::Allow) } @@ -1780,10 +1941,10 @@ fn should_do_disjoint_capture_migration_analysis(tcx: TyCtxt<'_>, closure_id: hi /// - s2: Comma separated names of the variables being migrated. fn migration_suggestion_for_2229( tcx: TyCtxt<'_>, - need_migrations: &Vec, + need_migrations: &Vec, ) -> (String, String) { let need_migrations_variables = - need_migrations.iter().map(|v| var_name(tcx, *v)).collect::>(); + need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::>(); let migration_ref_concat = need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::>().join(", "); @@ -1924,3 +2085,55 @@ fn determine_place_ancestry_relation( PlaceAncestryRelation::Divergent } } + +/// Reduces the precision of the captured place when the precision doesn't yeild any benefit from +/// borrow checking prespective, allowing us to save us on the size of the capture. +/// +/// +/// Fields that are read through a shared reference will always be read via a shared ref or a copy, +/// and therefore capturing precise paths yields no benefit. This optimization truncates the +/// rightmost deref of the capture if the deref is applied to a shared ref. +/// +/// Reason we only drop the last deref is because of the following edge case: +/// +/// ```rust +/// struct MyStruct<'a> { +/// a: &'static A, +/// b: B, +/// c: C<'a>, +/// } +/// +/// fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { +/// let c = || drop(&*m.a.field_of_a); +/// // Here we really do want to capture `*m.a` because that outlives `'static` +/// +/// // If we capture `m`, then the closure no longer outlives `'static' +/// // it is constrained to `'a` +/// } +/// ``` +fn truncate_capture_for_optimization<'tcx>(place: &Place<'tcx>) -> Place<'tcx> { + let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not)); + + // Find the right-most deref (if any). All the projections that come after this + // are fields or other "in-place pointer adjustments"; these refer therefore to + // data owned by whatever pointer is being dereferenced here. + let idx = place.projections.iter().rposition(|proj| ProjectionKind::Deref == proj.kind); + + match idx { + // If that pointer is a shared reference, then we don't need those fields. + Some(idx) if is_shared_ref(place.ty_before_projection(idx)) => { + Place { projections: place.projections[0..=idx].to_vec(), ..place.clone() } + } + None | Some(_) => place.clone(), + } +} + +/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if +/// user is using Rust Edition 2021 or higher. +/// +/// `span` is the span of the closure. +fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool { + // We use span here to ensure that if the closure was generated by a macro with a different + // edition. + tcx.features().capture_disjoint_fields || span.rust_2021() +} diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 7436edccf8..e33cc603b5 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -22,8 +22,9 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc}; +use std::convert::TryInto; use std::iter; use std::ops::ControlFlow; @@ -379,15 +380,14 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { } } +#[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))] fn check_associated_item( tcx: TyCtxt<'_>, item_id: hir::HirId, span: Span, sig_if_method: Option<&hir::FnSig<'_>>, ) { - debug!("check_associated_item: {:?}", item_id); - - let code = ObligationCauseCode::MiscObligation; + let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))); for_id(tcx, item_id, span).with_fcx(|fcx| { let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id)); @@ -401,12 +401,15 @@ fn check_associated_item( match item.kind { ty::AssocKind::Const => { let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in(span, ty); + let ty = fcx.normalize_associated_types_in_wf( + span, + ty, + WellFormedLoc::Ty(item_id.expect_owner()), + ); fcx.register_wf_obligation(ty.into(), span, code.clone()); } ty::AssocKind::Fn => { let sig = fcx.tcx.fn_sig(item.def_id); - let sig = fcx.normalize_associated_types_in(span, sig); let hir_sig = sig_if_method.expect("bad signature for method"); check_fn_or_method( fcx, @@ -424,7 +427,11 @@ fn check_associated_item( } if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in(span, ty); + let ty = fcx.normalize_associated_types_in_wf( + span, + ty, + WellFormedLoc::Ty(item_id.expect_owner()), + ); fcx.register_wf_obligation(ty.into(), span, code.clone()); } } @@ -516,7 +523,7 @@ fn check_type_defn<'tcx, F>( fcx.register_wf_obligation( field.ty.into(), field.span, - ObligationCauseCode::MiscObligation, + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(field.def_id))), ) } @@ -611,7 +618,6 @@ fn check_item_fn( for_id(tcx, item_id, span).with_fcx(|fcx| { let def_id = tcx.hir().local_def_id(item_id); let sig = tcx.fn_sig(def_id); - let sig = fcx.normalize_associated_types_in(span, sig); let mut implied_bounds = vec![]; check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds); implied_bounds @@ -623,7 +629,11 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo for_id(tcx, item_id, ty_span).with_fcx(|fcx| { let ty = tcx.type_of(tcx.hir().local_def_id(item_id)); - let item_ty = fcx.normalize_associated_types_in(ty_span, ty); + let item_ty = fcx.normalize_associated_types_in_wf( + ty_span, + ty, + WellFormedLoc::Ty(item_id.expect_owner()), + ); let mut forbid_unsized = true; if allow_foreign_ty { @@ -633,7 +643,11 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo } } - fcx.register_wf_obligation(item_ty.into(), ty_span, ObligationCauseCode::MiscObligation); + fcx.register_wf_obligation( + item_ty.into(), + ty_span, + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))), + ); if forbid_unsized { fcx.register_bound( item_ty, @@ -647,14 +661,13 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo }); } +#[tracing::instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, ast_self_ty: &hir::Ty<'_>, ast_trait_ref: &Option>, ) { - debug!("check_impl: {:?}", item); - for_item(tcx, item).with_fcx(|fcx| { match *ast_trait_ref { Some(ref ast_trait_ref) => { @@ -672,6 +685,7 @@ fn check_impl<'tcx>( ast_trait_ref.path.span, Some(item), ); + debug!(?obligations); for obligation in obligations { fcx.register_predicate(obligation); } @@ -682,7 +696,9 @@ fn check_impl<'tcx>( fcx.register_wf_obligation( self_ty.into(), ast_self_ty.span, - ObligationCauseCode::MiscObligation, + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty( + item.hir_id().expect_owner(), + ))), ); } } @@ -738,15 +754,19 @@ fn check_where_clauses<'tcx, 'fcx>( } } GenericParamDefKind::Const { .. } => { - // FIXME(const_generics_defaults): Figure out if this - // is the behavior we want, see the comment further below. if is_our_default(¶m) { + // FIXME(const_generics_defaults): This + // is incorrect when dealing with unused substs, for example + // for `struct Foo` + // we should eagerly error. let default_ct = tcx.const_param_default(param.def_id); - fcx.register_wf_obligation( - default_ct.into(), - tcx.def_span(param.def_id), - ObligationCauseCode::MiscObligation, - ); + if !default_ct.needs_subst() { + fcx.register_wf_obligation( + default_ct.into(), + tcx.def_span(param.def_id), + ObligationCauseCode::WellFormed(None), + ); + } } } // Doesn't have defaults. @@ -783,14 +803,6 @@ fn check_where_clauses<'tcx, 'fcx>( tcx.mk_param_from_def(param) } GenericParamDefKind::Const { .. } => { - // FIXME(const_generics_defaults): I(@lcnr) feel like always - // using the const parameter is the right choice here, even - // if it needs substs. - // - // Before stabilizing this we probably want to get some tests - // where this makes a difference and figure out what's the exact - // behavior we want here. - // If the param has a default, ... if is_our_default(param) { let default_ct = tcx.const_param_default(param.def_id); @@ -902,12 +914,49 @@ fn check_fn_or_method<'fcx, 'tcx>( def_id: DefId, implied_bounds: &mut Vec>, ) { - let sig = fcx.normalize_associated_types_in(span, sig); let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - for (&input_ty, ty) in iter::zip(sig.inputs(), hir_decl.inputs) { - fcx.register_wf_obligation(input_ty.into(), ty.span, ObligationCauseCode::MiscObligation); + // Normalize the input and output types one at a time, using a different + // `WellFormedLoc` for each. We cannot call `normalize_associated_types` + // on the entire `FnSig`, since this would use the same `WellFormedLoc` + // for each type, preventing the HIR wf check from generating + // a nice error message. + let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig; + inputs_and_output = + fcx.tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| { + fcx.normalize_associated_types_in_wf( + span, + ty, + WellFormedLoc::Param { + function: def_id.expect_local(), + // Note that the `param_idx` of the output type is + // one greater than the index of the last input type. + param_idx: i.try_into().unwrap(), + }, + ) + })); + // Manually call `normalize_assocaited_types_in` on the other types + // in `FnSig`. This ensures that if the types of these fields + // ever change to include projections, we will start normalizing + // them automatically. + let sig = ty::FnSig { + inputs_and_output, + c_variadic: fcx.normalize_associated_types_in(span, c_variadic), + unsafety: fcx.normalize_associated_types_in(span, unsafety), + abi: fcx.normalize_associated_types_in(span, abi), + }; + + for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() { + fcx.register_wf_obligation( + input_ty.into(), + ty.span, + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Param { + function: def_id.expect_local(), + param_idx: i.try_into().unwrap(), + })), + ); } + implied_bounds.extend(sig.inputs()); fcx.register_wf_obligation( @@ -1081,20 +1130,15 @@ fn check_method_receiver<'fcx, 'tcx>( let span = fn_sig.decl.inputs[0].span; let sig = fcx.tcx.fn_sig(method.def_id); - let sig = fcx.normalize_associated_types_in(span, sig); let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, sig); + let sig = fcx.normalize_associated_types_in(span, sig); debug!("check_method_receiver: sig={:?}", sig); let self_ty = fcx.normalize_associated_types_in(span, self_ty); - let self_ty = - fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx)); let receiver_ty = sig.inputs()[0]; - let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty); - let receiver_ty = - fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx)); if fcx.tcx.features().arbitrary_self_types { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { @@ -1422,6 +1466,7 @@ struct AdtVariant<'tcx> { struct AdtField<'tcx> { ty: Ty<'tcx>, + def_id: LocalDefId, span: Span, } @@ -1432,11 +1477,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .fields() .iter() .map(|field| { - let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id(field.hir_id)); + let def_id = self.tcx.hir().local_def_id(field.hir_id); + let field_ty = self.tcx.type_of(def_id); let field_ty = self.normalize_associated_types_in(field.ty.span, field_ty); let field_ty = self.resolve_vars_if_possible(field_ty); debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty); - AdtField { ty: field_ty, span: field.ty.span } + AdtField { ty: field_ty, span: field.ty.span, def_id } }) .collect(); AdtVariant { fields, explicit_discr: None } diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 032cc7ee23..935bcc9f32 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -15,7 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -60,6 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } wbcx.visit_body(body); wbcx.visit_min_capture_map(); + wbcx.eval_closure_size(); wbcx.visit_fake_reads_map(); wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); @@ -333,6 +334,19 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { } impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { + fn eval_closure_size(&mut self) { + let mut res: FxHashMap> = Default::default(); + for (closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() { + let closure_hir_id = + self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()); + + let data = self.resolve(*data, &closure_hir_id); + + res.insert(*closure_def_id, data); + } + + self.typeck_results.closure_size_eval = res; + } fn visit_min_capture_map(&mut self) { let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher( self.fcx.typeck_results.borrow().closure_min_captures.len(), @@ -482,6 +496,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { debug_assert!(!instantiated_ty.has_escaping_bound_vars()); + let opaque_type_key = self.fcx.fully_resolve(opaque_type_key).unwrap(); + // Prevent: // * `fn foo() -> Foo` // * `fn foo() -> Foo` @@ -494,6 +510,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // fn foo() -> Foo { .. } // ``` // figures out the concrete type with `U`, but the stored type is with `T`. + + // FIXME: why are we calling this here? This seems too early, and duplicated. let definition_ty = self.fcx.infer_opaque_definition_from_instantiation( opaque_type_key, instantiated_ty, @@ -503,8 +521,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut skip_add = false; if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() { - if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin - { + if opaque_defn.origin == hir::OpaqueTyOrigin::TyAlias { if opaque_type_key.def_id == definition_ty_def_id { debug!( "skipping adding concrete definition for opaque type {:?} {:?}", @@ -515,33 +532,33 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - if !opaque_type_key.substs.needs_infer() { - // We only want to add an entry into `concrete_opaque_types` - // if we actually found a defining usage of this opaque type. - // Otherwise, we do nothing - we'll either find a defining usage - // in some other location, or we'll end up emitting an error due - // to the lack of defining usage - if !skip_add { - let old_concrete_ty = self - .typeck_results - .concrete_opaque_types - .insert(opaque_type_key, definition_ty); - if let Some(old_concrete_ty) = old_concrete_ty { - if old_concrete_ty != definition_ty { - span_bug!( - span, - "`visit_opaque_types` tried to write different types for the same \ + if opaque_type_key.substs.needs_infer() { + span_bug!(span, "{:#?} has inference variables", opaque_type_key.substs) + } + + // We only want to add an entry into `concrete_opaque_types` + // if we actually found a defining usage of this opaque type. + // Otherwise, we do nothing - we'll either find a defining usage + // in some other location, or we'll end up emitting an error due + // to the lack of defining usage + if !skip_add { + let old_concrete_ty = self + .typeck_results + .concrete_opaque_types + .insert(opaque_type_key, definition_ty); + if let Some(old_concrete_ty) = old_concrete_ty { + if old_concrete_ty != definition_ty { + span_bug!( + span, + "`visit_opaque_types` tried to write different types for the same \ opaque type: {:?}, {:?}, {:?}, {:?}", - opaque_type_key.def_id, - definition_ty, - opaque_defn, - old_concrete_ty, - ); - } + opaque_type_key.def_id, + definition_ty, + opaque_defn, + old_concrete_ty, + ); } } - } else { - self.tcx().sess.delay_span_bug(span, "`opaque_defn` has inference variables"); } } } diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index 836bed2a15..7e5cc771b3 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -116,6 +116,8 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { crates_to_lint: &mut crates_to_lint, }); + let extern_prelude = &tcx.resolutions(()).extern_prelude; + for extern_crate in &crates_to_lint { let def_id = extern_crate.def_id.expect_local(); let id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -155,7 +157,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { // If the extern crate isn't in the extern prelude, // there is no way it can be written as an `use`. let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name); - if !tcx.extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) { + if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) { continue; } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index aebae0d47c..1a4c2eb515 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -15,6 +15,8 @@ //! At present, however, we do run collection across all items in the //! crate as a kind of pass. This should eventually be factored away. +// ignore-tidy-filelength + use crate::astconv::{AstConv, SizedByDefault}; use crate::bounds::Bounds; use crate::check::intrinsic::intrinsic_operation_unsafety; @@ -33,7 +35,6 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::weak_lang_items; use rustc_hir::{GenericParamKind, HirId, Node}; -use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::hir::map::Map; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::mono::Linkage; @@ -75,7 +76,6 @@ pub fn provide(providers: &mut Providers) { generics_of, predicates_of, predicates_defined_on, - projection_ty_from_predicates, explicit_predicates_of, super_predicates_of, super_predicates_that_define_assoc_type, @@ -91,6 +91,7 @@ pub fn provide(providers: &mut Providers) { generator_kind, codegen_fn_attrs, collect_mod_item_types, + should_inherit_track_caller, ..*providers }; } @@ -144,6 +145,7 @@ crate fn placeholder_type_error( placeholder_types: Vec, suggest: bool, hir_ty: Option<&hir::Ty<'_>>, + kind: &'static str, ) { if placeholder_types.is_empty() { return; @@ -173,13 +175,12 @@ crate fn placeholder_type_error( )); } - let mut err = bad_placeholder_type(tcx, placeholder_types); + let mut err = bad_placeholder_type(tcx, placeholder_types, kind); // Suggest, but only if it is not a function in const or static if suggest { let mut is_fn = false; - let mut is_const = false; - let mut is_static = false; + let mut is_const_or_static = false; if let Some(hir_ty) = hir_ty { if let hir::TyKind::BareFn(_) = hir_ty.kind { @@ -189,19 +190,26 @@ crate fn placeholder_type_error( let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); let parent_node = tcx.hir().get(parent_id); - if let hir::Node::Item(item) = parent_node { - if let hir::ItemKind::Const(_, _) = item.kind { - is_const = true; - } else if let hir::ItemKind::Static(_, _, _) = item.kind { - is_static = true; - } - } + is_const_or_static = match parent_node { + Node::Item(&hir::Item { + kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), + .. + }) + | Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Const(..), + .. + }) + | Node::ImplItem(&hir::ImplItem { + kind: hir::ImplItemKind::Const(..), .. + }) => true, + _ => false, + }; } } // if function is wrapped around a const or static, // then don't show the suggestion - if !(is_fn && (is_const || is_static)) { + if !(is_fn && is_const_or_static) { err.multipart_suggestion( "use type parameters instead", sugg, @@ -229,7 +237,15 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_item(item); - placeholder_type_error(tcx, Some(generics.span), generics.params, visitor.0, suggest, None); + placeholder_type_error( + tcx, + Some(generics.span), + generics.params, + visitor.0, + suggest, + None, + item.kind.descr(), + ); } impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { @@ -295,13 +311,17 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { fn bad_placeholder_type( tcx: TyCtxt<'tcx>, mut spans: Vec, + kind: &'static str, ) -> rustc_errors::DiagnosticBuilder<'tcx> { + let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) }; + spans.sort(); let mut err = struct_span_err!( tcx.sess, spans.clone(), E0121, - "the type placeholder `_` is not allowed within types on item signatures", + "the type placeholder `_` is not allowed within types on item signatures for {}", + kind ); for span in spans { err.span_label(span, "not allowed in type signatures"); @@ -337,11 +357,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } fn default_constness_for_trait_bounds(&self) -> hir::Constness { - if let Some(fn_like) = FnLikeNode::from_node(self.node()) { - fn_like.constness() - } else { - hir::Constness::NotConst - } + self.node().constness() } fn get_type_parameter_bounds( @@ -375,7 +391,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { _: Option<&ty::GenericParamDef>, span: Span, ) -> &'tcx Const<'tcx> { - bad_placeholder_type(self.tcx(), vec![span]).emit(); + bad_placeholder_type(self.tcx(), vec![span], "generic").emit(); // Typeck doesn't expect erased regions to be returned from `type_of`. let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r { ty::ReErased => self.tcx.lifetimes.re_static, @@ -739,7 +755,15 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ForeignItemKind::Static(..) => { let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_foreign_item(item); - placeholder_type_error(tcx, None, &[], visitor.0, false, None); + placeholder_type_error( + tcx, + None, + &[], + visitor.0, + false, + None, + "static variable", + ); } _ => (), } @@ -806,6 +830,22 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { match it.kind { hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id), hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id), + hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => { + // (#75889): Account for `const C: dyn Fn() -> _ = "";` + if let hir::TyKind::TraitObject(..) = ty.kind { + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_item(it); + placeholder_type_error( + tcx, + None, + &[], + visitor.0, + false, + None, + it.kind.descr(), + ); + } + } _ => (), } } @@ -831,7 +871,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { // Account for `const C: _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false, None); + placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant"); } hir::TraitItemKind::Type(_, Some(_)) => { @@ -840,7 +880,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { // Account for `type T = _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false, None); + placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); } hir::TraitItemKind::Type(_, None) => { @@ -850,7 +890,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); - placeholder_type_error(tcx, None, &[], visitor.0, false, None); + placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); } }; @@ -872,7 +912,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_impl_item(impl_item); - placeholder_type_error(tcx, None, &[], visitor.0, false, None); + placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type"); } hir::ImplItemKind::Const(..) => {} } @@ -1693,11 +1733,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ty::ReErased => tcx.lifetimes.re_static, _ => r, }); + let fn_sig = ty::Binder::dummy(fn_sig); let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_ty(ty); - let mut diag = bad_placeholder_type(tcx, visitor.0); - let ret_ty = fn_sig.output(); + let mut diag = bad_placeholder_type(tcx, visitor.0, "return type"); + let ret_ty = fn_sig.skip_binder().output(); if ret_ty != tcx.ty_error() { if !ret_ty.is_closure() { let ret_ty_str = match ret_ty.kind() { @@ -1723,7 +1764,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } diag.emit(); - ty::Binder::bind(fn_sig, tcx) + fn_sig } None => >::ty_of_fn( &icx, @@ -1767,10 +1808,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id()); let inputs = data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id))); - ty::Binder::bind( - tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust), - tcx, - ) + ty::Binder::dummy(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust, + )) } Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { @@ -2054,7 +2098,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP param.bounds.iter().for_each(|bound| match bound { hir::GenericBound::Outlives(lt) => { let bound = >::ast_region_to_region(&icx, <, None); - let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx); + let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound)); predicates.insert((outlives.to_predicate(tcx), lt.span)); } _ => bug!(), @@ -2260,6 +2304,16 @@ fn const_evaluatable_predicates_of<'tcx>( )); } } + + 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; + // struct Bar(Foo); + } } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -2350,29 +2404,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } } -fn projection_ty_from_predicates( - tcx: TyCtxt<'tcx>, - key: ( - // ty_def_id - DefId, - // def_id of `N` in `::N` - DefId, - ), -) -> Option> { - let (ty_def_id, item_def_id) = key; - let mut projection_ty = None; - for (predicate, _) in tcx.predicates_of(ty_def_id).predicates { - if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() - { - if item_def_id == projection_predicate.projection_ty.item_def_id { - projection_ty = Some(projection_predicate.projection_ty); - break; - } - } - } - projection_ty -} - /// 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 @@ -2651,7 +2682,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { let attrs = tcx.get_attrs(id); let mut codegen_fn_attrs = CodegenFnAttrs::new(); - if should_inherit_track_caller(tcx, id) { + if tcx.should_inherit_track_caller(id) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } @@ -2920,6 +2951,36 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { None } }; + } else if tcx.sess.check_name(attr, sym::repr) { + codegen_fn_attrs.alignment = match attr.meta_item_list() { + Some(items) => match items.as_slice() { + [item] => match item.name_value_literal() { + Some((sym::align, literal)) => { + let alignment = rustc_attr::parse_alignment(&literal.kind); + + match alignment { + Ok(align) => Some(align), + Err(msg) => { + struct_span_err!( + tcx.sess.diagnostic(), + attr.span, + E0589, + "invalid `repr(align)` attribute: {}", + msg + ) + .emit(); + + None + } + } + } + _ => None, + }, + [] => None, + _ => None, + }, + None => None, + }; } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 29a87b18a9..50e4ba4fe6 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -9,7 +9,7 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -285,7 +285,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { TraitItemKind::Const(ref ty, body_id) => body_id .and_then(|body_id| { if is_suggestable_infer_ty(ty) { - Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) + Some(infer_placeholder_type( + tcx, def_id, body_id, ty.span, item.ident, "constant", + )) } else { None } @@ -304,7 +306,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } ImplItemKind::Const(ref ty, body_id) => { if is_suggestable_infer_ty(ty) { - infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) + infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant") } else { icx.to_ty(ty) } @@ -320,9 +322,25 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Item(item) => { match item.kind { - ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => { + ItemKind::Static(ref ty, .., body_id) => { if is_suggestable_infer_ty(ty) { - infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) + infer_placeholder_type( + tcx, + def_id, + body_id, + ty.span, + item.ident, + "static variable", + ) + } else { + icx.to_ty(ty) + } + } + ItemKind::Const(ref ty, body_id) => { + if is_suggestable_infer_ty(ty) { + infer_placeholder_type( + tcx, def_id, body_id, ty.span, item.ident, "constant", + ) } else { icx.to_ty(ty) } @@ -338,9 +356,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_adt(def, substs) } - ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::Binding, .. }) => { - let_position_impl_trait_type(tcx, def_id) - } ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => { find_opaque_ty_constraints(tcx, def_id) } @@ -349,7 +364,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let concrete_ty = tcx .mir_borrowck(owner.expect_local()) .concrete_opaque_types - .get_by(|(key, _)| key.def_id == def_id.to_def_id()) + .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .map(|concrete_ty| *concrete_ty) .unwrap_or_else(|| { tcx.sess.delay_span_bug( @@ -474,7 +489,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { x => tcx.ty_error_with_message( DUMMY_SP, - &format!("unexpected const parent in type_of_def_id(): {:?}", x), + &format!("unexpected const parent in type_of(): {:?}", x), ), } } @@ -486,31 +501,35 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { }, x => { - bug!("unexpected sort of node in type_of_def_id(): {:?}", x); + bug!("unexpected sort of node in type_of(): {:?}", x); } } } +#[instrument(skip(tcx), level = "debug")] fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { use rustc_hir::{Expr, ImplItem, Item, TraitItem}; - debug!("find_opaque_ty_constraints({:?})", def_id); - struct ConstraintLocator<'tcx> { tcx: TyCtxt<'tcx>, + + /// def_id of the opaque type whose defining uses are being checked def_id: DefId, - // (first found type span, actual type) + + /// as we walk the defining uses, we are checking that all of them + /// define the same hidden type. This variable is set to `Some` + /// with the first type that we find, and then later types are + /// checked against it (we also carry the span of that first + /// type). found: Option<(Span, Ty<'tcx>)>, } impl ConstraintLocator<'_> { + #[instrument(skip(self), level = "debug")] fn check(&mut self, def_id: LocalDefId) { // Don't try to check items that cannot possibly constrain the type. if !self.tcx.has_typeck_results(def_id) { - debug!( - "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no typeck results", - self.def_id, def_id, - ); + debug!("no constraint: no typeck results"); return; } // Calling `mir_borrowck` can lead to cycle errors through @@ -519,24 +538,22 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { .tcx .typeck(def_id) .concrete_opaque_types - .get_by(|(key, _)| key.def_id == self.def_id) + .any_value_matching(|(key, _)| key.def_id == self.def_id) .is_none() { - debug!( - "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", - self.def_id, def_id, - ); + debug!("no constraints in typeck results"); return; } // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; - if let Some((opaque_type_key, concrete_type)) = - concrete_opaque_types.iter().find(|(key, _)| key.def_id == self.def_id) - { - debug!( - "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}", - self.def_id, def_id, concrete_type, - ); + debug!(?concrete_opaque_types); + for (opaque_type_key, concrete_type) in concrete_opaque_types { + if opaque_type_key.def_id != self.def_id { + // Ignore constraints for other opaque types. + continue; + } + + debug!(?concrete_type, ?opaque_type_key.substs, "found constraint"); // FIXME(oli-obk): trace the actual span from inference to improve errors. let span = self.tcx.def_span(def_id); @@ -585,7 +602,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { if let Some((prev_span, prev_ty)) = self.found { if *concrete_type != prev_ty { - debug!("find_opaque_ty_constraints: span={:?}", span); + debug!(?span); // Found different concrete types for the opaque type. let mut err = self.tcx.sess.struct_span_err( span, @@ -601,11 +618,6 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } else { self.found = Some((span, concrete_type)); } - } else { - debug!( - "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", - self.def_id, def_id, - ); } } } @@ -688,67 +700,48 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } } -/// Retrieve the inferred concrete type for let position impl trait. -/// -/// This is different to other kinds of impl trait because: -/// -/// 1. We know which function contains the defining use (the function that -/// contains the let statement) -/// 2. We do not currently allow (free) lifetimes in the return type. `let` -/// statements in some statically unreachable code are removed from the MIR -/// by the time we borrow check, and it's not clear how we should handle -/// those. -fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> { - let scope = tcx.hir().get_defining_scope(tcx.hir().local_def_id_to_hir_id(opaque_ty_id)); - let scope_def_id = tcx.hir().local_def_id(scope); - - let opaque_ty_def_id = opaque_ty_id.to_def_id(); - - let owner_typeck_results = tcx.typeck(scope_def_id); - let concrete_ty = owner_typeck_results - .concrete_opaque_types - .get_by(|(key, _)| key.def_id == opaque_ty_def_id) - .map(|concrete_ty| *concrete_ty) - .unwrap_or_else(|| { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no opaque type for {:?} in its typeck results", - scope_def_id, opaque_ty_id - ), - ); - if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors { - // Some error in the owner fn prevented us from populating the - // `concrete_opaque_types` table. - tcx.ty_error() - } else { - // We failed to resolve the opaque type or it resolves to - // itself. Return the non-revealed type, which should result in - // E0720. - tcx.mk_opaque( - opaque_ty_def_id, - InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), - ) - } - }); - debug!("concrete_ty = {:?}", concrete_ty); - if concrete_ty.has_erased_regions() { - // FIXME(impl_trait_in_bindings) Handle this case. - tcx.sess.span_fatal( - tcx.hir().span(tcx.hir().local_def_id_to_hir_id(opaque_ty_id)), - "lifetimes in impl Trait types in bindings are not currently supported", - ); - } - concrete_ty -} - -fn infer_placeholder_type( - tcx: TyCtxt<'_>, +fn infer_placeholder_type<'a>( + tcx: TyCtxt<'a>, def_id: LocalDefId, body_id: hir::BodyId, span: Span, item_ident: Ident, -) -> Ty<'_> { + kind: &'static str, +) -> Ty<'a> { + // Attempts to make the type nameable by turning FnDefs into FnPtrs. + struct MakeNameable<'tcx> { + success: bool, + tcx: TyCtxt<'tcx>, + } + + impl<'tcx> MakeNameable<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + MakeNameable { success: true, tcx } + } + } + + impl TypeFolder<'tcx> for MakeNameable<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if !self.success { + return ty; + } + + match ty.kind() { + ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)), + // FIXME: non-capturing closures should also suggest a function pointer + ty::Closure(..) | ty::Generator(..) => { + self.success = false; + ty + } + _ => ty.super_fold_with(self), + } + } + } + let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id); // If this came from a free `const` or `static mut?` item, @@ -760,24 +753,47 @@ fn infer_placeholder_type( // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. // We are typeck and have the real type, so remove that and suggest the actual type. err.suggestions.clear(); - err.span_suggestion( - span, - "provide a type for the item", - format!("{}: {}", item_ident, ty), - Applicability::MachineApplicable, - ) - .emit_unless(ty.references_error()); + + // Suggesting unnameable types won't help. + let mut mk_nameable = MakeNameable::new(tcx); + let ty = mk_nameable.fold_ty(ty); + let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; + if let Some(sugg_ty) = sugg_ty { + err.span_suggestion( + span, + &format!("provide a type for the {item}", item = kind), + format!("{}: {}", item_ident, sugg_ty), + Applicability::MachineApplicable, + ); + } else { + err.span_note( + tcx.hir().body(body_id).value.span, + &format!("however, the inferred type `{}` cannot be named", ty.to_string()), + ); + } + + err.emit_unless(ty.references_error()); } None => { - let mut diag = bad_placeholder_type(tcx, vec![span]); + let mut diag = bad_placeholder_type(tcx, vec![span], kind); if !ty.references_error() { - diag.span_suggestion( - span, - "replace with the correct type", - ty.to_string(), - Applicability::MaybeIncorrect, - ); + let mut mk_nameable = MakeNameable::new(tcx); + let ty = mk_nameable.fold_ty(ty); + let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; + if let Some(sugg_ty) = sugg_ty { + diag.span_suggestion( + span, + "replace with the correct type", + sugg_ty.to_string(), + Applicability::MaybeIncorrect, + ); + } else { + diag.span_note( + tcx.hir().body(body_id).value.span, + &format!("however, the inferred type `{}` cannot be named", ty.to_string()), + ); + } } diag.emit(); diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 5068242692..1e6a240b2f 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -24,13 +24,15 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(SessionDiagnostic)] #[error = "E0094"] -pub struct WrongNumberOfTypeArgumentsToInstrinsic { - #[message = "intrinsic has wrong number of type \ +pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { + #[message = "intrinsic has wrong number of {descr} \ parameters: found {found}, expected {expected}"] - #[label = "expected {expected} type parameter"] + #[label = "expected {expected} {descr} parameter{expected_pluralize}"] pub span: Span, pub found: usize, pub expected: usize, + pub expected_pluralize: &'a str, + pub descr: &'a str, } #[derive(SessionDiagnostic)] @@ -147,6 +149,10 @@ pub struct TypeofReservedKeywordUsed { pub struct ReturnStmtOutsideOfFnBody { #[message = "return statement outside of function body"] pub span: Span, + #[label = "the return is part of this body..."] + pub encl_body_span: Option, + #[label = "...not the enclosing function body"] + pub encl_fn_span: Option, } #[derive(SessionDiagnostic)] diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index f174941279..806f1a2711 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -2,8 +2,6 @@ //! normal visitor, which just walks the entire body in one shot, the //! `ExprUseVisitor` determines how expressions are being used. -pub use self::ConsumeMode::*; - // Export these here so that Clippy can use them. pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection}; @@ -28,19 +26,20 @@ use crate::mem_categorization as mc; /// This trait defines the callbacks you can expect to receive when /// employing the ExprUseVisitor. pub trait Delegate<'tcx> { - // The value found at `place` is either copied or moved, depending + // The value found at `place` is moved, depending // on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`. // + // Use of a `Copy` type in a ByValue context is considered a use + // by `ImmBorrow` and `borrow` is called instead. This is because + // a shared borrow is the "minimum access" that would be needed + // to perform a copy. + // + // // The parameter `diag_expr_id` indicates the HIR id that ought to be used for // diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic // id will be the id of the expression `expr` but the place itself will have // the id of the binding in the pattern `pat`. - fn consume( - &mut self, - place_with_id: &PlaceWithHirId<'tcx>, - diag_expr_id: hir::HirId, - mode: ConsumeMode, - ); + fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId); // The value found at `place` is being borrowed with kind `bk`. // `diag_expr_id` is the id used for diagnostics (see `consume` for more details). @@ -60,7 +59,7 @@ pub trait Delegate<'tcx> { } #[derive(Copy, Clone, PartialEq, Debug)] -pub enum ConsumeMode { +enum ConsumeMode { Copy, // reference to x where x has a type that copies Move, // reference to x where x has a type that moves } @@ -141,10 +140,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) { - debug!("delegate_consume(place_with_id={:?})", place_with_id); - - let mode = copy_or_move(&self.mc, place_with_id); - self.delegate.consume(place_with_id, diag_expr_id, mode); + delegate_consume(&self.mc, self.delegate, place_with_id, diag_expr_id) } fn consume_exprs(&mut self, exprs: &[hir::Expr<'_>]) { @@ -256,12 +252,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { | PatKind::Path(..) | PatKind::Struct(..) | PatKind::Tuple(..) => { - // If the PatKind is a TupleStruct, Struct or Tuple then we want to check + // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check // whether the Variant is a MultiVariant or a SingleVariant. We only want // to borrow discr if it is a MultiVariant. // If it is a SingleVariant and creates a binding we will handle that when // this callback gets called again. - if let ty::Adt(def, _) = place.place.base_ty.kind() { + + // Get the type of the Place after all projections have been applied + let place_ty = place.place.ty(); + + if let ty::Adt(def, _) = place_ty.kind() { if def.variants.len() > 1 { needs_to_be_read = true; } @@ -653,9 +653,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { delegate.borrow(place, discr_place.hir_id, bk); } ty::BindByValue(..) => { - let mode = copy_or_move(mc, &place); debug!("walk_pat binding consuming pat"); - delegate.consume(place, discr_place.hir_id, mode); + delegate_consume(mc, *delegate, place, discr_place.hir_id); } } } @@ -773,8 +772,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { match capture_info.capture_kind { ty::UpvarCapture::ByValue(_) => { - let mode = copy_or_move(&self.mc, &place_with_id); - self.delegate.consume(&place_with_id, place_with_id.hir_id, mode); + self.delegate_consume(&place_with_id, place_with_id.hir_id); } ty::UpvarCapture::ByRef(upvar_borrow) => { self.delegate.borrow( @@ -798,8 +796,28 @@ fn copy_or_move<'a, 'tcx>( place_with_id.place.ty(), mc.tcx().hir().span(place_with_id.hir_id), ) { - Move + ConsumeMode::Move } else { - Copy + ConsumeMode::Copy + } +} + +// - If a place is used in a `ByValue` context then move it if it's not a `Copy` type. +// - If the place that is a `Copy` type consider it a `ImmBorrow`. +fn delegate_consume<'a, 'tcx>( + mc: &mc::MemCategorizationContext<'a, 'tcx>, + delegate: &mut (dyn Delegate<'tcx> + 'a), + place_with_id: &PlaceWithHirId<'tcx>, + diag_expr_id: hir::HirId, +) { + debug!("delegate_consume(place_with_id={:?})", place_with_id); + + let mode = copy_or_move(&mc, place_with_id); + + match mode { + ConsumeMode::Move => delegate.consume(place_with_id, diag_expr_id), + ConsumeMode::Copy => { + delegate.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow) + } } } diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs new file mode 100644 index 0000000000..e7503d3d71 --- /dev/null +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -0,0 +1,185 @@ +use crate::collect::ItemCtxt; +use rustc_hir as hir; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::HirId; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::TraitEngine; +use rustc_infer::traits::{ObligationCause, WellFormedLoc}; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_trait_selection::traits; + +pub fn provide(providers: &mut Providers) { + *providers = Providers { diagnostic_hir_wf_check, ..*providers }; +} + +// Ideally, this would be in `rustc_trait_selection`, but we +// need access to `ItemCtxt` +fn diagnostic_hir_wf_check<'tcx>( + tcx: TyCtxt<'tcx>, + (predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc), +) -> Option> { + let hir = tcx.hir(); + + let def_id = match loc { + WellFormedLoc::Ty(def_id) => def_id, + WellFormedLoc::Param { function, param_idx: _ } => function, + }; + let hir_id = hir.local_def_id_to_hir_id(def_id); + + // HIR wfcheck should only ever happen as part of improving an existing error + tcx.sess + .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!"); + + let icx = ItemCtxt::new(tcx, def_id.to_def_id()); + + // To perform HIR-based WF checking, we iterate over all HIR types + // that occur 'inside' the item we're checking. For example, + // given the type `Option>`, we will check + // `Option>`, `MyStruct`, and `u8`. + // For each type, we perform a well-formed check, and see if we get + // an erorr that matches our expected predicate. We keep save + // the `ObligationCause` corresponding to the *innermost* type, + // which is the most specific type that we can point to. + // In general, the different components of an `hir::Ty` may have + // completely differentr spans due to macro invocations. Pointing + // to the most accurate part of the type can be the difference + // between a useless span (e.g. the macro invocation site) + // and a useful span (e.g. a user-provided type passed in to the macro). + // + // This approach is quite inefficient - we redo a lot of work done + // by the normal WF checker. However, this code is run at most once + // per reported error - it will have no impact when compilation succeeds, + // and should only have an impact if a very large number of errors are + // displaydd to the user. + struct HirWfCheck<'tcx> { + tcx: TyCtxt<'tcx>, + predicate: ty::Predicate<'tcx>, + cause: Option>, + cause_depth: usize, + icx: ItemCtxt<'tcx>, + hir_id: HirId, + param_env: ty::ParamEnv<'tcx>, + depth: usize, + } + + impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { + type Map = intravisit::ErasedMap<'tcx>; + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { + self.tcx.infer_ctxt().enter(|infcx| { + let mut fulfill = traits::FulfillmentContext::new(); + 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::MiscObligation, + ); + fulfill.register_predicate_obligation( + &infcx, + traits::Obligation::new( + cause, + self.param_env, + ty::PredicateKind::WellFormed(tcx_ty.into()).to_predicate(self.tcx), + ), + ); + + if let Err(errors) = fulfill.select_all_or_error(&infcx) { + tracing::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`) + // over less-specific types (e.g. `Option>`) + 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; + } + } + + let mut visitor = HirWfCheck { + tcx, + predicate, + cause: None, + cause_depth: 0, + icx, + hir_id, + param_env: tcx.param_env(def_id.to_def_id()), + depth: 0, + }; + + // Get the starting `hir::Ty` using our `WellFormedLoc`. + // We will walk 'into' this type to try to find + // a more precise span for our predicate. + let ty = match loc { + WellFormedLoc::Ty(_) => match hir.get(hir_id) { + hir::Node::ImplItem(item) => match item.kind { + hir::ImplItemKind::TyAlias(ty) => Some(ty), + ref item => bug!("Unexpected ImplItem {:?}", item), + }, + hir::Node::TraitItem(item) => match item.kind { + hir::TraitItemKind::Type(_, ty) => ty, + ref item => bug!("Unexpected TraitItem {:?}", item), + }, + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty), + hir::ItemKind::Impl(ref impl_) => { + assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_); + Some(impl_.self_ty) + } + ref item => bug!("Unexpected item {:?}", item), + }, + hir::Node::Field(field) => Some(field.ty), + ref node => bug!("Unexpected node {:?}", node), + }, + WellFormedLoc::Param { function: _, param_idx } => { + let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap(); + // Get return type + if param_idx as usize == fn_decl.inputs.len() { + match fn_decl.output { + hir::FnRetTy::Return(ty) => Some(ty), + // The unit type `()` is always well-formed + hir::FnRetTy::DefaultReturn(_span) => None, + } + } else { + Some(&fn_decl.inputs[param_idx as usize]) + } + } + }; + if let Some(ty) = ty { + visitor.visit_ty(ty); + } + visitor.cause +} + +struct EraseAllBoundRegions<'tcx> { + tcx: TyCtxt<'tcx>, +} + +// Higher ranked regions are complicated. +// To make matters worse, the HIR WF check can instantiate them +// outside of a `Binder`, due to the way we (ab)use +// `ItemCtxt::to_ty`. To make things simpler, we just erase all +// of them, regardless of depth. At worse, this will give +// us an inaccurate span for an error message, but cannot +// lead to unsoundess (we call `delay_span_bug` at the start +// of `diagnostic_hir_wf_check`). +impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + if let ty::ReLateBound(..) = r { &ty::ReErased } else { r } + } +} diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 92ef829747..5b717862e0 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -88,6 +88,7 @@ mod coherence; mod collect; mod constrained_generic_params; mod errors; +pub mod hir_wf_check; mod impl_wf_check; mod mem_categorization; mod outlives; @@ -462,6 +463,7 @@ pub fn provide(providers: &mut Providers) { variance::provide(providers); outlives::provide(providers); impl_wf_check::provide(providers); + hir_wf_check::provide(providers); } pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { diff --git a/config.toml.example b/config.toml.example index 7fa5353d09..775133f2ab 100644 --- a/config.toml.example +++ b/config.toml.example @@ -38,7 +38,7 @@ changelog-seen = 2 # This is false by default so that distributions don't unexpectedly download # LLVM from the internet. # -# All tier 1 targets are currently supported; set this to `"if-supported"` if +# All tier 1 targets are currently supported; set this to `"if-available"` if # you are not sure whether you're on a tier 1 target. # # We also currently only support this when building LLVM for the build triple. @@ -567,8 +567,8 @@ changelog-seen = 2 # On Linux target, if crt-static is not enabled, 'no' means dynamic link to # `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind # and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled, -# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both -# means static link to the in-tree build of llvm libunwind, and 'system' means +# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both +# means static link to the in-tree build of llvm libunwind, and 'system' means # static link to `libunwind.a` provided by system. Due to the limitation of glibc, # it must link to `libgcc_eh.a` to get a working output, and this option have no effect. #llvm-libunwind = 'no' diff --git a/git-commit-hash b/git-commit-hash index c7d63488d8..2753057ab4 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -a178d0322ce20e33eac124758e837cbd80a6f633 \ No newline at end of file +c8dfcfe046a7680554bf4eb612bad840e7631c4b \ No newline at end of file diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs index 21a0fb844e..920a5ca7db 100644 --- a/library/alloc/benches/btree/map.rs +++ b/library/alloc/benches/btree/map.rs @@ -177,7 +177,7 @@ pub fn iteration_mut_100000(b: &mut Bencher) { bench_iteration_mut(b, 100000); } -fn bench_first_and_last(b: &mut Bencher, size: i32) { +fn bench_first_and_last_nightly(b: &mut Bencher, size: i32) { let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); b.iter(|| { for _ in 0..10 { @@ -187,19 +187,44 @@ fn bench_first_and_last(b: &mut Bencher, size: i32) { }); } +fn bench_first_and_last_stable(b: &mut Bencher, size: i32) { + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + b.iter(|| { + for _ in 0..10 { + black_box(map.iter().next()); + black_box(map.iter().next_back()); + } + }); +} + +#[bench] +pub fn first_and_last_0_nightly(b: &mut Bencher) { + bench_first_and_last_nightly(b, 0); +} + +#[bench] +pub fn first_and_last_0_stable(b: &mut Bencher) { + bench_first_and_last_stable(b, 0); +} + +#[bench] +pub fn first_and_last_100_nightly(b: &mut Bencher) { + bench_first_and_last_nightly(b, 100); +} + #[bench] -pub fn first_and_last_0(b: &mut Bencher) { - bench_first_and_last(b, 0); +pub fn first_and_last_100_stable(b: &mut Bencher) { + bench_first_and_last_stable(b, 100); } #[bench] -pub fn first_and_last_100(b: &mut Bencher) { - bench_first_and_last(b, 100); +pub fn first_and_last_10k_nightly(b: &mut Bencher) { + bench_first_and_last_nightly(b, 10_000); } #[bench] -pub fn first_and_last_10k(b: &mut Bencher) { - bench_first_and_last(b, 10_000); +pub fn first_and_last_10k_stable(b: &mut Bencher) { + bench_first_and_last_stable(b, 10_000); } const BENCH_RANGE_SIZE: i32 = 145; diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 9d61b3684b..482a497201 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -177,6 +177,7 @@ where /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")] pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 13b42442dc..53bfe02d0e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -187,8 +187,6 @@ impl Box { /// ``` #[cfg(not(no_global_oom_handling))] #[inline(always)] - #[doc(alias = "alloc")] - #[doc(alias = "malloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(x: T) -> Self { box x @@ -239,7 +237,6 @@ impl Box { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[doc(alias = "calloc")] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed() -> Box> { Self::new_zeroed_in(Global) diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 544e18d1ff..2f656e4a6b 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -1034,7 +1034,6 @@ impl BinaryHeap { /// /// assert_eq!(heap.len(), 2); /// ``` - #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.data.len() diff --git a/library/alloc/src/collections/btree/fix.rs b/library/alloc/src/collections/btree/fix.rs index af87a9b956..c4861817dd 100644 --- a/library/alloc/src/collections/btree/fix.rs +++ b/library/alloc/src/collections/btree/fix.rs @@ -3,7 +3,7 @@ use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef, Root} impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { /// Stocks up a possibly underfull node by merging with or stealing from a - /// sibling. If succesful but at the cost of shrinking the parent node, + /// sibling. If successful but at the cost of shrinking the parent node, /// returns that shrunk parent node. Returns an `Err` if the node is /// an empty root. fn fix_node_through_parent( diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 30194aa446..79042ab739 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -889,7 +889,6 @@ impl BTreeMap { /// assert_eq!(map.remove(&1), Some("a")); /// assert_eq!(map.remove(&1), None); /// ``` - #[doc(alias = "delete")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, key: &Q) -> Option where @@ -936,6 +935,7 @@ impl BTreeMap { /// Retains only the elements specified by the predicate. /// /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. + /// The elements are visited in ascending key order. /// /// # Examples /// @@ -1299,7 +1299,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { None } else { self.length -= 1; - Some(unsafe { self.range.next_unchecked() }) + Some(unsafe { self.range.inner.next_unchecked() }) } } @@ -1330,7 +1330,7 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { None } else { self.length -= 1; - Some(unsafe { self.range.next_back_unchecked() }) + Some(unsafe { self.range.inner.next_back_unchecked() }) } } } @@ -1368,7 +1368,7 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> { None } else { self.length -= 1; - Some(unsafe { self.range.next_unchecked() }) + Some(unsafe { self.range.inner.next_unchecked() }) } } @@ -1396,7 +1396,7 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for IterMut<'a, K, V> { None } else { self.length -= 1; - Some(unsafe { self.range.next_back_unchecked() }) + Some(unsafe { self.range.inner.next_back_unchecked() }) } } } @@ -1475,7 +1475,7 @@ impl Drop for Dropper { #[stable(feature = "btree_drop", since = "1.7.0")] impl Drop for IntoIter { fn drop(&mut self) { - if let Some(front) = self.range.front.take() { + if let Some(front) = self.range.take_front() { Dropper { front, remaining_length: self.length }; } } @@ -1490,8 +1490,7 @@ impl Iterator for IntoIter { None } else { self.length -= 1; - let front = self.range.front.as_mut().unwrap(); - let kv = unsafe { front.deallocating_next_unchecked() }; + let kv = unsafe { self.range.deallocating_next_unchecked() }; Some(kv.into_key_val()) } } @@ -1508,8 +1507,7 @@ impl DoubleEndedIterator for IntoIter { None } else { self.length -= 1; - let back = self.range.back.as_mut().unwrap(); - let kv = unsafe { back.deallocating_next_back_unchecked() }; + let kv = unsafe { self.range.deallocating_next_back_unchecked() }; Some(kv.into_key_val()) } } @@ -1727,7 +1725,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { type Item = (&'a K, &'a V); fn next(&mut self) -> Option<(&'a K, &'a V)> { - if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) } + self.inner.next_checked() } fn last(mut self) -> Option<(&'a K, &'a V)> { @@ -1777,12 +1775,6 @@ impl ExactSizeIterator for ValuesMut<'_, K, V> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ValuesMut<'_, K, V> {} -impl<'a, K, V> Range<'a, K, V> { - unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { - unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() } - } -} - #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl Iterator for IntoKeys { type Item = K; @@ -1862,13 +1854,7 @@ impl FusedIterator for IntoValues {} #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a V)> { - if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) } - } -} - -impl<'a, K, V> Range<'a, K, V> { - unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { - unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() } + self.inner.next_back_checked() } } @@ -1878,7 +1864,7 @@ impl FusedIterator for Range<'_, K, V> {} #[stable(feature = "btree_range", since = "1.17.0")] impl Clone for Range<'_, K, V> { fn clone(&self) -> Self { - Range { inner: LeafRange { front: self.inner.front, back: self.inner.back } } + Range { inner: self.inner.clone() } } } @@ -1887,7 +1873,7 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { type Item = (&'a K, &'a mut V); fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) } + self.inner.next_checked() } fn last(mut self) -> Option<(&'a K, &'a mut V)> { @@ -1904,10 +1890,6 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { } impl<'a, K, V> RangeMut<'a, K, V> { - unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { - unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() } - } - /// Returns an iterator of references over the remaining items. #[inline] pub(super) fn iter(&self) -> Range<'_, K, V> { @@ -1918,19 +1900,13 @@ impl<'a, K, V> RangeMut<'a, K, V> { #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { - if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) } + self.inner.next_back_checked() } } #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for RangeMut<'_, K, V> {} -impl<'a, K, V> RangeMut<'a, K, V> { - unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { - unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator<(K, V)> for BTreeMap { fn from_iter>(iter: T) -> BTreeMap { @@ -2189,7 +2165,6 @@ impl BTreeMap { /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` - #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn len(&self) -> usize { diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 6b30d95977..5fec8dc2d1 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -14,6 +14,7 @@ use Entry::*; /// /// [`entry`]: BTreeMap::entry #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeEntry")] pub enum Entry<'a, K: 'a, V: 'a> { /// A vacant entry. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index 563c070dd0..bf3542b384 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -4,9 +4,16 @@ use core::ptr; use super::node::{marker, ForceResult::*, Handle, NodeRef}; +// `front` and `back` are always both `None` or both `Some`. pub struct LeafRange { - pub front: Option, marker::Edge>>, - pub back: Option, marker::Edge>>, + front: Option, marker::Edge>>, + back: Option, marker::Edge>>, +} + +impl<'a, K: 'a, V: 'a> Clone for LeafRange, K, V> { + fn clone(&self) -> Self { + LeafRange { front: self.front.clone(), back: self.back.clone() } + } } impl LeafRange { @@ -14,7 +21,7 @@ impl LeafRange { LeafRange { front: None, back: None } } - pub fn is_empty(&self) -> bool { + fn is_empty(&self) -> bool { self.front == self.back } @@ -27,6 +34,77 @@ impl LeafRange { } } +impl<'a, K, V> LeafRange, K, V> { + #[inline] + pub fn next_checked(&mut self) -> Option<(&'a K, &'a V)> { + if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) } + } + + #[inline] + pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a V)> { + if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) } + } + + #[inline] + pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe { self.front.as_mut().unwrap().next_unchecked() } + } + + #[inline] + pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe { self.back.as_mut().unwrap().next_back_unchecked() } + } +} + +impl<'a, K, V> LeafRange, K, V> { + #[inline] + pub fn next_checked(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) } + } + + #[inline] + pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) } + } + + #[inline] + pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe { self.front.as_mut().unwrap().next_unchecked() } + } + + #[inline] + pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe { self.back.as_mut().unwrap().next_back_unchecked() } + } +} + +impl LeafRange { + #[inline] + pub fn take_front( + &mut self, + ) -> Option, marker::Edge>> { + self.front.take() + } + + #[inline] + pub unsafe fn deallocating_next_unchecked( + &mut self, + ) -> Handle, marker::KV> { + debug_assert!(self.front.is_some()); + let front = self.front.as_mut().unwrap(); + unsafe { front.deallocating_next_unchecked() } + } + + #[inline] + pub unsafe fn deallocating_next_back_unchecked( + &mut self, + ) -> Handle, marker::KV> { + debug_assert!(self.back.is_some()); + let back = self.back.as_mut().unwrap(); + unsafe { back.deallocating_next_back_unchecked() } + } +} + impl NodeRef { /// Finds the distinct leaf edges delimiting a specified range in a tree. /// @@ -36,7 +114,7 @@ impl NodeRef /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV /// on the left side, which is either in the same leaf node or in an ancestor node. /// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node. - pub fn next_back_kv( + fn next_back_kv( self, ) -> Result< Handle, marker::KV>, @@ -216,7 +294,7 @@ impl /// Given an internal edge handle, returns [`Result::Ok`] with a handle to the neighboring KV /// on the right side, which is either in the same internal node or in an ancestor node. /// If the internal edge is the last one in the tree, returns [`Result::Err`] with the root node. - pub fn next_kv( + fn next_kv( self, ) -> Result< Handle, marker::KV>, @@ -250,7 +328,7 @@ impl Handle, marker::Edge> { /// - The returned KV handle is only valid to access the key and value, /// and only valid until the next call to this method or counterpart /// `deallocating_next_back`. - pub unsafe fn deallocating_next( + unsafe fn deallocating_next( self, ) -> Option<(Self, Handle, marker::KV>)> { @@ -316,10 +394,9 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Ed /// /// # Safety /// There must be another KV in the direction travelled. - pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { super::mem::replace(self, |leaf_edge| { - let kv = leaf_edge.next_kv(); - let kv = unsafe { kv.ok().unwrap_unchecked() }; + let kv = leaf_edge.next_kv().ok().unwrap(); (kv.next_leaf_edge(), kv.into_kv()) }) } @@ -329,10 +406,9 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Ed /// /// # Safety /// There must be another KV in the direction travelled. - pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { super::mem::replace(self, |leaf_edge| { - let kv = leaf_edge.next_back_kv(); - let kv = unsafe { kv.ok().unwrap_unchecked() }; + let kv = leaf_edge.next_back_kv().ok().unwrap(); (kv.next_back_leaf_edge(), kv.into_kv()) }) } @@ -344,10 +420,9 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::E /// /// # Safety /// There must be another KV in the direction travelled. - pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { let kv = super::mem::replace(self, |leaf_edge| { - let kv = leaf_edge.next_kv(); - let kv = unsafe { kv.ok().unwrap_unchecked() }; + let kv = leaf_edge.next_kv().ok().unwrap(); (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv) }); // Doing this last is faster, according to benchmarks. @@ -359,10 +434,9 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::E /// /// # Safety /// There must be another KV in the direction travelled. - pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { let kv = super::mem::replace(self, |leaf_edge| { - let kv = leaf_edge.next_back_kv(); - let kv = unsafe { kv.ok().unwrap_unchecked() }; + let kv = leaf_edge.next_back_kv().ok().unwrap(); (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv) }); // Doing this last is faster, according to benchmarks. @@ -386,9 +460,7 @@ impl Handle, marker::Edge> { pub unsafe fn deallocating_next_unchecked( &mut self, ) -> Handle, marker::KV> { - super::mem::replace(self, |leaf_edge| unsafe { - leaf_edge.deallocating_next().unwrap_unchecked() - }) + super::mem::replace(self, |leaf_edge| unsafe { leaf_edge.deallocating_next().unwrap() }) } /// Moves the leaf edge handle to the previous leaf edge and returns the key and value @@ -403,11 +475,11 @@ impl Handle, marker::Edge> { /// /// The only safe way to proceed with the updated handle is to compare it, drop it, /// or call this method or counterpart `deallocating_next_unchecked` again. - pub unsafe fn deallocating_next_back_unchecked( + unsafe fn deallocating_next_back_unchecked( &mut self, ) -> Handle, marker::KV> { super::mem::replace(self, |leaf_edge| unsafe { - leaf_edge.deallocating_next_back().unwrap_unchecked() + leaf_edge.deallocating_next_back().unwrap() }) } } @@ -508,9 +580,7 @@ impl } /// Returns the leaf edge closest to a KV for backward navigation. - pub fn next_back_leaf_edge( - self, - ) -> Handle, marker::Edge> { + fn next_back_leaf_edge(self) -> Handle, marker::Edge> { match self.force() { Leaf(leaf_kv) => leaf_kv.left_edge(), Internal(internal_kv) => { diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 3c453529ba..30d237d8bb 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -167,7 +167,7 @@ type BoxedNode = NonNull>; /// carry a lifetime, because we want it to return `&'a` references. /// Therefore, we define it only for the least powerful type `Immut<'a>`. /// - We cannot get implicit coercion from say `Mut<'a>` to `Immut<'a>`. -/// Therefore, we have to explicitly call `reborrow` on a more powerfull +/// Therefore, we have to explicitly call `reborrow` on a more powerful /// `NodeRef` in order to reach a method like `into_kv`. /// /// All methods on `NodeRef` that return some kind of reference, either: diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 737932d931..9711214aea 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -810,7 +810,6 @@ impl BTreeSet { /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` - #[doc(alias = "delete")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, value: &Q) -> bool where @@ -847,6 +846,7 @@ impl BTreeSet { /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// The elements are visited in ascending order. /// /// # Examples /// @@ -904,8 +904,8 @@ impl BTreeSet { self.map.append(&mut other.map); } - /// Splits the collection into two at the given key. Returns everything after the given key, - /// including the key. + /// Splits the collection into two at the given value. Returns everything after the given value, + /// including the value. /// /// # Examples /// @@ -934,25 +934,27 @@ impl BTreeSet { /// assert!(b.contains(&41)); /// ``` #[stable(feature = "btree_split_off", since = "1.11.0")] - pub fn split_off(&mut self, key: &Q) -> Self + pub fn split_off(&mut self, value: &Q) -> Self where T: Borrow + Ord, { - BTreeSet { map: self.map.split_off(key) } + BTreeSet { map: self.map.split_off(value) } } - /// Creates an iterator which uses a closure to determine if a value should be removed. + /// Creates an iterator that visits all values in ascending order and uses a closure + /// to determine if a value should be removed. /// - /// If the closure returns true, then the value is removed and yielded. - /// If the closure returns false, the value will remain in the list and will not be yielded - /// by the iterator. + /// If the closure returns `true`, the value is removed from the set and yielded. If + /// the closure returns `false`, or panics, the value remains in the set and will + /// not be yielded. /// - /// If the iterator is only partially consumed or not consumed at all, each of the remaining - /// values will still be subjected to the closure and removed and dropped if it returns true. + /// If the iterator is only partially consumed or not consumed at all, each of the + /// remaining values is still subjected to the closure and removed and dropped if it + /// returns `true`. /// - /// It is unspecified how many more values will be subjected to the closure - /// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the - /// `DrainFilter` itself is leaked. + /// It is unspecified how many more values will be subjected to the closure if a + /// panic occurs in the closure, or if a panic occurs while dropping a value, or if + /// the `DrainFilter` itself is leaked. /// /// # Examples /// @@ -1021,7 +1023,6 @@ impl BTreeSet { /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` - #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn len(&self) -> usize { diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1a58ad51f7..588ba2de22 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -586,7 +586,6 @@ impl LinkedList { /// dl.push_back(3); /// assert_eq!(dl.len(), 3); /// ``` - #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { @@ -1243,6 +1242,20 @@ impl<'a, T> Cursor<'a, T> { prev.map(|prev| &(*prev.as_ptr()).element) } } + + /// Provides a reference to the front element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn front(&self) -> Option<&'a T> { + self.list.front() + } + + /// Provides a reference to the back element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn back(&self) -> Option<&'a T> { + self.list.back() + } } impl<'a, T> CursorMut<'a, T> { @@ -1506,6 +1519,135 @@ impl<'a, T> CursorMut<'a, T> { self.index = 0; unsafe { self.list.split_off_before_node(self.current, split_off_idx) } } + + /// Appends an element to the front of the cursor's parent list. The node + /// that the cursor points to is unchanged, even if it is the "ghost" node. + /// + /// This operation should compute in O(1) time. + // `push_front` continues to point to "ghost" when it addes a node to mimic + // the behavior of `insert_before` on an empty list. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn push_front(&mut self, elt: T) { + // Safety: We know that `push_front` does not change the position in + // memory of other nodes. This ensures that `self.current` remains + // valid. + self.list.push_front(elt); + self.index += 1; + } + + /// Appends an element to the back of the cursor's parent list. The node + /// that the cursor points to is unchanged, even if it is the "ghost" node. + /// + /// This operation should compute in O(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn push_back(&mut self, elt: T) { + // Safety: We know that `push_back` does not change the position in + // memory of other nodes. This ensures that `self.current` remains + // valid. + self.list.push_back(elt); + if self.current().is_none() { + // The index of "ghost" is the length of the list, so we just need + // to increment self.index to reflect the new length of the list. + self.index += 1; + } + } + + /// Removes the first element from the cursor's parent list and returns it, + /// or None if the list is empty. The element the cursor points to remains + /// unchanged, unless it was pointing to the front element. In that case, it + /// points to the new front element. + /// + /// This operation should compute in O(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn pop_front(&mut self) -> Option { + // We can't check if current is empty, we must check the list directly. + // It is possible for `self.current == None` and the list to be + // non-empty. + if self.list.is_empty() { + 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. + // 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 { + self.move_next(); + } else { + self.index -= 1; + } + self.list.pop_front() + } + } + + /// Removes the last element from the cursor's parent list and returns it, + /// or None if the list is empty. The element the cursor points to remains + /// unchanged, unless it was pointing to the back element. In that case, it + /// points to the "ghost" element. + /// + /// This operation should compute in O(1) time. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn pop_back(&mut self) -> Option { + if self.list.is_empty() { + None + } else { + if self.list.tail == self.current { + // The index now reflects the length of the list. It was the + // length of the list minus 1, but now the list is 1 smaller. No + // change is needed for `index`. + self.current = None; + } else if self.current.is_none() { + self.index = self.list.len - 1; + } + self.list.pop_back() + } + } + + /// Provides a reference to the front element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn front(&self) -> Option<&T> { + self.list.front() + } + + /// Provides a mutable reference to the front element of the cursor's + /// parent list, or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn front_mut(&mut self) -> Option<&mut T> { + self.list.front_mut() + } + + /// Provides a reference to the back element of the cursor's parent list, + /// or None if the list is empty. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn back(&self) -> Option<&T> { + self.list.back() + } + + /// Provides a mutable reference to back element of the cursor's parent + /// list, or `None` if the list is empty. + /// + /// # Examples + /// Building and mutating a list with a cursor, then getting the back element: + /// ``` + /// #![feature(linked_list_cursors)] + /// use std::collections::LinkedList; + /// let mut dl = LinkedList::new(); + /// dl.push_front(3); + /// dl.push_front(2); + /// dl.push_front(1); + /// let mut cursor = dl.cursor_front_mut(); + /// *cursor.current().unwrap() = 99; + /// *cursor.back_mut().unwrap() = 0; + /// let mut contents = dl.into_iter(); + /// assert_eq!(contents.next(), Some(99)); + /// assert_eq!(contents.next(), Some(2)); + /// assert_eq!(contents.next(), Some(0)); + /// assert_eq!(contents.next(), None); + /// ``` + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn back_mut(&mut self) -> Option<&mut T> { + self.list.back_mut() + } } /// An iterator produced by calling `drain_filter` on LinkedList. diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs index ad643a7bdf..5a65ed7a96 100644 --- a/library/alloc/src/collections/linked_list/tests.rs +++ b/library/alloc/src/collections/linked_list/tests.rs @@ -428,3 +428,50 @@ fn test_cursor_mut_insert() { check_links(&m); assert_eq!(m.iter().cloned().collect::>(), &[200, 201, 202, 203, 1, 100, 101]); } + +#[test] +fn test_cursor_push_front_back() { + let mut ll: LinkedList = LinkedList::new(); + ll.extend(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + let mut c = ll.cursor_front_mut(); + assert_eq!(c.current(), Some(&mut 1)); + assert_eq!(c.index(), Some(0)); + c.push_front(0); + assert_eq!(c.current(), Some(&mut 1)); + assert_eq!(c.peek_prev(), Some(&mut 0)); + assert_eq!(c.index(), Some(1)); + c.push_back(11); + drop(c); + let p = ll.cursor_back().front().unwrap(); + assert_eq!(p, &0); + assert_eq!(ll, (0..12).collect()); + check_links(&ll); +} + +#[test] +fn test_cursor_pop_front_back() { + let mut ll: LinkedList = LinkedList::new(); + ll.extend(&[1, 2, 3, 4, 5, 6]); + let mut c = ll.cursor_back_mut(); + assert_eq!(c.pop_front(), Some(1)); + c.move_prev(); + c.move_prev(); + c.move_prev(); + assert_eq!(c.pop_back(), Some(6)); + let c = c.as_cursor(); + assert_eq!(c.front(), Some(&2)); + assert_eq!(c.back(), Some(&5)); + assert_eq!(c.index(), Some(1)); + drop(c); + assert_eq!(ll, (2..6).collect()); + check_links(&ll); + let mut c = ll.cursor_back_mut(); + assert_eq!(c.current(), Some(&mut 5)); + assert_eq!(c.index, 3); + assert_eq!(c.pop_back(), Some(5)); + assert_eq!(c.current(), None); + assert_eq!(c.index, 3); + assert_eq!(c.pop_back(), Some(4)); + assert_eq!(c.current(), None); + assert_eq!(c.index, 2); +} diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index b9b3d650ea..97bfe2f398 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -83,6 +83,7 @@ pub enum TryReserveError { #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] impl From for TryReserveError { + /// Always evaluates to [`TryReserveError::CapacityOverflow`]. #[inline] fn from(_: LayoutError) -> Self { TryReserveError::CapacityOverflow diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index f3eb228c9e..ae1b03c9a4 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -103,6 +103,7 @@ impl<'a, T> Iterator for Iter<'a, T> { } #[inline] + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item where Self: TrustedRandomAccess, diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 9493676e66..df30c38652 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -89,6 +89,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { } #[inline] + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item where Self: TrustedRandomAccess, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 5d03be35e4..461e701be0 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1036,7 +1036,6 @@ impl VecDeque { /// v.push_back(1); /// assert_eq!(v.len(), 1); /// ``` - #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { count(self.tail, self.head, self.cap()) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index a04e7c8a49..fa1f361a5b 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -56,6 +56,10 @@ //! [`Rc`]: rc //! [`RefCell`]: core::cell +// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] #![allow(unused_attributes)] #![stable(feature = "alloc", since = "1.36.0")] #![doc( @@ -109,7 +113,6 @@ #![feature(iter_zip)] #![feature(lang_items)] #![feature(layout_for_ptr)] -#![feature(maybe_uninit_ref)] #![feature(negative_impls)] #![feature(never_type)] #![feature(nll)] @@ -137,8 +140,7 @@ #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)] #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] -#![cfg_attr(bootstrap, feature(try_trait))] -#![cfg_attr(not(bootstrap), feature(try_trait_v2))] +#![feature(try_trait_v2)] #![feature(min_type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 6a64587a22..189da9f063 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -35,8 +35,6 @@ /// /// [`Vec`]: crate::vec::Vec #[cfg(not(test))] -#[doc(alias = "alloc")] -#[doc(alias = "malloc")] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(box_syntax, liballoc_internals)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 2e2c9b76bd..d11d4031f7 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -463,7 +463,6 @@ impl RawVec { Ok(()) } - #[cfg(not(no_global_oom_handling))] fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> { assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity"); diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f131182a89..e116ab6483 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -262,6 +262,7 @@ use core::marker::{self, PhantomData, Unpin, Unsize}; use core::mem::size_of_val; use core::mem::{self, align_of_val_raw, forget}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +#[cfg(not(no_global_oom_handling))] use core::pin::Pin; use core::ptr::{self, NonNull}; #[cfg(not(no_global_oom_handling))] @@ -346,6 +347,7 @@ impl Rc { /// /// let five = Rc::new(5); /// ``` + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(value: T) -> Rc { // There is an implicit weak pointer owned by all the strong @@ -381,6 +383,7 @@ impl Rc { /// } /// } /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "arc_new_cyclic", issue = "75861")] pub fn new_cyclic(data_fn: impl FnOnce(&Weak) -> T) -> Rc { // Construct the inner in the "uninitialized" state with a single @@ -577,6 +580,7 @@ impl Rc { } /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] pub fn pin(value: T) -> Pin> { unsafe { Pin::new_unchecked(Rc::new(value)) } @@ -1473,6 +1477,7 @@ impl Clone for Rc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Rc { /// Creates a new `Rc`, with the `Default` value for `T`. @@ -1731,6 +1736,7 @@ impl fmt::Pointer for Rc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Rc { /// Converts a generic type `T` into a `Rc` diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index dcd6489920..4c8ea6902f 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -1042,7 +1042,7 @@ where } /// This merge sort borrows some (but not all) ideas from TimSort, which is described in detail -/// [here](http://svn.python.org/projects/python/trunk/Objects/listsort.txt). +/// [here](https://github.com/python/cpython/blob/main/Objects/listsort.txt). /// /// The algorithm identifies strictly descending and non-descending subsequences, which are called /// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 57279e81a9..62ba2e5765 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -396,7 +396,7 @@ impl str { return s; fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) { - // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 + // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 // for the definition of `Final_Sigma`. debug_assert!('Σ'.len_utf8() == 2); let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 93f5fe45cd..0d8678291b 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -419,8 +419,6 @@ impl String { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[doc(alias = "alloc")] - #[doc(alias = "malloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(capacity: usize) -> String { String { vec: Vec::with_capacity(capacity) } @@ -1451,7 +1449,7 @@ impl String { unsafe { ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); - ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); + ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); self.vec.set_len(len + amt); } } @@ -1534,7 +1532,6 @@ impl String { /// assert_eq!(fancy_f.len(), 4); /// assert_eq!(fancy_f.chars().count(), 3); /// ``` - #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { @@ -2769,33 +2766,31 @@ impl<'a> Drain<'a> { /// # Examples /// /// ``` - /// #![feature(string_drain_as_str)] /// let mut s = String::from("abc"); /// let mut drain = s.drain(..); /// assert_eq!(drain.as_str(), "abc"); /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_str(), "bc"); /// ``` - #[unstable(feature = "string_drain_as_str", issue = "76905")] // Note: uncomment AsRef impls below when stabilizing. + #[stable(feature = "string_drain_as_str", since = "1.55.0")] pub fn as_str(&self) -> &str { self.iter.as_str() } } -// Uncomment when stabilizing `string_drain_as_str`. -// #[unstable(feature = "string_drain_as_str", issue = "76905")] -// impl<'a> AsRef for Drain<'a> { -// fn as_ref(&self) -> &str { -// self.as_str() -// } -// } -// -// #[unstable(feature = "string_drain_as_str", issue = "76905")] -// impl<'a> AsRef<[u8]> for Drain<'a> { -// fn as_ref(&self) -> &[u8] { -// self.as_str().as_bytes() -// } -// } +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a> AsRef for Drain<'a> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +#[stable(feature = "string_drain_as_str", since = "1.55.0")] +impl<'a> AsRef<[u8]> for Drain<'a> { + fn as_ref(&self) -> &[u8] { + self.as_str().as_bytes() + } +} #[stable(feature = "drain", since = "1.6.0")] impl Iterator for Drain<'_> { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a8fa028fc9..d821e71562 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -332,6 +332,7 @@ impl Arc { /// /// let five = Arc::new(5); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(data: T) -> Arc { @@ -365,6 +366,7 @@ impl Arc { /// me: me.clone(), /// }); /// ``` + #[cfg(not(no_global_oom_handling))] #[inline] #[unstable(feature = "arc_new_cyclic", issue = "75861")] pub fn new_cyclic(data_fn: impl FnOnce(&Weak) -> T) -> Arc { @@ -485,11 +487,19 @@ impl Arc { /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. + #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] pub fn pin(data: T) -> Pin> { unsafe { Pin::new_unchecked(Arc::new(data)) } } + /// Constructs a new `Pin>`, return an error if allocation fails. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_pin(data: T) -> Result>, AllocError> { + unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) } + } + /// Constructs a new `Arc`, returning an error if allocation fails. /// /// # Examples @@ -2274,6 +2284,7 @@ impl fmt::Pointer for Arc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Arc { /// Creates a new `Arc`, with the `Default` value for `T`. @@ -2298,8 +2309,23 @@ impl Hash for Arc { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Arc { + /// Converts a `T` into an `Arc` + /// + /// The conversion moves the value into a + /// newly allocated `Arc`. It is equivalent to + /// calling `Arc::new(t)`. + /// + /// # Example + /// ```rust + /// # use std::sync::Arc; + /// let x = 5; + /// let arc = Arc::new(5); + /// + /// assert_eq!(Arc::from(x), arc); + /// ``` fn from(t: T) -> Self { Arc::new(t) } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 8da4d995ba..7a08f4c6cb 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -163,6 +163,7 @@ impl Iterator for IntoIter { self.len() } + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item where Self: TrustedRandomAccess, diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 4a1d564e2a..6159925973 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -459,7 +459,6 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[doc(alias = "malloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) @@ -799,7 +798,6 @@ impl Vec { /// assert!(vec.capacity() >= 11); /// ``` #[cfg(not(no_global_oom_handling))] - #[doc(alias = "realloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { self.buf.reserve(self.len, additional); @@ -826,7 +824,6 @@ impl Vec { /// assert!(vec.capacity() >= 11); /// ``` #[cfg(not(no_global_oom_handling))] - #[doc(alias = "realloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve_exact(&mut self, additional: usize) { self.buf.reserve_exact(self.len, additional); @@ -864,7 +861,6 @@ impl Vec { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[doc(alias = "realloc")] #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve(self.len, additional) @@ -906,7 +902,6 @@ impl Vec { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[doc(alias = "realloc")] #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve_exact(self.len, additional) @@ -927,7 +922,6 @@ impl Vec { /// assert!(vec.capacity() >= 3); /// ``` #[cfg(not(no_global_oom_handling))] - #[doc(alias = "realloc")] #[stable(feature = "rust1", since = "1.0.0")] pub fn shrink_to_fit(&mut self) { // The capacity is never less than the length, and there's nothing to do when @@ -958,7 +952,6 @@ impl Vec { /// assert!(vec.capacity() >= 3); /// ``` #[cfg(not(no_global_oom_handling))] - #[doc(alias = "realloc")] #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] pub fn shrink_to(&mut self, min_capacity: usize) { if self.capacity() > min_capacity { @@ -1820,7 +1813,6 @@ impl Vec { /// let a = vec![1, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` - #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { @@ -2407,6 +2399,18 @@ impl Clone for Vec { } } +/// The hash of a vector is the same as that of the corresponding slice, +/// as required by the `core::borrow::Borrow` implementation. +/// +/// ``` +/// #![feature(build_hasher_simple_hash_one)] +/// use std::hash::BuildHasher; +/// +/// let b = std::collections::hash_map::RandomState::new(); +/// let v: Vec = vec![0xa8, 0x3c, 0x09]; +/// let s: &[u8] = &[0xa8, 0x3c, 0x09]; +/// assert_eq!(b.hash_one(v), b.hash_one(s)); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Vec { #[inline] @@ -2551,6 +2555,8 @@ impl Vec { } unsafe { ptr::write(self.as_mut_ptr().add(len), element); + // Since next() executes user code which can panic we have to bump the length + // after each step. // NB can't overflow since we would have had to alloc the address space self.set_len(len + 1); } diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index e857d284d3..d814d4ae35 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -89,6 +89,8 @@ fn write_in_place_with_drop( // all we can do is check if it's still in range debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); ptr::write(sink.dst, item); + // Since this executes user code which can panic we have to bump the pointer + // after each step. sink.dst = sink.dst.add(1); } Ok(sink) @@ -136,6 +138,8 @@ where let dst = dst_buf.offset(i as isize); debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation"); ptr::write(dst, self.__iterator_get_unchecked(i)); + // Since this executes user code which can panic we have to bump the pointer + // after each step. drop_guard.dst = dst.add(1); } } diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index c6f4f22a01..c3b4534096 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -40,6 +40,8 @@ where iterator.for_each(move |element| { ptr::write(ptr, element); ptr = ptr.offset(1); + // Since the loop executes user code which can panic we have to bump the pointer + // after each step. // NB can't overflow since we would have had to alloc the address space local_len.increment_len(1); }); diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index 6df8d8c2f3..a1e819cf8f 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -534,7 +534,7 @@ mod slice_index { #[test] #[should_panic] fn test_slice_fail() { - &"中华Việt Nam"[0..2]; + let _ = &"中华Việt Nam"[0..2]; } panic_cases! { @@ -714,13 +714,13 @@ mod slice_index { #[test] #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")] fn test_slice_fail_truncated_1() { - &LOREM_PARAGRAPH[..1024]; + let _ = &LOREM_PARAGRAPH[..1024]; } // check the truncation in the panic message #[test] #[should_panic(expected = "luctus, im`[...]")] fn test_slice_fail_truncated_2() { - &LOREM_PARAGRAPH[..1024]; + let _ = &LOREM_PARAGRAPH[..1024]; } } @@ -735,7 +735,7 @@ fn test_str_slice_rangetoinclusive_ok() { #[should_panic] fn test_str_slice_rangetoinclusive_notok() { let s = "abcαβγ"; - &s[..=3]; + let _ = &s[..=3]; } #[test] @@ -751,7 +751,7 @@ fn test_str_slicemut_rangetoinclusive_ok() { fn test_str_slicemut_rangetoinclusive_notok() { let mut s = "abcαβγ".to_owned(); let s: &mut str = &mut s; - &mut s[..=3]; + let _ = &mut s[..=3]; } #[test] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index c203cdafec..3b72370168 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -542,35 +542,35 @@ fn test_index_out_of_bounds() { #[should_panic] fn test_slice_out_of_bounds_1() { let x = vec![1, 2, 3, 4, 5]; - &x[!0..]; + let _ = &x[!0..]; } #[test] #[should_panic] fn test_slice_out_of_bounds_2() { let x = vec![1, 2, 3, 4, 5]; - &x[..6]; + let _ = &x[..6]; } #[test] #[should_panic] fn test_slice_out_of_bounds_3() { let x = vec![1, 2, 3, 4, 5]; - &x[!0..4]; + let _ = &x[!0..4]; } #[test] #[should_panic] fn test_slice_out_of_bounds_4() { let x = vec![1, 2, 3, 4, 5]; - &x[1..6]; + let _ = &x[1..6]; } #[test] #[should_panic] fn test_slice_out_of_bounds_5() { let x = vec![1, 2, 3, 4, 5]; - &x[3..2]; + let _ = &x[3..2]; } #[test] diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index f2169914ac..24257ba987 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -45,7 +45,7 @@ fn bench_max_by_key(b: &mut Bencher) { }) } -// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/ +// https://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/ #[bench] fn bench_max_by_key2(b: &mut Bencher) { fn max_index_iter(array: &[i32]) -> usize { diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index 6dcc110f15..0a098c8e2d 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -20,24 +20,69 @@ use crate::ptr; /// /// # Example /// -/// ```no_run -/// use std::alloc::{GlobalAlloc, Layout, alloc}; +/// ``` +/// use std::alloc::{GlobalAlloc, Layout}; +/// use std::cell::UnsafeCell; /// use std::ptr::null_mut; +/// use std::sync::atomic::{ +/// AtomicUsize, +/// Ordering::{Acquire, SeqCst}, +/// }; /// -/// struct MyAllocator; -/// -/// unsafe impl GlobalAlloc for MyAllocator { -/// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() } -/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +/// const ARENA_SIZE: usize = 128 * 1024; +/// const MAX_SUPPORTED_ALIGN: usize = 4096; +/// #[repr(C, align(4096))] // 4096 == MAX_SUPPORTED_ALIGN +/// struct SimpleAllocator { +/// arena: UnsafeCell<[u8; ARENA_SIZE]>, +/// remaining: AtomicUsize, // we allocate from the top, counting down /// } /// /// #[global_allocator] -/// static A: MyAllocator = MyAllocator; +/// static ALLOCATOR: SimpleAllocator = SimpleAllocator { +/// arena: UnsafeCell::new([0x55; ARENA_SIZE]), +/// remaining: AtomicUsize::new(ARENA_SIZE), +/// }; /// -/// fn main() { -/// unsafe { -/// assert!(alloc(Layout::new::()).is_null()) +/// unsafe impl Sync for SimpleAllocator {} +/// +/// unsafe impl GlobalAlloc for SimpleAllocator { +/// unsafe fn alloc(&self, layout: Layout) -> *mut u8 { +/// let size = layout.size(); +/// let align = layout.align(); +/// +/// // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2. +/// // So we can safely use a mask to ensure alignment without worrying about UB. +/// let align_mask_to_round_down = !(align - 1); +/// +/// if align > MAX_SUPPORTED_ALIGN { +/// return null_mut(); +/// } +/// +/// let mut allocated = 0; +/// if self +/// .remaining +/// .fetch_update(SeqCst, SeqCst, |mut remaining| { +/// if size > remaining { +/// return None; +/// } +/// remaining -= size; +/// remaining &= align_mask_to_round_down; +/// allocated = remaining; +/// Some(remaining) +/// }) +/// .is_err() +/// { +/// return null_mut(); +/// }; +/// (self.arena.get() as *mut u8).add(allocated) /// } +/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +/// } +/// +/// fn main() { +/// let _s = format!("allocating a string!"); +/// let currently = ALLOCATOR.remaining.load(Acquire); +/// println!("allocated so far: {}", ARENA_SIZE - currently); /// } /// ``` /// diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 0e7667dd89..ccf6e420de 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -60,7 +60,7 @@ impl Layout { #[inline] pub const fn from_size_align(size: usize, align: usize) -> Result { if !align.is_power_of_two() { - return Err(LayoutError { private: () }); + return Err(LayoutError); } // (power-of-two implies align != 0.) @@ -78,7 +78,7 @@ impl Layout { // Above implies that checking for summation overflow is both // necessary and sufficient. if size > usize::MAX - (align - 1) { - return Err(LayoutError { private: () }); + return Err(LayoutError); } // SAFETY: the conditions for `from_size_align_unchecked` have been @@ -288,7 +288,7 @@ impl Layout { // > must not overflow (i.e., the rounded value must be less than // > `usize::MAX`) let padded_size = self.size() + self.padding_needed_for(self.align()); - let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError { private: () })?; + let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?; // SAFETY: self.align is already known to be valid and alloc_size has been // padded already. @@ -346,8 +346,8 @@ impl Layout { let new_align = cmp::max(self.align(), next.align()); let pad = self.padding_needed_for(next.align()); - let offset = self.size().checked_add(pad).ok_or(LayoutError { private: () })?; - let new_size = offset.checked_add(next.size()).ok_or(LayoutError { private: () })?; + let offset = self.size().checked_add(pad).ok_or(LayoutError)?; + let new_size = offset.checked_add(next.size()).ok_or(LayoutError)?; let layout = Layout::from_size_align(new_size, new_align)?; Ok((layout, offset)) @@ -368,7 +368,7 @@ impl Layout { #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[inline] pub fn repeat_packed(&self, n: usize) -> Result { - let size = self.size().checked_mul(n).ok_or(LayoutError { private: () })?; + let size = self.size().checked_mul(n).ok_or(LayoutError)?; Layout::from_size_align(size, self.align()) } @@ -381,7 +381,7 @@ impl Layout { #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[inline] pub fn extend_packed(&self, next: Self) -> Result { - let new_size = self.size().checked_add(next.size()).ok_or(LayoutError { private: () })?; + let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?; Layout::from_size_align(new_size, self.align()) } @@ -409,10 +409,9 @@ pub type LayoutErr = LayoutError; /// or some other `Layout` constructor /// do not satisfy its documented constraints. #[stable(feature = "alloc_layout_error", since = "1.50.0")] +#[non_exhaustive] #[derive(Clone, PartialEq, Eq, Debug)] -pub struct LayoutError { - private: (), -} +pub struct LayoutError; // (we need this for downstream impl of trait Error) #[stable(feature = "alloc_layout", since = "1.28.0")] diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 5e1725cfc7..19652106b3 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -108,6 +108,7 @@ use crate::intrinsics; // unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call, // but we would likely want to indicate as such in documentation). #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Any")] pub trait Any: 'static { /// Gets the `TypeId` of `self`. /// diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs new file mode 100644 index 0000000000..6d66b9e2f2 --- /dev/null +++ b/library/core/src/array/equality.rs @@ -0,0 +1,160 @@ +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[B; N]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &[B; N]) -> bool { + SpecArrayEq::spec_eq(self, other) + } + #[inline] + fn ne(&self, other: &[B; N]) -> bool { + SpecArrayEq::spec_ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[B]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &[B]) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &[B]) -> bool { + self[..] != other[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[A; N]> for [B] +where + B: PartialEq, +{ + #[inline] + fn eq(&self, other: &[A; N]) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { + self[..] != other[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<&[B]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &&[B]) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &&[B]) -> bool { + self[..] != other[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[A; N]> for &[B] +where + B: PartialEq, +{ + #[inline] + fn eq(&self, other: &[A; N]) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { + self[..] != other[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<&mut [B]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &&mut [B]) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &&mut [B]) -> bool { + self[..] != other[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[A; N]> for &mut [B] +where + B: PartialEq, +{ + #[inline] + fn eq(&self, other: &[A; N]) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { + self[..] != other[..] + } +} + +// NOTE: some less important impls are omitted to reduce code bloat +// __impl_slice_eq2! { [A; $N], &'b [B; $N] } +// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for [T; N] {} + +trait SpecArrayEq: Sized { + fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; + fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; +} + +impl, Other, const N: usize> SpecArrayEq for T { + default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool { + a[..] == b[..] + } + default fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool { + a[..] != b[..] + } +} + +impl + IsRawEqComparable, U, const N: usize> SpecArrayEq for T { + #[cfg(bootstrap)] + fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { + a[..] == b[..] + } + #[cfg(not(bootstrap))] + fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { + // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`. + unsafe { + let b = &*b.as_ptr().cast::<[T; N]>(); + crate::intrinsics::raw_eq(a, b) + } + } + fn spec_ne(a: &[T; N], b: &[U; N]) -> bool { + !Self::spec_eq(a, b) + } +} + +/// `U` exists on here mostly because `min_specialization` didn't let me +/// repeat the `T` type parameter in the above specialization, so instead +/// the `T == U` constraint comes from the impls on this. +/// # Safety +/// - Neither `Self` nor `U` has any padding. +/// - `Self` and `U` have the same layout. +/// - `Self: PartialEq` is byte-wise (this means no floats, among other things) +#[rustc_specialization_trait] +unsafe trait IsRawEqComparable {} + +macro_rules! is_raw_comparable { + ($($t:ty),+) => {$( + unsafe impl IsRawEqComparable<$t> for $t {} + )+}; +} +is_raw_comparable!(bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 37af3557fd..78b799cd70 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -14,6 +14,7 @@ use crate::mem::{self, MaybeUninit}; use crate::ops::{Index, IndexMut}; use crate::slice::{Iter, IterMut}; +mod equality; mod iter; #[stable(feature = "array_value_iter", since = "1.51.0")] @@ -139,6 +140,18 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { } } +/// The hash of an array is the same as that of the corresponding slice, +/// as required by the `Borrow` implementation. +/// +/// ``` +/// #![feature(build_hasher_simple_hash_one)] +/// use std::hash::BuildHasher; +/// +/// let b = std::collections::hash_map::RandomState::new(); +/// let a: [u8; 3] = [0xa8, 0x3c, 0x09]; +/// let s: &[u8] = &[0xa8, 0x3c, 0x09]; +/// assert_eq!(b.hash_one(a), b.hash_one(s)); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] impl Hash for [T; N] { fn hash(&self, state: &mut H) { @@ -218,118 +231,6 @@ where } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[B; N]> for [A; N] -where - A: PartialEq, -{ - #[inline] - fn eq(&self, other: &[B; N]) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &[B; N]) -> bool { - self[..] != other[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[B]> for [A; N] -where - A: PartialEq, -{ - #[inline] - fn eq(&self, other: &[B]) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &[B]) -> bool { - self[..] != other[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for [B] -where - B: PartialEq, -{ - #[inline] - fn eq(&self, other: &[A; N]) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &[A; N]) -> bool { - self[..] != other[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&[B]> for [A; N] -where - A: PartialEq, -{ - #[inline] - fn eq(&self, other: &&[B]) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &&[B]) -> bool { - self[..] != other[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for &[B] -where - B: PartialEq, -{ - #[inline] - fn eq(&self, other: &[A; N]) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &[A; N]) -> bool { - self[..] != other[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&mut [B]> for [A; N] -where - A: PartialEq, -{ - #[inline] - fn eq(&self, other: &&mut [B]) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &&mut [B]) -> bool { - self[..] != other[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for &mut [B] -where - B: PartialEq, -{ - #[inline] - fn eq(&self, other: &[A; N]) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &[A; N]) -> bool { - self[..] != other[..] - } -} - -// NOTE: some less important impls are omitted to reduce code bloat -// __impl_slice_eq2! { [A; $N], &'b [B; $N] } -// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } - -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for [T; N] {} - #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for [T; N] { #[inline] @@ -395,7 +296,6 @@ impl [T; N] { /// # Examples /// /// ``` - /// #![feature(array_map)] /// let x = [1, 2, 3]; /// let y = x.map(|v| v + 1); /// assert_eq!(y, [2, 3, 4]); @@ -409,7 +309,7 @@ impl [T; N] { /// let y = x.map(|v| v.len()); /// assert_eq!(y, [6, 9, 3, 3]); /// ``` - #[unstable(feature = "array_map", issue = "75243")] + #[stable(feature = "array_map", since = "1.55.0")] pub fn map(self, f: F) -> [U; N] where F: FnMut(T) -> U, @@ -476,7 +376,7 @@ impl [T; N] { /// array if its elements are not `Copy`. /// /// ``` - /// #![feature(array_methods, array_map)] + /// #![feature(array_methods)] /// /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()]; /// let is_ascii = strings.each_ref().map(|s| s.is_ascii()); diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 00164c631b..dcafaae2f5 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -12,7 +12,7 @@ impl bool { /// assert_eq!(false.then_some(0), None); /// assert_eq!(true.then_some(0), Some(0)); /// ``` - #[unstable(feature = "bool_to_option", issue = "64260")] + #[unstable(feature = "bool_to_option", issue = "80967")] #[inline] pub fn then_some(self, t: T) -> Option { if self { Some(t) } else { None } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index f88a6e418c..24b0797f93 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -488,6 +488,13 @@ impl Cell { /// This call borrows `Cell` mutably (at compile-time) which guarantees /// that we possess the only reference. /// + /// However be cautious: this method expects `self` to be mutable, which is + /// generally not the case when using a `Cell`. If you require interior + /// mutability by reference, consider using `RefCell` which provides + /// run-time checked mutable borrows through its [`borrow_mut`] method. + /// + /// [`borrow_mut`]: RefCell::borrow_mut() + /// /// # Examples /// /// ``` @@ -578,7 +585,7 @@ pub struct RefCell { // Stores the location of the earliest currently active borrow. // This gets updated whenver we go from having zero borrows // to having a single borrow. When a borrow occurs, this gets included - // in the generated `BorroeError/`BorrowMutError` + // in the generated `BorrowError/`BorrowMutError` #[cfg(feature = "debug_refcell")] borrowed_at: Cell>>, value: UnsafeCell, @@ -586,8 +593,8 @@ pub struct RefCell { /// An error returned by [`RefCell::try_borrow`]. #[stable(feature = "try_borrow", since = "1.13.0")] +#[non_exhaustive] pub struct BorrowError { - _private: (), #[cfg(feature = "debug_refcell")] location: &'static crate::panic::Location<'static>, } @@ -613,8 +620,8 @@ impl Display for BorrowError { /// An error returned by [`RefCell::try_borrow_mut`]. #[stable(feature = "try_borrow", since = "1.13.0")] +#[non_exhaustive] pub struct BorrowMutError { - _private: (), #[cfg(feature = "debug_refcell")] location: &'static crate::panic::Location<'static>, } @@ -865,7 +872,6 @@ impl RefCell { Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }) } None => Err(BorrowError { - _private: (), // If a borrow occured, then we must already have an outstanding borrow, // so `borrowed_at` will be `Some` #[cfg(feature = "debug_refcell")] @@ -951,7 +957,6 @@ impl RefCell { Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }) } None => Err(BorrowMutError { - _private: (), // If a borrow occured, then we must already have an outstanding borrow, // so `borrowed_at` will be `Some` #[cfg(feature = "debug_refcell")] @@ -1073,7 +1078,6 @@ impl RefCell { Ok(unsafe { &*self.value.get() }) } else { Err(BorrowError { - _private: (), // If a borrow occured, then we must already have an outstanding borrow, // so `borrowed_at` will be `Some` #[cfg(feature = "debug_refcell")] diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 80d0890551..e5af22c8fb 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -15,8 +15,8 @@ impl char { /// Point], but only ones within a certain range. `MAX` is the highest valid /// code point that's a valid [Unicode Scalar Value]. /// - /// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value - /// [Code Point]: http://www.unicode.org/glossary/#code_point + /// [Unicode Scalar Value]: https://www.unicode.org/glossary/#unicode_scalar_value + /// [Code Point]: https://www.unicode.org/glossary/#code_point #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const MAX: char = '\u{10ffff}'; @@ -28,7 +28,7 @@ impl char { #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}'; - /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of + /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of /// `char` and `str` methods are based on. /// /// New versions of Unicode are released regularly and subsequently all methods @@ -1494,8 +1494,8 @@ impl char { /// before using this function. /// /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace - /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 - /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 + /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 + /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 /// /// # Examples /// diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 25a7c1de9d..0728523d0a 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -5,8 +5,8 @@ //! scalar value]', which is similar to, but not the same as, a '[Unicode code //! point]'. //! -//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value -//! [Unicode code point]: http://www.unicode.org/glossary/#code_point +//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +//! [Unicode code point]: https://www.unicode.org/glossary/#code_point //! //! This module exists for technical reasons, the primary documentation for //! `char` is directly on [the `char` primitive type][char] itself. @@ -95,8 +95,8 @@ const MAX_THREE_B: u32 = 0x10000; /// Point], but only ones within a certain range. `MAX` is the highest valid /// code point that's a valid [Unicode Scalar Value]. /// -/// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value -/// [Code Point]: http://www.unicode.org/glossary/#code_point +/// [Unicode Scalar Value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [Code Point]: https://www.unicode.org/glossary/#code_point #[stable(feature = "rust1", since = "1.0.0")] pub const MAX: char = char::MAX; diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 51a2dc03de..19faf9cdda 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -38,7 +38,7 @@ /// A common trait for the ability to explicitly duplicate an object. /// -/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while +/// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while /// `Clone` is always explicit and may or may not be expensive. In order to enforce /// these characteristics, Rust does not allow you to reimplement [`Copy`], but you /// may reimplement `Clone` and run arbitrary code. diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index ecea898504..79610bb409 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -27,12 +27,25 @@ use self::Ordering::*; /// Trait for equality comparisons which are [partial equivalence /// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation). /// +/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`. +/// We use the easier-to-read infix notation in the remainder of this documentation. +/// /// This trait allows for partial equality, for types that do not have a full /// equivalence relation. For example, in floating point numbers `NaN != NaN`, /// so floating point types implement `PartialEq` but not [`trait@Eq`]. /// -/// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`, -/// `C`): +/// Implementations must ensure that `eq` and `ne` are consistent with each other: +/// +/// - `a != b` if and only if `!(a == b)` +/// (ensured by the default implementation). +/// +/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also +/// be consistent with `PartialEq` (see the documentation of those traits for the exact +/// requirements). It's easy to accidentally make them disagree by deriving some of the traits and +/// manually implementing others. +/// +/// The equality relation `==` must satisfy the following conditions +/// (for all `a`, `b`, `c` of type `A`, `B`, `C`): /// /// - **Symmetric**: if `A: PartialEq` and `B: PartialEq`, then **`a == b` /// implies `b == a`**; and @@ -53,15 +66,6 @@ use self::Ordering::*; /// /// ## How can I implement `PartialEq`? /// -/// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined -/// in terms of it by default. Any manual implementation of [`ne`] *must* respect -/// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and -/// only if `a != b`. -/// -/// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with -/// each other. It's easy to accidentally make them disagree by deriving some -/// of the traits and manually implementing others. -/// /// An example implementation for a domain in which two books are considered /// the same book if their ISBN matches, even if the formats differ: /// @@ -631,10 +635,25 @@ impl Clone for Reverse { /// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order). /// -/// An order is a total order if it is (for all `a`, `b` and `c`): +/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure +/// `max`, `min`, and `clamp` are consistent with `cmp`: +/// +/// - `partial_cmp(a, b) == Some(cmp(a, b))`. +/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation). +/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation). +/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp) +/// (ensured by the default implementation). +/// +/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by +/// deriving some of the traits and manually implementing others. +/// +/// ## Corollaries +/// +/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order. +/// This means that for all `a`, `b` and `c`: /// -/// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and -/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. +/// - exactly one of `a < b`, `a == b` or `a > b` is true; and +/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. /// /// ## Derivable /// @@ -659,12 +678,6 @@ impl Clone for Reverse { /// Then you must define an implementation for [`cmp`]. You may find it useful to use /// [`cmp`] on your type's fields. /// -/// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must* -/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if -/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for -/// all `a` and `b`. It's easy to accidentally make them disagree by -/// deriving some of the traits and manually implementing others. -/// /// Here's an example where you want to sort people by height only, disregarding `id` /// and `name`: /// @@ -824,15 +837,45 @@ impl PartialOrd for Ordering { /// Trait for values that can be compared for a sort-order. /// +/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using +/// the `<`, `<=`, `>`, and `>=` operators, respectively. +/// +/// The methods of this trait must be consistent with each other and with those of `PartialEq` in +/// the following sense: +/// +/// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`. +/// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)` +/// (ensured by the default implementation). +/// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)` +/// (ensured by the default implementation). +/// - `a <= b` if and only if `a < b || a == b` +/// (ensured by the default implementation). +/// - `a >= b` if and only if `a > b || a == b` +/// (ensured by the default implementation). +/// - `a != b` if and only if `!(a == b)` (already part of `PartialEq`). +/// +/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with +/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's +/// easy to accidentally make them disagree by deriving some of the traits and manually +/// implementing others. +/// /// The comparison must satisfy, for all `a`, `b` and `c`: /// -/// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and /// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. +/// - duality: `a < b` if and only if `b > a`. /// /// Note that these requirements mean that the trait itself must be implemented symmetrically and /// transitively: if `T: PartialOrd` and `U: PartialOrd` then `U: PartialOrd` and `T: /// PartialOrd`. /// +/// ## Corollaries +/// +/// The following corollaries follow from the above requirements: +/// +/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)` +/// - transitivity of `>`: if `a > b` and `b > c` then `a > c` +/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)` +/// /// ## Derivable /// /// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a @@ -850,10 +893,6 @@ impl PartialOrd for Ordering { /// /// `PartialOrd` requires your type to be [`PartialEq`]. /// -/// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's -/// easy to accidentally make them disagree by deriving some of the traits and manually -/// implementing others. -/// /// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]: /// /// ``` @@ -1065,6 +1104,7 @@ pub macro PartialOrd($item:item) { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")] pub fn min(v1: T, v2: T) -> T { v1.min(v2) } @@ -1127,6 +1167,7 @@ pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")] pub fn max(v1: T, v2: T) -> T { v1.max(v2) } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 65af8508a6..1e512af480 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -152,6 +152,7 @@ pub const fn identity(x: T) -> T { /// is_hello(s); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")] pub trait AsRef { /// Performs the conversion. #[stable(feature = "rust1", since = "1.0.0")] @@ -193,6 +194,7 @@ pub trait AsRef { /// /// [`Box`]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")] pub trait AsMut { /// Performs the conversion. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index a522b7da3b..1d3a129621 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -145,7 +145,7 @@ impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.2 // CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize. // https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf -// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf +// https://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf // Note: integers can only be represented with full precision in a float if // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index ece3cde001..ba65f0fadb 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -1,6 +1,7 @@ use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp}; use crate::mem::MaybeUninit; use crate::num::flt2dec; +use crate::num::fmt as numfmt; // Don't inline this so callers don't use the stack space this function // requires unless they have to. @@ -15,7 +16,7 @@ where T: flt2dec::DecodableFloat, { let mut buf: [MaybeUninit; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64 - let mut parts: [MaybeUninit>; 4] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit>; 4] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_exact_fixed_str( flt2dec::strategy::grisu::format_exact, *num, @@ -41,7 +42,7 @@ where { // enough for f32 and f64 let mut buf: [MaybeUninit; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array(); - let mut parts: [MaybeUninit>; 4] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit>; 4] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_shortest_str( flt2dec::strategy::grisu::format_shortest, *num, @@ -85,7 +86,7 @@ where T: flt2dec::DecodableFloat, { let mut buf: [MaybeUninit; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64 - let mut parts: [MaybeUninit>; 6] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit>; 6] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_exact_exp_str( flt2dec::strategy::grisu::format_exact, *num, @@ -112,7 +113,7 @@ where { // enough for f32 and f64 let mut buf: [MaybeUninit; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array(); - let mut parts: [MaybeUninit>; 6] = MaybeUninit::uninit_array(); + let mut parts: [MaybeUninit>; 6] = MaybeUninit::uninit_array(); let formatted = flt2dec::to_shortest_exp_str( flt2dec::strategy::grisu::format_shortest, *num, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 02ac4fb800..48142f6691 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -7,13 +7,16 @@ use crate::char::EscapeDebugExtArgs; use crate::iter; use crate::marker::PhantomData; use crate::mem; -use crate::num::flt2dec; +use crate::num::fmt as numfmt; use crate::ops::Deref; use crate::result; use crate::str; mod builders; +#[cfg(not(no_fp_fmt_parse))] mod float; +#[cfg(no_fp_fmt_parse)] +mod nofloat; mod num; #[stable(feature = "fmt_flags_align", since = "1.28.0")] @@ -444,8 +447,9 @@ impl<'a> Arguments<'a> { /// assert_eq!(format_args!("{}", 1).as_str(), None); /// ``` #[stable(feature = "fmt_as_str", since = "1.52.0")] + #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "none")] #[inline] - pub fn as_str(&self) -> Option<&'static str> { + pub const fn as_str(&self) -> Option<&'static str> { match (self.pieces, self.args) { ([], []) => Some(""), ([s], []) => Some(s), @@ -564,7 +568,7 @@ impl Display for Arguments<'_> { on( crate_local, label = "`{Self}` cannot be formatted using `{{:?}}`", - note = "add `#[derive(Debug)]` or manually implement `{Debug}`" + note = "add `#[derive(Debug)]` to `{Self}` or manually `impl {Debug} for {Self}`" ), message = "`{Self}` doesn't implement `{Debug}`", label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`" @@ -662,6 +666,7 @@ pub use macros::Debug; note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead" )] #[doc(alias = "{}")] +#[rustc_diagnostic_item = "display_trait"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Display { /// Formats the value using the given formatter. @@ -1421,7 +1426,7 @@ impl<'a> Formatter<'a> { /// Takes the formatted parts and applies the padding. /// Assumes that the caller already has rendered the parts with required precision, /// so that `self.precision` can be ignored. - fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result { + fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { if let Some(mut width) = self.width { // for the sign-aware zero padding, we render the sign first and // behave as if we had no sign from the beginning. @@ -1461,14 +1466,14 @@ impl<'a> Formatter<'a> { } } - fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result { + fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result { - // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`. - // It's safe to use for `flt2dec::Part::Num` since every char `c` is between + // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`. + // It's safe to use for `numfmt::Part::Num` since every char `c` is between // `b'0'` and `b'9'`, which means `s` is valid UTF-8. - // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)` + // It's also probably safe in practice to use for `numfmt::Part::Copy(buf)` // since `buf` should be plain ASCII, but it's possible for someone to pass - // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is a + // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a // public function. // FIXME: Determine whether this could result in UB. buf.write_str(unsafe { str::from_utf8_unchecked(s) }) @@ -1479,7 +1484,7 @@ impl<'a> Formatter<'a> { } for part in formatted.parts { match *part { - flt2dec::Part::Zero(mut nzeroes) => { + numfmt::Part::Zero(mut nzeroes) => { const ZEROES: &str = // 64 zeroes "0000000000000000000000000000000000000000000000000000000000000000"; while nzeroes > ZEROES.len() { @@ -1490,7 +1495,7 @@ impl<'a> Formatter<'a> { self.buf.write_str(&ZEROES[..nzeroes])?; } } - flt2dec::Part::Num(mut v) => { + numfmt::Part::Num(mut v) => { let mut s = [0; 5]; let len = part.len(); for c in s[..len].iter_mut().rev() { @@ -1499,7 +1504,7 @@ impl<'a> Formatter<'a> { } write_bytes(self.buf, &s[..len])?; } - flt2dec::Part::Copy(buf) => { + numfmt::Part::Copy(buf) => { write_bytes(self.buf, buf)?; } } diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs new file mode 100644 index 0000000000..cfb94cd9de --- /dev/null +++ b/library/core/src/fmt/nofloat.rs @@ -0,0 +1,15 @@ +use crate::fmt::{Debug, Formatter, Result}; + +macro_rules! floating { + ($ty:ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl Debug for $ty { + fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result { + panic!("floating point support is turned off"); + } + } + }; +} + +floating! { f32 } +floating! { f64 } diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index cdd731fdd4..db45640df4 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -2,7 +2,7 @@ use crate::fmt; use crate::mem::MaybeUninit; -use crate::num::flt2dec; +use crate::num::fmt as numfmt; use crate::ops::{Div, Rem, Sub}; use crate::ptr; use crate::slice; @@ -406,9 +406,9 @@ macro_rules! impl_Exp { }; let parts = &[ - flt2dec::Part::Copy(buf_slice), - flt2dec::Part::Zero(added_precision), - flt2dec::Part::Copy(exp_slice) + numfmt::Part::Copy(buf_slice), + numfmt::Part::Zero(added_precision), + numfmt::Part::Copy(exp_slice) ]; let sign = if !is_nonnegative { "-" @@ -417,7 +417,7 @@ macro_rules! impl_Exp { } else { "" }; - let formatted = flt2dec::Formatted{sign, parts}; + let formatted = numfmt::Formatted{sign, parts}; f.pad_formatted_parts(&formatted) } diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 77d3a35b26..8dec643255 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -481,6 +481,53 @@ pub trait BuildHasher { /// ``` #[stable(since = "1.7.0", feature = "build_hasher")] fn build_hasher(&self) -> Self::Hasher; + + /// Calculates the hash of a single value. + /// + /// This is intended as a convenience for code which *consumes* hashes, such + /// as the implementation of a hash table or in unit tests that check + /// whether a custom [`Hash`] implementation behaves as expected. + /// + /// This must not be used in any code which *creates* hashes, such as in an + /// implementation of [`Hash`]. The way to create a combined hash of + /// multiple values is to call [`Hash::hash`] multiple times using the same + /// [`Hasher`], not to call this method repeatedly and combine the results. + /// + /// # Example + /// + /// ``` + /// #![feature(build_hasher_simple_hash_one)] + /// + /// use std::cmp::{max, min}; + /// use std::hash::{BuildHasher, Hash, Hasher}; + /// struct OrderAmbivalentPair(T, T); + /// impl Hash for OrderAmbivalentPair { + /// fn hash(&self, hasher: &mut H) { + /// min(&self.0, &self.1).hash(hasher); + /// max(&self.0, &self.1).hash(hasher); + /// } + /// } + /// + /// // Then later, in a `#[test]` for the type... + /// let bh = std::collections::hash_map::RandomState::new(); + /// assert_eq!( + /// bh.hash_one(OrderAmbivalentPair(1, 2)), + /// bh.hash_one(OrderAmbivalentPair(2, 1)) + /// ); + /// assert_eq!( + /// bh.hash_one(OrderAmbivalentPair(10, 2)), + /// bh.hash_one(&OrderAmbivalentPair(2, 10)) + /// ); + /// ``` + #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")] + fn hash_one(&self, x: T) -> u64 + where + Self: Sized, + { + let mut hasher = self.build_hasher(); + x.hash(&mut hasher); + hasher.finish() + } } /// Used to create a default [`BuildHasher`] instance for types that implement diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 70ab27cbfa..238f00e41b 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -25,7 +25,7 @@ //! across other volatile intrinsics. See the LLVM documentation on //! [[volatile]]. //! -//! [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses +//! [volatile]: https://llvm.org/docs/LangRef.html#volatile-memory-accesses //! //! # Atomics //! @@ -33,7 +33,7 @@ //! words, with multiple possible memory orderings. They obey the same //! semantics as C++11. See the LLVM documentation on [[atomics]]. //! -//! [atomics]: http://llvm.org/docs/Atomics.html +//! [atomics]: https://llvm.org/docs/Atomics.html //! //! A quick refresher on memory ordering: //! @@ -712,8 +712,19 @@ extern "rust-intrinsic" { /// Aborts the execution of the process. /// - /// A more user-friendly and stable version of this operation is - /// [`std::process::abort`](../../std/process/fn.abort.html). + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// + /// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible, + /// as its behavior is more user-friendly and more stable. + /// + /// The current implementation of `intrinsics::abort` is to invoke an invalid instruction, + /// on most platforms. + /// 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. pub fn abort() -> !; /// Informs the optimizer that this point in the code is not reachable, @@ -745,6 +756,11 @@ extern "rust-intrinsic" { /// /// Any use other than with `if` statements will probably not have an effect. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn likely(b: bool) -> bool; @@ -754,6 +770,11 @@ extern "rust-intrinsic" { /// /// Any use other than with `if` statements will probably not have an effect. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// This intrinsic does not have a stable counterpart. #[rustc_const_unstable(feature = "const_likely", issue = "none")] pub fn unlikely(b: bool) -> bool; @@ -765,6 +786,11 @@ extern "rust-intrinsic" { /// The size of a type in bytes. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// More specifically, this is the offset in bytes between successive /// items of the same type, including alignment padding. /// @@ -774,6 +800,11 @@ extern "rust-intrinsic" { /// The minimum alignment of a type. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::mem::align_of`]. #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")] pub fn min_align_of() -> usize; @@ -796,6 +827,11 @@ extern "rust-intrinsic" { /// Gets a static string slice containing the name of a type. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::any::type_name`]. #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub fn type_name() -> &'static str; @@ -804,6 +840,11 @@ extern "rust-intrinsic" { /// function will return the same value for a type regardless of whichever /// crate it is invoked in. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] pub fn type_id() -> u64; @@ -829,6 +870,11 @@ extern "rust-intrinsic" { /// Gets a reference to a static `Location` indicating where it was called. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// Consider using [`core::panic::Location::caller`] instead. #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")] pub fn caller_location() -> &'static crate::panic::Location<'static>; @@ -837,6 +883,11 @@ extern "rust-intrinsic" { /// /// This exists solely for [`mem::forget_unsized`]; normal `forget` uses /// `ManuallyDrop` instead. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")] pub fn forget(_: T); @@ -1090,6 +1141,11 @@ extern "rust-intrinsic" { /// If the actual type neither requires drop glue nor implements /// `Copy`, then the return value of this function is unspecified. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// 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")] pub fn needs_drop() -> bool; @@ -1310,21 +1366,41 @@ extern "rust-intrinsic" { /// Returns the minimum of two `f32` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f32::min`] pub fn minnumf32(x: f32, y: f32) -> f32; /// Returns the minimum of two `f64` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f64::min`] pub fn minnumf64(x: f64, y: f64) -> f64; /// Returns the maximum of two `f32` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f32::max`] pub fn maxnumf32(x: f32, y: f32) -> f32; /// Returns the maximum of two `f64` values. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is /// [`f64::max`] pub fn maxnumf64(x: f64, y: f64) -> f64; @@ -1438,6 +1514,11 @@ extern "rust-intrinsic" { /// Returns the number of bits set in an integer type `T` /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, /// [`u32::count_ones`] @@ -1446,6 +1527,11 @@ extern "rust-intrinsic" { /// Returns the number of leading unset bits (zeroes) in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `leading_zeros` method. For example, /// [`u32::leading_zeros`] @@ -1497,6 +1583,11 @@ extern "rust-intrinsic" { /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `trailing_zeros` method. For example, /// [`u32::trailing_zeros`] @@ -1548,6 +1639,11 @@ extern "rust-intrinsic" { /// Reverses the bytes in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `swap_bytes` method. For example, /// [`u32::swap_bytes`] @@ -1556,6 +1652,11 @@ extern "rust-intrinsic" { /// Reverses the bits in an integer type `T`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `reverse_bits` method. For example, /// [`u32::reverse_bits`] @@ -1564,6 +1665,11 @@ extern "rust-intrinsic" { /// Performs checked integer addition. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, /// [`u32::overflowing_add`] @@ -1572,6 +1678,11 @@ extern "rust-intrinsic" { /// Performs checked integer subtraction /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, /// [`u32::overflowing_sub`] @@ -1580,6 +1691,11 @@ extern "rust-intrinsic" { /// Performs checked integer multiplication /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, /// [`u32::overflowing_mul`] @@ -1649,6 +1765,11 @@ extern "rust-intrinsic" { /// Performs rotate left. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`u32::rotate_left`] @@ -1657,6 +1778,11 @@ extern "rust-intrinsic" { /// Performs rotate right. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`u32::rotate_right`] @@ -1665,6 +1791,11 @@ extern "rust-intrinsic" { /// Returns (a + b) mod 2N, where N is the width of T in bits. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`u32::wrapping_add`] @@ -1672,6 +1803,11 @@ extern "rust-intrinsic" { pub fn wrapping_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`u32::wrapping_sub`] @@ -1679,6 +1815,11 @@ extern "rust-intrinsic" { pub fn wrapping_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`u32::wrapping_mul`] @@ -1687,6 +1828,11 @@ extern "rust-intrinsic" { /// Computes `a + b`, saturating at numeric bounds. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, /// [`u32::saturating_add`] @@ -1694,6 +1840,11 @@ extern "rust-intrinsic" { pub fn saturating_add(a: T, b: T) -> T; /// Computes `a - b`, saturating at numeric bounds. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_sub` method. For example, /// [`u32::saturating_sub`] @@ -1703,6 +1854,11 @@ extern "rust-intrinsic" { /// Returns the value of the discriminant for the variant in 'v'; /// if `T` has no discriminant, returns `0`. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] pub fn discriminant_value(v: &T) -> ::Discriminant; @@ -1710,6 +1866,11 @@ extern "rust-intrinsic" { /// Returns the number of variants of the type `T` cast to a `usize`; /// if `T` has no variants, returns `0`. Uninhabited variants will be counted. /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. + /// /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`]. #[rustc_const_unstable(feature = "variant_count", issue = "73662")] pub fn variant_count() -> usize; @@ -1732,16 +1893,46 @@ extern "rust-intrinsic" { pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; /// See documentation of `<*const T>::guaranteed_eq` for details. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] pub fn ptr_guaranteed_eq(ptr: *const T, other: *const T) -> bool; /// See documentation of `<*const T>::guaranteed_ne` for details. + /// + /// Note that, unlike most intrinsics, this is safe to call; + /// it does not require an `unsafe` block. + /// Therefore, implementations must not require the user to uphold + /// any safety invariants. #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] pub fn ptr_guaranteed_ne(ptr: *const T, other: *const T) -> bool; /// Allocate at compile time. Should not be called at runtime. #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub fn const_allocate(size: usize, align: usize) -> *mut u8; + + /// Determines whether the raw bytes of the two values are equal. + /// + /// The is particularly handy for arrays, since it allows things like just + /// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`. + /// + /// Above some backend-decided threshold this will emit calls to `memcmp`, + /// like slice equality does, instead of causing massive code size. + /// + /// # Safety + /// + /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized. + /// Note that this is a stricter criterion than just the *values* being + /// fully-initialized: if `T` has padding, it's UB to call this intrinsic. + /// + /// (The implementation is allowed to branch on the results of comparisons, + /// which is UB if any of their inputs are `undef`.) + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")] + pub fn raw_eq(a: &T, b: &T) -> bool; } // Some functions are defined here because they accidentally got made diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index 7efc155175..5cd65a9415 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -58,6 +58,7 @@ where self.it.map(T::clone).fold(init, f) } + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T where Self: TrustedRandomAccess, diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index def2408927..07a3b5d245 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -74,6 +74,7 @@ where self.it.count() } + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T where Self: TrustedRandomAccess, diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 91722a4b62..8b27bdc60a 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -111,6 +111,7 @@ where } #[rustc_inherit_overflow_checks] + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> ::Item where Self: TrustedRandomAccess, diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 3315d34659..48880a4d91 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,5 +1,5 @@ use crate::fmt; -use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map}; +use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen}; use crate::ops::Try; /// An iterator that maps each element to an iterator, and yields the elements @@ -114,6 +114,30 @@ where { } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for FlatMap +where + I: TrustedLen, + F: FnMut(I::Item) -> [T; N], +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap +where + I: TrustedLen, + F: FnMut(I::Item) -> &'a [T; N], +{ +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap +where + I: TrustedLen, + F: FnMut(I::Item) -> &'a mut [T; N], +{ +} + /// An iterator that flattens one level of nesting in an iterator of things /// that can be turned into iterators. /// @@ -230,6 +254,14 @@ where { } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Flatten +where + I: TrustedLen, + ::Item: TrustedConstSize, +{ +} + /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. #[derive(Clone, Debug)] @@ -282,6 +314,17 @@ where let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint); let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint); let lo = flo.saturating_add(blo); + + if let Some(fixed_size) = <::Item as ConstSizeIntoIterator>::size() { + let (lower, upper) = self.iter.size_hint(); + + let lower = lower.saturating_mul(fixed_size).saturating_add(lo); + let upper = + try { fhi?.checked_add(bhi?)?.checked_add(fixed_size.checked_mul(upper?)?)? }; + + return (lower, upper); + } + match (self.iter.size_hint(), fhi, bhi) { ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), _ => (lo, None), @@ -444,3 +487,52 @@ where init } } + +trait ConstSizeIntoIterator: IntoIterator { + // FIXME(#31844): convert to an associated const once specialization supports that + fn size() -> Option; +} + +impl ConstSizeIntoIterator for T +where + T: IntoIterator, +{ + #[inline] + default fn size() -> Option { + None + } +} + +impl ConstSizeIntoIterator for [T; N] { + #[inline] + fn size() -> Option { + Some(N) + } +} + +impl ConstSizeIntoIterator for &[T; N] { + #[inline] + fn size() -> Option { + Some(N) + } +} + +impl ConstSizeIntoIterator for &mut [T; N] { + #[inline] + fn size() -> Option { + Some(N) + } +} + +#[doc(hidden)] +#[unstable(feature = "std_internals", issue = "none")] +// FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<> +// blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping +pub unsafe trait TrustedConstSize: IntoIterator {} + +#[unstable(feature = "std_internals", issue = "none")] +unsafe impl TrustedConstSize for [T; N] {} +#[unstable(feature = "std_internals", issue = "none")] +unsafe impl TrustedConstSize for &'_ [T; N] {} +#[unstable(feature = "std_internals", issue = "none")] +unsafe impl TrustedConstSize for &'_ mut [T; N] {} diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index aff48b1b22..408328adee 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -1,5 +1,5 @@ use crate::intrinsics; -use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter}; +use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::{ DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess, }; @@ -14,7 +14,9 @@ use crate::ops::Try; #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Fuse { - // NOTE: for `I: FusedIterator`, this is always assumed `Some`! + // NOTE: for `I: FusedIterator`, we never bother setting `None`, but + // we still have to be prepared for that state due to variance. + // See rust-lang/rust#85863 iter: Option, } impl Fuse { @@ -42,19 +44,19 @@ macro_rules! fuse { }; } -// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`. -// Implementing this as a directly-expanded macro helps codegen performance. -macro_rules! unchecked { - ($self:ident) => { - match $self { - Fuse { iter: Some(iter) } => iter, - // SAFETY: the specialized iterator never sets `None` - Fuse { iter: None } => unsafe { intrinsics::unreachable() }, +/// Specialized macro that doesn't check if the expression is `None`. +/// (We trust that a `FusedIterator` will fuse itself.) +macro_rules! spec { + ($self:ident . iter . $($call:tt)+) => { + match $self.iter { + Some(ref mut iter) => iter.$($call)+, + None => None, } }; } -// Any implementation here is made internal to avoid exposing default fns outside this trait +// Any specialized implementation here is made internal +// to avoid exposing default fns outside this trait. #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Fuse where @@ -74,17 +76,26 @@ where #[inline] fn last(self) -> Option { - FuseImpl::last(self) + match self.iter { + Some(iter) => iter.last(), + None => None, + } } #[inline] fn count(self) -> usize { - FuseImpl::count(self) + match self.iter { + Some(iter) => iter.count(), + None => 0, + } } #[inline] fn size_hint(&self) -> (usize, Option) { - FuseImpl::size_hint(self) + match self.iter { + Some(ref iter) => iter.size_hint(), + None => (0, Some(0)), + } } #[inline] @@ -98,11 +109,14 @@ where } #[inline] - fn fold(self, acc: Acc, fold: Fold) -> Acc + fn fold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseImpl::fold(self, acc, fold) + if let Some(iter) = self.iter { + acc = iter.fold(acc, fold); + } + acc } #[inline] @@ -114,6 +128,7 @@ where } #[inline] + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item where Self: TrustedRandomAccess, @@ -154,11 +169,14 @@ where } #[inline] - fn rfold(self, acc: Acc, fold: Fold) -> Acc + fn rfold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseImpl::rfold(self, acc, fold) + if let Some(iter) = self.iter { + acc = iter.rfold(acc, fold); + } + acc } #[inline] @@ -176,11 +194,17 @@ where I: ExactSizeIterator, { fn len(&self) -> usize { - FuseImpl::len(self) + match self.iter { + Some(ref iter) => iter.len(), + None => 0, + } } fn is_empty(&self) -> bool { - FuseImpl::is_empty(self) + match self.iter { + Some(ref iter) => iter.is_empty(), + None => true, + } } } @@ -204,7 +228,10 @@ where const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; } -// Fuse specialization trait +/// Fuse specialization trait +/// +/// We only need to worry about `&mut self` methods, which +/// may exhaust the iterator without consuming it. #[doc(hidden)] trait FuseImpl { type Item; @@ -212,17 +239,11 @@ trait FuseImpl { // Functions specific to any normal Iterators fn next(&mut self) -> Option; fn nth(&mut self, n: usize) -> Option; - fn last(self) -> Option; - fn count(self) -> usize; - fn size_hint(&self) -> (usize, Option); fn try_fold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try; - fn fold(self, acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc; fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool; @@ -240,25 +261,13 @@ trait FuseImpl { Fold: FnMut(Acc, Self::Item) -> R, R: Try, I: DoubleEndedIterator; - fn rfold(self, acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - I: DoubleEndedIterator; fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator; - - // Functions specific to ExactSizeIterator - fn len(&self) -> usize - where - I: ExactSizeIterator; - fn is_empty(&self) -> bool - where - I: ExactSizeIterator; } -// General Fuse impl +/// General `Fuse` impl which sets `iter = None` when exhausted. #[doc(hidden)] impl FuseImpl for Fuse where @@ -276,30 +285,6 @@ where fuse!(self.iter.nth(n)) } - #[inline] - default fn last(self) -> Option { - match self.iter { - Some(iter) => iter.last(), - None => None, - } - } - - #[inline] - default fn count(self) -> usize { - match self.iter { - Some(iter) => iter.count(), - None => 0, - } - } - - #[inline] - default fn size_hint(&self) -> (usize, Option) { - match self.iter { - Some(ref iter) => iter.size_hint(), - None => (0, Some(0)), - } - } - #[inline] default fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R where @@ -314,17 +299,6 @@ where try { acc } } - #[inline] - default fn fold(self, mut acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - if let Some(iter) = self.iter { - acc = iter.fold(acc, fold); - } - acc - } - #[inline] default fn find

(&mut self, predicate: P) -> Option where @@ -364,18 +338,6 @@ where try { acc } } - #[inline] - default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - I: DoubleEndedIterator, - { - if let Some(iter) = self.iter { - acc = iter.rfold(acc, fold); - } - acc - } - #[inline] default fn rfind

Potential deadlock example +/// +/// ```text +/// // Thread 1 | // Thread 2 +/// let _rg = lock.read(); | +/// | // will block +/// | let _wg = lock.write(); +/// // may deadlock | +/// let _rg = lock.read(); | +/// ``` +///
/// /// The type parameter `T` represents the data that this lock protects. It is /// required that `T` satisfies [`Send`] to be shared across threads and diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs index 4eb0d8437b..1c7e1dd8d5 100644 --- a/library/std/src/sys/hermit/args.rs +++ b/library/std/src/sys/hermit/args.rs @@ -55,8 +55,8 @@ impl DoubleEndedIterator for Args { mod imp { use super::Args; use crate::ffi::{CStr, OsString}; + use crate::os::unix::ffi::OsStringExt; use crate::ptr; - use crate::sys_common::os_str_bytes::*; use crate::sys_common::mutex::StaticMutex; diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index 76ea70d997..be019d4435 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -3,6 +3,7 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::io::{self, Error, ErrorKind}; use crate::io::{IoSlice, IoSliceMut, SeekFrom}; +use crate::os::unix::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sys::cvt; use crate::sys::hermit::abi; @@ -10,7 +11,6 @@ use crate::sys::hermit::abi::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRU use crate::sys::hermit::fd::FileDesc; use crate::sys::time::SystemTime; use crate::sys::unsupported; -use crate::sys_common::os_str_bytes::OsStrExt; pub use crate::sys_common::fs::{copy, try_exists}; //pub use crate::sys_common::fs::remove_dir_all; diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index 15a76bbd2c..10c1942495 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -149,7 +149,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { x if x == 1 as i32 => ErrorKind::PermissionDenied, x if x == 32 as i32 => ErrorKind::BrokenPipe, x if x == 110 as i32 => ErrorKind::TimedOut, - _ => ErrorKind::Other, + _ => ErrorKind::Uncategorized, } } diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs index 885389ca54..4221799114 100644 --- a/library/std/src/sys/hermit/mutex.rs +++ b/library/std/src/sys/hermit/mutex.rs @@ -14,7 +14,7 @@ use crate::sys::hermit::abi; /// This structure behaves a lot like a common mutex. There are some differences: /// /// - By using busy waiting, it can be used outside the runtime. -/// - It is a so called ticket lock and is completly fair. +/// - It is a so called ticket lock and is completely fair. #[cfg_attr(target_arch = "x86_64", repr(align(128)))] #[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))] struct Spinlock { diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index 5f8839157e..3f0c99cf74 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -15,7 +15,7 @@ use crate::time::Duration; pub fn init() -> io::Result<()> { if abi::network_init() < 0 { return Err(io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"Unable to initialize network interface", )); } @@ -51,7 +51,7 @@ impl TcpStream { match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), _ => Err(io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"Unable to initiate a connection on a socket", )), } @@ -65,7 +65,7 @@ impl TcpStream { ) { Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), _ => Err(io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"Unable to initiate a connection on a socket", )), } @@ -73,7 +73,9 @@ impl TcpStream { pub fn set_read_timeout(&self, duration: Option) -> io::Result<()> { abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64)) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) + .map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value") + }) } pub fn set_write_timeout(&self, duration: Option) -> io::Result<()> { @@ -81,12 +83,12 @@ impl TcpStream { *self.0.as_inner(), duration.map(|d| d.as_millis() as u64), ) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"Unable to set timeout value")) } pub fn read_timeout(&self) -> io::Result> { let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| { - io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value") })?; Ok(duration.map(|d| Duration::from_millis(d))) @@ -94,7 +96,7 @@ impl TcpStream { pub fn write_timeout(&self) -> io::Result> { let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| { - io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to determine timeout value") })?; Ok(duration.map(|d| Duration::from_millis(d))) @@ -102,7 +104,7 @@ impl TcpStream { pub fn peek(&self, buf: &mut [u8]) -> io::Result { abi::tcpstream::peek(*self.0.as_inner(), buf) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peek failed")) } pub fn read(&self, buffer: &mut [u8]) -> io::Result { @@ -113,8 +115,9 @@ impl TcpStream { let mut size: usize = 0; for i in ioslice.iter_mut() { - let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?; + let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to read on socket") + })?; if ret != 0 { size += ret; @@ -138,7 +141,7 @@ impl TcpStream { for i in ioslice.iter() { size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| { - io::Error::new_const(ErrorKind::Other, &"Unable to write on socket") + io::Error::new_const(ErrorKind::Uncategorized, &"Unable to write on socket") })?; } @@ -152,13 +155,13 @@ impl TcpStream { pub fn peer_addr(&self) -> io::Result { let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"peer_addr failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed"))?; let saddr = match ipaddr { Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { - return Err(io::Error::new_const(ErrorKind::Other, &"peer_addr failed")); + return Err(io::Error::new_const(ErrorKind::Uncategorized, &"peer_addr failed")); } }; @@ -170,8 +173,9 @@ impl TcpStream { } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - abi::tcpstream::shutdown(*self.0.as_inner(), how as i32) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket")) + abi::tcpstream::shutdown(*self.0.as_inner(), how as i32).map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"unable to shutdown socket") + }) } pub fn duplicate(&self) -> io::Result { @@ -180,22 +184,22 @@ impl TcpStream { pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { abi::tcpstream::set_nodelay(*self.0.as_inner(), mode) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed")) } pub fn nodelay(&self) -> io::Result { abi::tcpstream::nodelay(*self.0.as_inner()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"nodelay failed")) } pub fn set_ttl(&self, tll: u32) -> io::Result<()> { abi::tcpstream::set_tll(*self.0.as_inner(), tll) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to set TTL")) } pub fn ttl(&self) -> io::Result { abi::tcpstream::get_tll(*self.0.as_inner()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to get TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"unable to get TTL")) } pub fn take_error(&self) -> io::Result> { @@ -203,8 +207,9 @@ impl TcpStream { } pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { - abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode")) + abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| { + io::Error::new_const(ErrorKind::Uncategorized, &"unable to set blocking mode") + }) } } @@ -230,12 +235,12 @@ impl TcpListener { pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port()) - .map_err(|_| io::Error::new_const(ErrorKind::Other, &"accept failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"accept failed"))?; let saddr = match ipaddr { Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { - return Err(io::Error::new_const(ErrorKind::Other, &"accept failed")); + return Err(io::Error::new_const(ErrorKind::Uncategorized, &"accept failed")); } }; diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs index 40bd393098..eeb30a578c 100644 --- a/library/std/src/sys/hermit/os.rs +++ b/library/std/src/sys/hermit/os.rs @@ -4,13 +4,13 @@ use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io; use crate::marker::PhantomData; +use crate::os::unix::ffi::OsStringExt; use crate::path::{self, PathBuf}; use crate::str; use crate::sync::Mutex; use crate::sys::hermit::abi; use crate::sys::memchr; use crate::sys::unsupported; -use crate::sys_common::os_str_bytes::*; use crate::vec; pub fn errno() -> i32 { diff --git a/library/std/src/sys/hermit/stdio.rs b/library/std/src/sys/hermit/stdio.rs index 6bff13ca92..33b8390431 100644 --- a/library/std/src/sys/hermit/stdio.rs +++ b/library/std/src/sys/hermit/stdio.rs @@ -40,7 +40,7 @@ impl io::Write for Stdout { unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print")) } else { Ok(len as usize) } @@ -52,7 +52,7 @@ impl io::Write for Stdout { unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stdout is not able to print")) } else { Ok(len as usize) } @@ -81,7 +81,7 @@ impl io::Write for Stderr { unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print")) } else { Ok(len as usize) } @@ -93,7 +93,7 @@ impl io::Write for Stderr { unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Stderr is not able to print")) } else { Ok(len as usize) } diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index f35a3a8a80..8be25f8499 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -1,8 +1,10 @@ #![allow(dead_code)] +use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::sys::hermit::abi; use crate::sys::hermit::thread_local_dtor::run_dtors; use crate::time::Duration; @@ -37,7 +39,7 @@ impl Thread { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. drop(Box::from_raw(p)); - Err(io::Error::new_const(io::ErrorKind::Other, &"Unable to create thread!")) + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"Unable to create thread!")) } else { Ok(Thread { tid: tid }) }; @@ -95,6 +97,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/sgx/abi/mem.rs b/library/std/src/sys/sgx/abi/mem.rs index 1e743894a9..52e8bec937 100644 --- a/library/std/src/sys/sgx/abi/mem.rs +++ b/library/std/src/sys/sgx/abi/mem.rs @@ -36,9 +36,9 @@ pub fn image_base() -> u64 { let base: u64; unsafe { asm!( - "lea {}, qword ptr [rip + IMAGE_BASE]", + "lea IMAGE_BASE(%rip), {}", lateout(reg) base, - options(nostack, preserves_flags, nomem, pure), + options(att_syntax, nostack, preserves_flags, nomem, pure), ) }; base diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index cdfceca19f..fce6b42073 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -70,7 +70,7 @@ pub fn sgx_ineffective(v: T) -> crate::io::Result { static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false); if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) { Err(crate::io::Error::new_const( - ErrorKind::Other, + ErrorKind::Uncategorized, &"operation can't be trusted to have any effect on SGX", )) } else { @@ -115,11 +115,11 @@ pub fn decode_error_kind(code: i32) -> ErrorKind { } else if code == Error::Interrupted as _ { ErrorKind::Interrupted } else if code == Error::Other as _ { - ErrorKind::Other + ErrorKind::Uncategorized } else if code == Error::UnexpectedEof as _ { ErrorKind::UnexpectedEof } else { - ErrorKind::Other + ErrorKind::Uncategorized } } diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs index 5ccedece0f..3a69aa039e 100644 --- a/library/std/src/sys/sgx/net.rs +++ b/library/std/src/sys/sgx/net.rs @@ -466,7 +466,7 @@ pub struct LookupHost(!); impl LookupHost { fn new(host: String) -> io::Result { - Err(io::Error::new(io::ErrorKind::Other, NonIpSockAddr { host })) + Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host })) } pub fn port(&self) -> u16 { diff --git a/library/std/src/sys/sgx/stdio.rs b/library/std/src/sys/sgx/stdio.rs index 548e28a43d..8ccf043b5b 100644 --- a/library/std/src/sys/sgx/stdio.rs +++ b/library/std/src/sys/sgx/stdio.rs @@ -65,7 +65,7 @@ impl io::Write for Stderr { pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { - // FIXME: Rust normally maps Unix EBADF to `Other` + // FIXME: Rust normally maps Unix EBADF to `Uncategorized` err.raw_os_error() == Some(abi::Error::BrokenPipe as _) } diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index 67e2e8b59d..cbb8ba9640 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -1,6 +1,8 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? +use super::unsupported; use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::time::Duration; use super::abi::usercalls; @@ -135,6 +137,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/unix/android.rs b/library/std/src/sys/unix/android.rs index cf6aa31b7c..6a46525f68 100644 --- a/library/std/src/sys/unix/android.rs +++ b/library/std/src/sys/unix/android.rs @@ -21,7 +21,7 @@ use libc::{c_int, c_void, sighandler_t, size_t, ssize_t}; use libc::{ftruncate, pread, pwrite}; -use super::{cvt, cvt_r}; +use super::{cvt, cvt_r, weak::weak}; use crate::io; // The `log2` and `log2f` functions apparently appeared in android-18, or at diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index fc423e393d..0bd1ea6457 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -14,11 +14,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) } -/// One-time global cleanup. -pub unsafe fn cleanup() { - imp::cleanup() -} - /// Returns the command line arguments pub fn args() -> Args { imp::args() @@ -82,16 +77,18 @@ mod imp { use crate::ptr; use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering}; - use crate::sys_common::mutex::StaticMutex; - + // The system-provided argc and argv, which we store in static memory + // here so that we can defer the work of parsing them until its actually + // needed. + // + // Note that we never mutate argv/argc, the argv array, or the argv + // strings, which allows the code in this file to be very simple. static ARGC: AtomicIsize = AtomicIsize::new(0); static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); - // We never call `ENV_LOCK.init()`, so it is UB to attempt to - // acquire this mutex reentrantly! - static LOCK: StaticMutex = StaticMutex::new(); unsafe fn really_init(argc: isize, argv: *const *const u8) { - let _guard = LOCK.lock(); + // These don't need to be ordered with each other or other stores, + // because they only hold the unmodified system-provide argv/argc. ARGC.store(argc, Ordering::Relaxed); ARGV.store(argv as *mut _, Ordering::Relaxed); } @@ -127,21 +124,22 @@ mod imp { init_wrapper }; - pub unsafe fn cleanup() { - let _guard = LOCK.lock(); - ARGC.store(0, Ordering::Relaxed); - ARGV.store(ptr::null_mut(), Ordering::Relaxed); - } - pub fn args() -> Args { Args { iter: clone().into_iter() } } fn clone() -> Vec { unsafe { - let _guard = LOCK.lock(); - let argc = ARGC.load(Ordering::Relaxed); + // Load ARGC and ARGV, which hold the unmodified system-provided + // argc/argv, so we can read the pointed-to memory without atomics + // or synchronization. + // + // If either ARGC or ARGV is still zero or null, then either there + // really are no arguments, or someone is asking for `args()` + // before initialization has completed, and we return an empty + // list. let argv = ARGV.load(Ordering::Relaxed); + let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) }; (0..argc) .map(|i| { let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char); @@ -159,8 +157,6 @@ mod imp { pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} - pub fn cleanup() {} - #[cfg(target_os = "macos")] pub fn args() -> Args { use crate::os::unix::prelude::*; diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index f8ca67c844..5c8c94971c 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -12,8 +12,23 @@ use crate::sys::time::SystemTime; use crate::sys::{cvt, cvt_r}; use crate::sys_common::{AsInner, FromInner}; +#[cfg(any( + all(target_os = "linux", target_env = "gnu"), + target_os = "macos", + target_os = "ios", +))] +use crate::sys::weak::syscall; +#[cfg(target_os = "macos")] +use crate::sys::weak::weak; + use libc::{c_int, mode_t}; +#[cfg(any( + target_os = "macos", + target_os = "ios", + all(target_os = "linux", target_env = "gnu") +))] +use libc::c_char; #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] use libc::dirfd; #[cfg(any(target_os = "linux", target_os = "emscripten"))] @@ -92,7 +107,7 @@ cfg_has_statx! {{ // Default `stat64` contains no creation time. unsafe fn try_statx( fd: c_int, - path: *const libc::c_char, + path: *const c_char, flags: i32, mask: u32, ) -> Option> { @@ -107,7 +122,7 @@ cfg_has_statx! {{ syscall! { fn statx( fd: c_int, - pathname: *const libc::c_char, + pathname: *const c_char, flags: c_int, mask: libc::c_uint, statxbuf: *mut libc::statx @@ -358,7 +373,7 @@ impl FileAttr { })) } else { Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"creation time is not available for the filesystem", )) }; @@ -647,6 +662,10 @@ impl DirEntry { fn name_bytes(&self) -> &[u8] { &*self.name } + + pub fn file_name_os_str(&self) -> &OsStr { + OsStr::from_bytes(self.name_bytes()) + } } impl OpenOptions { @@ -752,7 +771,7 @@ impl File { cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, - b"\0" as *const _ as *const libc::c_char, + b"\0" as *const _ as *const c_char, libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT, libc::STATX_ALL, ) } { @@ -1083,15 +1102,28 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { let link = cstr(link)?; cfg_if::cfg_if! { if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] { - // VxWorks, Redox, and old versions of Android 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. + // VxWorks and Redox 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` ecause 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 { - // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives - // us a flag to specify how symlinks should be handled. Pass 0 as - // the flags argument, meaning don't follow symlinks. + // 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) })?; } } @@ -1274,7 +1306,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { fn fclonefileat( srcfd: libc::c_int, dst_dirfd: libc::c_int, - dst: *const libc::c_char, + dst: *const c_char, flags: libc::c_int ) -> libc::c_int } diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 9687576bb6..a6b43229ba 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -61,6 +61,7 @@ use crate::process::{ChildStderr, ChildStdin, ChildStdout}; use crate::ptr; use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use crate::sys::cvt; +use crate::sys::weak::syscall; use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV}; #[cfg(test)] diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index ca9cc8ca7b..9e553ec768 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -123,7 +123,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { // SAFETY: must be called only once during runtime cleanup. // NOTE: this is not guaranteed to run, for example when the program aborts. pub unsafe fn cleanup() { - args::cleanup(); stack_overflow::cleanup(); } @@ -133,29 +132,51 @@ pub use crate::sys::android::signal; pub use libc::signal; pub fn decode_error_kind(errno: i32) -> ErrorKind { + use ErrorKind::*; match errno as libc::c_int { - libc::ECONNREFUSED => ErrorKind::ConnectionRefused, - libc::ECONNRESET => ErrorKind::ConnectionReset, - libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied, - libc::EPIPE => ErrorKind::BrokenPipe, - libc::ENOTCONN => ErrorKind::NotConnected, - libc::ECONNABORTED => ErrorKind::ConnectionAborted, - libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - libc::EADDRINUSE => ErrorKind::AddrInUse, - libc::ENOENT => ErrorKind::NotFound, - libc::EINTR => ErrorKind::Interrupted, - libc::EINVAL => ErrorKind::InvalidInput, - libc::ETIMEDOUT => ErrorKind::TimedOut, - libc::EEXIST => ErrorKind::AlreadyExists, - libc::ENOSYS => ErrorKind::Unsupported, - libc::ENOMEM => ErrorKind::OutOfMemory, + libc::E2BIG => ArgumentListTooLong, + libc::EADDRINUSE => AddrInUse, + libc::EADDRNOTAVAIL => AddrNotAvailable, + libc::EBUSY => ResourceBusy, + libc::ECONNABORTED => ConnectionAborted, + libc::ECONNREFUSED => ConnectionRefused, + libc::ECONNRESET => ConnectionReset, + libc::EDEADLK => Deadlock, + libc::EDQUOT => FilesystemQuotaExceeded, + libc::EEXIST => AlreadyExists, + libc::EFBIG => FileTooLarge, + libc::EHOSTUNREACH => HostUnreachable, + libc::EINTR => Interrupted, + libc::EINVAL => InvalidInput, + libc::EISDIR => IsADirectory, + libc::ELOOP => FilesystemLoop, + libc::ENOENT => NotFound, + libc::ENOMEM => OutOfMemory, + libc::ENOSPC => StorageFull, + libc::ENOSYS => Unsupported, + libc::EMLINK => TooManyLinks, + libc::ENAMETOOLONG => FilenameTooLong, + libc::ENETDOWN => NetworkDown, + libc::ENETUNREACH => NetworkUnreachable, + libc::ENOTCONN => NotConnected, + libc::ENOTDIR => NotADirectory, + libc::ENOTEMPTY => DirectoryNotEmpty, + libc::EPIPE => BrokenPipe, + libc::EROFS => ReadOnlyFilesystem, + libc::ESPIPE => NotSeekable, + libc::ESTALE => StaleNetworkFileHandle, + libc::ETIMEDOUT => TimedOut, + libc::ETXTBSY => ExecutableFileBusy, + libc::EXDEV => CrossesDevices, + + libc::EACCES | libc::EPERM => PermissionDenied, // These two constants can have the same value on some systems, // but different values on others, so we can't use a match // clause - x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock, + x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock, - _ => ErrorKind::Other, + _ => Uncategorized, } } @@ -195,13 +216,41 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> { if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) } } -// On Unix-like platforms, libc::abort will unregister signal handlers -// including the SIGABRT handler, preventing the abort from being blocked, and -// fclose streams, with the side effect of flushing them so libc buffered -// output will be printed. Additionally the shell will generally print a more -// understandable error message like "Abort trap" rather than "Illegal -// instruction" that intrinsics::abort would cause, as intrinsics::abort is -// implemented as an illegal instruction. +// libc::abort() will run the SIGABRT handler. That's fine because anyone who +// installs a SIGABRT handler already has to expect it to run in Very Bad +// situations (eg, malloc crashing). +// +// Current glibc's abort() function unblocks SIGABRT, raises SIGABRT, clears the +// SIGABRT handler and raises it again, and then starts to get creative. +// +// See the public documentation for `intrinsics::abort()` and `process::abort()` +// for further discussion. +// +// There is confusion about whether libc::abort() flushes stdio streams. +// libc::abort() is required by ISO C 99 (7.14.1.1p5) to be async-signal-safe, +// so flushing streams is at least extremely hard, if not entirely impossible. +// +// However, some versions of POSIX (eg IEEE Std 1003.1-2001) required abort to +// do so. In 1003.1-2004 this was fixed. +// +// glibc's implementation did the flush, unsafely, before glibc commit +// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]' by Florian +// Weimer. According to glibc's NEWS: +// +// The abort function terminates the process immediately, without flushing +// stdio streams. Previous glibc versions used to flush streams, resulting +// in deadlocks and further data corruption. This change also affects +// process aborts as the result of assertion failures. +// +// This is an accurate description of the problem. The only solution for +// program with nontrivial use of C stdio is a fixed libc - one which does not +// try to flush in abort - since even libc-internal errors, and assertion +// failures generated from C, will go via abort(). +// +// On systems with old, buggy, libcs, the impact can be severe for a +// multithreaded C program. It is much less severe for Rust, because Rust +// stdlib doesn't use libc stdio buffering. In a typical Rust program, which +// does not use C stdio, even a buggy libc::abort() is, in fact, safe. pub fn abort_internal() -> ! { unsafe { libc::abort() } } @@ -240,7 +289,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "macos")] { #[link(name = "System")] // res_init and friends require -lresolv on macOS/iOS. - // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html + // See #41582 and https://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html #[link(name = "resolv")] extern "C" {} } else if #[cfg(target_os = "ios")] { diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index d5a15964c0..753cad55ce 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -38,7 +38,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned() }; Err(io::Error::new( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &format!("failed to lookup address information: {}", detail)[..], )) } @@ -178,7 +178,7 @@ impl Socket { if pollfd.revents & libc::POLLHUP != 0 { let e = self.take_error()?.unwrap_or_else(|| { io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"no error set after POLLHUP", ) }); diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 41ca976239..d3c874edf2 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -23,6 +23,9 @@ use crate::sys::memchr; use crate::sys_common::rwlock::{StaticRWLock, StaticRWLockReadGuard}; use crate::vec; +#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] +use crate::sys::weak::weak; + use libc::{c_char, c_int, c_void}; const TMPBUF_SZ: usize = 128; @@ -279,7 +282,7 @@ pub fn current_exe() -> io::Result { ))?; if path_len <= 1 { return Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"KERN_PROC_PATHNAME sysctl returned zero-length string", )); } @@ -302,7 +305,7 @@ pub fn current_exe() -> io::Result { return crate::fs::read_link(curproc_exe); } Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"/proc/curproc/exe doesn't point to regular file.", )) } @@ -320,7 +323,10 @@ pub fn current_exe() -> io::Result { cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?; argv.set_len(argv_len as usize); if argv[0].is_null() { - return Err(io::Error::new_const(io::ErrorKind::Other, &"no current exe available")); + return Err(io::Error::new_const( + io::ErrorKind::Uncategorized, + &"no current exe available", + )); } let argv0 = CStr::from_ptr(argv[0]).to_bytes(); if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') { @@ -335,7 +341,7 @@ pub fn current_exe() -> io::Result { pub fn current_exe() -> io::Result { match crate::fs::read_link("/proc/self/exe") { Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"no /proc/self/exe available. Is /proc mounted?", )), other => other, @@ -422,7 +428,7 @@ pub fn current_exe() -> io::Result { _get_next_image_info(0, &mut cookie, &mut info, mem::size_of::() as i32); if result != 0 { use crate::io::ErrorKind; - Err(io::Error::new_const(ErrorKind::Other, &"Error getting executable path")) + Err(io::Error::new_const(ErrorKind::Uncategorized, &"Error getting executable path")) } else { let name = CStr::from_ptr(info.name.as_ptr()).to_bytes(); Ok(PathBuf::from(OsStr::from_bytes(name))) diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index ed55e1aa71..c888dd0d87 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -9,6 +9,14 @@ use crate::sys; use crate::sys::cvt; use crate::sys::process::process_common::*; +#[cfg(any( + target_os = "macos", + target_os = "freebsd", + all(target_os = "linux", target_env = "gnu"), + all(target_os = "linux", target_env = "musl"), +))] +use crate::sys::weak::weak; + #[cfg(target_os = "vxworks")] use libc::RTP_ID as pid_t; diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index 44f9eabc31..32895001a6 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -25,6 +25,9 @@ mod imp { use crate::fs::File; use crate::io::Read; + #[cfg(any(target_os = "linux", target_os = "android"))] + use crate::sys::weak::syscall; + #[cfg(any(target_os = "linux", target_os = "android"))] fn getrandom(buf: &mut [u8]) -> libc::ssize_t { // A weak symbol allows interposition, e.g. for perf measurements that want to @@ -108,6 +111,7 @@ mod imp { use crate::fs::File; use crate::io::Read; use crate::sys::os::errno; + use crate::sys::weak::weak; use libc::{c_int, c_void, size_t}; fn getentropy_fill_bytes(v: &mut [u8]) -> bool { diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index b8f43caec3..879d716052 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -2,10 +2,13 @@ use crate::cmp; use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::ptr; use crate::sys::{os, stack_overflow}; use crate::time::Duration; +#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))] +use crate::sys::weak::weak; #[cfg(not(any(target_os = "l4re", target_os = "vxworks")))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; #[cfg(target_os = "l4re")] @@ -198,6 +201,88 @@ impl Drop for Thread { } } +pub fn available_concurrency() -> io::Result { + cfg_if::cfg_if! { + if #[cfg(any( + target_os = "android", + target_os = "emscripten", + target_os = "fuchsia", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "solaris", + target_os = "illumos", + ))] { + match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { + -1 => Err(io::Error::last_os_error()), + 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), + cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }), + } + } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { + use crate::ptr; + + let mut cpus: libc::c_uint = 0; + let mut cpus_size = crate::mem::size_of_val(&cpus); + + unsafe { + cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint; + } + + // Fallback approach in case of errors or no hardware threads. + if cpus < 1 { + let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + let res = unsafe { + libc::sysctl( + mib.as_mut_ptr(), + 2, + &mut cpus as *mut _ as *mut _, + &mut cpus_size as *mut _ as *mut _, + ptr::null_mut(), + 0, + ) + }; + + // Handle errors if any. + if res == -1 { + return Err(io::Error::last_os_error()); + } else if cpus == 0 { + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); + } + } + Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else if #[cfg(target_os = "openbsd")] { + use crate::ptr; + + let mut cpus: libc::c_uint = 0; + let mut cpus_size = crate::mem::size_of_val(&cpus); + let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; + + let res = unsafe { + libc::sysctl( + mib.as_mut_ptr(), + 2, + &mut cpus as *mut _ as *mut _, + &mut cpus_size as *mut _ as *mut _, + ptr::null_mut(), + 0, + ) + }; + + // Handle errors if any. + if res == -1 { + return Err(io::Error::last_os_error()); + } else if cpus == 0 { + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); + } + + Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else { + // FIXME: implement on vxWorks, Redox, Haiku, l4re + Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform")) + } + } +} + #[cfg(all( not(target_os = "linux"), not(target_os = "freebsd"), diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index 432fe4c33b..cad8be6d28 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -26,8 +26,11 @@ use crate::marker; use crate::mem; use crate::sync::atomic::{self, AtomicUsize, Ordering}; -macro_rules! weak { +// Temporary null documentation to work around #57569 until the fix is beta +#[cfg_attr(bootstrap, doc = "")] +pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + #[allow(non_upper_case_globals)] static $name: crate::sys::weak::Weak $ret> = crate::sys::weak::Weak::new(concat!(stringify!($name), '\0')); ) @@ -100,8 +103,10 @@ unsafe fn fetch(name: &str) -> usize { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize } +// Temporary null documentation to work around #57569 until the fix is beta +#[cfg_attr(bootstrap, doc = "")] #[cfg(not(any(target_os = "linux", target_os = "android")))] -macro_rules! syscall { +pub(crate) macro syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name: $t),*) -> $ret { use super::os; @@ -118,10 +123,12 @@ macro_rules! syscall { ) } +#[cfg_attr(bootstrap, doc = "")] #[cfg(any(target_os = "linux", target_os = "android"))] -macro_rules! syscall { +pub(crate) macro syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { + use weak; // This looks like a hack, but concat_idents only accepts idents // (not paths). use libc::*; diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs index 6e72a7c632..4e6c301d29 100644 --- a/library/std/src/sys/unsupported/common.rs +++ b/library/std/src/sys/unsupported/common.rs @@ -30,7 +30,7 @@ pub fn unsupported_err() -> std_io::Error { } pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { - crate::io::ErrorKind::Other + crate::io::ErrorKind::Uncategorized } pub fn abort_internal() -> ! { diff --git a/library/std/src/sys/unsupported/thread.rs b/library/std/src/sys/unsupported/thread.rs index cda8510e1b..dc75d4ee67 100644 --- a/library/std/src/sys/unsupported/thread.rs +++ b/library/std/src/sys/unsupported/thread.rs @@ -1,6 +1,7 @@ use super::unsupported; use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::time::Duration; pub struct Thread(!); @@ -30,6 +31,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 45e38f68b8..8ffa1c88d8 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -648,7 +648,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { through which {:?} could be opened", p ); - return Err(io::Error::new(io::ErrorKind::Other, msg)); + return Err(io::Error::new(io::ErrorKind::Uncategorized, msg)); } let relative = CStr::from_ptr(relative_path).to_bytes().to_vec(); @@ -670,7 +670,8 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { } pub fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) + f.to_str() + .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8")) } pub fn copy(from: &Path, to: &Path) -> io::Result { diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 45a829c0cd..4af99bfa46 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -58,7 +58,7 @@ pub use common::*; pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { use std_io::ErrorKind::*; if errno > u16::MAX as i32 || errno < 0 { - return Other; + return Uncategorized; } match errno as u16 { wasi::ERRNO_CONNREFUSED => ConnectionRefused, @@ -77,7 +77,7 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { wasi::ERRNO_AGAIN => WouldBlock, wasi::ERRNO_NOSYS => Unsupported, wasi::ERRNO_NOMEM => OutOfMemory, - _ => Other, + _ => Uncategorized, } } diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index 74515553a8..9ec02bbec2 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -3,6 +3,7 @@ use crate::ffi::CStr; use crate::io; use crate::mem; +use crate::num::NonZeroUsize; use crate::sys::unsupported; use crate::time::Duration; @@ -63,6 +64,10 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/wasm/atomics/thread.rs b/library/std/src/sys/wasm/atomics/thread.rs index 54bc877aa7..a66ab08375 100644 --- a/library/std/src/sys/wasm/atomics/thread.rs +++ b/library/std/src/sys/wasm/atomics/thread.rs @@ -1,5 +1,6 @@ use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::sys::unsupported; use crate::time::Duration; @@ -39,6 +40,10 @@ impl Thread { pub fn join(self) {} } +pub fn available_concurrency() -> io::Result { + unsupported() +} + pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index b7efc88447..63f9be7b7e 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -10,9 +10,14 @@ use crate::ptr; use libc::{c_void, size_t, wchar_t}; +#[path = "c/errors.rs"] // c.rs is included from two places so we need to specify this +mod errors; +pub use errors::*; + pub use self::EXCEPTION_DISPOSITION::*; pub use self::FILE_INFO_BY_HANDLE_CLASS::*; +pub type DWORD_PTR = ULONG_PTR; pub type DWORD = c_ulong; pub type NonZeroDWORD = NonZero_c_ulong; pub type HANDLE = LPVOID; @@ -53,6 +58,7 @@ pub type LPWSADATA = *mut WSADATA; pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; pub type LPWSTR = *mut WCHAR; pub type LPFILETIME = *mut FILETIME; +pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; pub type LPWSABUF = *mut WSABUF; pub type LPWSAOVERLAPPED = *mut c_void; pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void; @@ -68,6 +74,10 @@ pub type ADDRESS_FAMILY = USHORT; pub const TRUE: BOOL = 1; pub const FALSE: BOOL = 0; +pub const CSTR_LESS_THAN: c_int = 1; +pub const CSTR_EQUAL: c_int = 2; +pub const CSTR_GREATER_THAN: c_int = 3; + pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1; pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10; pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400; @@ -132,19 +142,6 @@ pub const WSASYS_STATUS_LEN: usize = 128; pub const WSAPROTOCOL_LEN: DWORD = 255; pub const INVALID_SOCKET: SOCKET = !0; -pub const WSAEACCES: c_int = 10013; -pub const WSAEINVAL: c_int = 10022; -pub const WSAEWOULDBLOCK: c_int = 10035; -pub const WSAEPROTOTYPE: c_int = 10041; -pub const WSAEADDRINUSE: c_int = 10048; -pub const WSAEADDRNOTAVAIL: c_int = 10049; -pub const WSAECONNABORTED: c_int = 10053; -pub const WSAECONNRESET: c_int = 10054; -pub const WSAENOTCONN: c_int = 10057; -pub const WSAESHUTDOWN: c_int = 10058; -pub const WSAETIMEDOUT: c_int = 10060; -pub const WSAECONNREFUSED: c_int = 10061; - pub const MAX_PROTOCOL_CHAIN: DWORD = 7; pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; @@ -164,42 +161,6 @@ pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; pub const PROGRESS_CONTINUE: DWORD = 0; -// List of Windows system error codes with descriptions: -// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes -pub const ERROR_FILE_NOT_FOUND: DWORD = 2; -pub const ERROR_PATH_NOT_FOUND: DWORD = 3; -pub const ERROR_ACCESS_DENIED: DWORD = 5; -pub const ERROR_INVALID_HANDLE: DWORD = 6; -pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8; -pub const ERROR_OUTOFMEMORY: DWORD = 14; -pub const ERROR_NO_MORE_FILES: DWORD = 18; -pub const ERROR_SHARING_VIOLATION: u32 = 32; -pub const ERROR_HANDLE_EOF: DWORD = 38; -pub const ERROR_FILE_EXISTS: DWORD = 80; -pub const ERROR_INVALID_PARAMETER: DWORD = 87; -pub const ERROR_BROKEN_PIPE: DWORD = 109; -pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; -pub const ERROR_SEM_TIMEOUT: DWORD = 121; -pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; -pub const ERROR_ALREADY_EXISTS: DWORD = 183; -pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; -pub const ERROR_NO_DATA: DWORD = 232; -pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; -pub const ERROR_OPERATION_ABORTED: DWORD = 995; -pub const ERROR_IO_PENDING: DWORD = 997; -pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; -pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; -pub const ERROR_TIMEOUT: DWORD = 1460; -pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; -pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; -pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; -pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; -pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; -pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; -pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; -pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; -pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; - pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT; pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE; @@ -234,6 +195,7 @@ pub const SD_RECEIVE: c_int = 0; pub const SD_SEND: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_STREAM: c_int = 1; +pub const SOCKET_ERROR: c_int = -1; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_SNDTIMEO: c_int = 0x1005; @@ -532,6 +494,21 @@ pub struct FILETIME { pub dwHighDateTime: DWORD, } +#[repr(C)] +pub struct SYSTEM_INFO { + pub wProcessorArchitecture: WORD, + pub wReserved: WORD, + pub dwPageSize: DWORD, + pub lpMinimumApplicationAddress: LPVOID, + pub lpMaximumApplicationAddress: LPVOID, + pub dwActiveProcessorMask: DWORD_PTR, + pub dwNumberOfProcessors: DWORD, + pub dwProcessorType: DWORD, + pub dwAllocationGranularity: DWORD, + pub wProcessorLevel: WORD, + pub wProcessorRevision: WORD, +} + #[repr(C)] pub struct OVERLAPPED { pub Internal: *mut c_ulong, @@ -933,6 +910,7 @@ extern "system" { pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); + pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); pub fn CreateEventW( lpEventAttributes: LPSECURITY_ATTRIBUTES, @@ -996,6 +974,14 @@ extern "system" { pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK); pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN; pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN; + + pub fn CompareStringOrdinal( + lpString1: LPCWSTR, + cchCount1: c_int, + lpString2: LPCWSTR, + cchCount2: c_int, + bIgnoreCase: BOOL, + ) -> c_int; } #[link(name = "ws2_32")] diff --git a/library/std/src/sys/windows/c/errors.rs b/library/std/src/sys/windows/c/errors.rs new file mode 100644 index 0000000000..23dcc119db --- /dev/null +++ b/library/std/src/sys/windows/c/errors.rs @@ -0,0 +1,1883 @@ +// List of Windows system error codes with descriptions: +// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes + +#![allow(dead_code)] + +use super::{c_int, DWORD}; + +pub const ERROR_DIRECTORY_NOT_SUPPORTED: DWORD = 336; +pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; +pub const ERROR_DISK_QUOTA_EXCEEDED: DWORD = 1295; +pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; +pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; +pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; + +// The followiung list was obtained from +// `/usr/x86_64-w64-mingw32/include/winerror.h` +// in the Debian package +// mingw-w64_6.0.0-3_all.deb +// +// The header of that file says: +// * This file has no copyright assigned and is placed in the Public Domain. +// * This file is part of the mingw-w64 runtime package. +// * No warranty is given; refer to the file DISCLAIMER.PD within this package. +// +// The text here is the result of the following rune: +// grep -P '#define ERROR' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs +// grep -P '#define WSA' /usr/x86_64-w64-mingw32/include/winerror.h >>library/std/src/sys/windows/c/errors.rs +// and then using some manually-invented but rather obvious editor search-and-replace +// invocations, plus some straightforward manual fixups, to turn it into Rust syntax +// and remove all the duplicates from the manual table above. + +pub const ERROR_SUCCESS: DWORD = 0; +pub const ERROR_INVALID_FUNCTION: DWORD = 1; +pub const ERROR_FILE_NOT_FOUND: DWORD = 2; +pub const ERROR_PATH_NOT_FOUND: DWORD = 3; +pub const ERROR_TOO_MANY_OPEN_FILES: DWORD = 4; +pub const ERROR_ACCESS_DENIED: DWORD = 5; +pub const ERROR_INVALID_HANDLE: DWORD = 6; +pub const ERROR_ARENA_TRASHED: DWORD = 7; +pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8; +pub const ERROR_INVALID_BLOCK: DWORD = 9; +pub const ERROR_BAD_ENVIRONMENT: DWORD = 10; +pub const ERROR_BAD_FORMAT: DWORD = 11; +pub const ERROR_INVALID_ACCESS: DWORD = 12; +pub const ERROR_INVALID_DATA: DWORD = 13; +pub const ERROR_OUTOFMEMORY: DWORD = 14; +pub const ERROR_INVALID_DRIVE: DWORD = 15; +pub const ERROR_CURRENT_DIRECTORY: DWORD = 16; +pub const ERROR_NOT_SAME_DEVICE: DWORD = 17; +pub const ERROR_NO_MORE_FILES: DWORD = 18; +pub const ERROR_WRITE_PROTECT: DWORD = 19; +pub const ERROR_BAD_UNIT: DWORD = 20; +pub const ERROR_NOT_READY: DWORD = 21; +pub const ERROR_BAD_COMMAND: DWORD = 22; +pub const ERROR_CRC: DWORD = 23; +pub const ERROR_BAD_LENGTH: DWORD = 24; +pub const ERROR_SEEK: DWORD = 25; +pub const ERROR_NOT_DOS_DISK: DWORD = 26; +pub const ERROR_SECTOR_NOT_FOUND: DWORD = 27; +pub const ERROR_OUT_OF_PAPER: DWORD = 28; +pub const ERROR_WRITE_FAULT: DWORD = 29; +pub const ERROR_READ_FAULT: DWORD = 30; +pub const ERROR_GEN_FAILURE: DWORD = 31; +pub const ERROR_SHARING_VIOLATION: DWORD = 32; +pub const ERROR_LOCK_VIOLATION: DWORD = 33; +pub const ERROR_WRONG_DISK: DWORD = 34; +pub const ERROR_SHARING_BUFFER_EXCEEDED: DWORD = 36; +pub const ERROR_HANDLE_EOF: DWORD = 38; +pub const ERROR_HANDLE_DISK_FULL: DWORD = 39; +pub const ERROR_NOT_SUPPORTED: DWORD = 50; +pub const ERROR_REM_NOT_LIST: DWORD = 51; +pub const ERROR_DUP_NAME: DWORD = 52; +pub const ERROR_BAD_NETPATH: DWORD = 53; +pub const ERROR_NETWORK_BUSY: DWORD = 54; +pub const ERROR_DEV_NOT_EXIST: DWORD = 55; +pub const ERROR_TOO_MANY_CMDS: DWORD = 56; +pub const ERROR_ADAP_HDW_ERR: DWORD = 57; +pub const ERROR_BAD_NET_RESP: DWORD = 58; +pub const ERROR_UNEXP_NET_ERR: DWORD = 59; +pub const ERROR_BAD_REM_ADAP: DWORD = 60; +pub const ERROR_PRINTQ_FULL: DWORD = 61; +pub const ERROR_NO_SPOOL_SPACE: DWORD = 62; +pub const ERROR_PRINT_CANCELLED: DWORD = 63; +pub const ERROR_NETNAME_DELETED: DWORD = 64; +pub const ERROR_NETWORK_ACCESS_DENIED: DWORD = 65; +pub const ERROR_BAD_DEV_TYPE: DWORD = 66; +pub const ERROR_BAD_NET_NAME: DWORD = 67; +pub const ERROR_TOO_MANY_NAMES: DWORD = 68; +pub const ERROR_TOO_MANY_SESS: DWORD = 69; +pub const ERROR_SHARING_PAUSED: DWORD = 70; +pub const ERROR_REQ_NOT_ACCEP: DWORD = 71; +pub const ERROR_REDIR_PAUSED: DWORD = 72; +pub const ERROR_FILE_EXISTS: DWORD = 80; +pub const ERROR_CANNOT_MAKE: DWORD = 82; +pub const ERROR_FAIL_I24: DWORD = 83; +pub const ERROR_OUT_OF_STRUCTURES: DWORD = 84; +pub const ERROR_ALREADY_ASSIGNED: DWORD = 85; +pub const ERROR_INVALID_PASSWORD: DWORD = 86; +pub const ERROR_INVALID_PARAMETER: DWORD = 87; +pub const ERROR_NET_WRITE_FAULT: DWORD = 88; +pub const ERROR_NO_PROC_SLOTS: DWORD = 89; +pub const ERROR_TOO_MANY_SEMAPHORES: DWORD = 100; +pub const ERROR_EXCL_SEM_ALREADY_OWNED: DWORD = 101; +pub const ERROR_SEM_IS_SET: DWORD = 102; +pub const ERROR_TOO_MANY_SEM_REQUESTS: DWORD = 103; +pub const ERROR_INVALID_AT_INTERRUPT_TIME: DWORD = 104; +pub const ERROR_SEM_OWNER_DIED: DWORD = 105; +pub const ERROR_SEM_USER_LIMIT: DWORD = 106; +pub const ERROR_DISK_CHANGE: DWORD = 107; +pub const ERROR_DRIVE_LOCKED: DWORD = 108; +pub const ERROR_BROKEN_PIPE: DWORD = 109; +pub const ERROR_OPEN_FAILED: DWORD = 110; +pub const ERROR_BUFFER_OVERFLOW: DWORD = 111; +pub const ERROR_DISK_FULL: DWORD = 112; +pub const ERROR_NO_MORE_SEARCH_HANDLES: DWORD = 113; +pub const ERROR_INVALID_TARGET_HANDLE: DWORD = 114; +pub const ERROR_INVALID_CATEGORY: DWORD = 117; +pub const ERROR_INVALID_VERIFY_SWITCH: DWORD = 118; +pub const ERROR_BAD_DRIVER_LEVEL: DWORD = 119; +pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; +pub const ERROR_SEM_TIMEOUT: DWORD = 121; +pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; +pub const ERROR_INVALID_NAME: DWORD = 123; +pub const ERROR_INVALID_LEVEL: DWORD = 124; +pub const ERROR_NO_VOLUME_LABEL: DWORD = 125; +pub const ERROR_MOD_NOT_FOUND: DWORD = 126; +pub const ERROR_PROC_NOT_FOUND: DWORD = 127; +pub const ERROR_WAIT_NO_CHILDREN: DWORD = 128; +pub const ERROR_CHILD_NOT_COMPLETE: DWORD = 129; +pub const ERROR_DIRECT_ACCESS_HANDLE: DWORD = 130; +pub const ERROR_NEGATIVE_SEEK: DWORD = 131; +pub const ERROR_SEEK_ON_DEVICE: DWORD = 132; +pub const ERROR_IS_JOIN_TARGET: DWORD = 133; +pub const ERROR_IS_JOINED: DWORD = 134; +pub const ERROR_IS_SUBSTED: DWORD = 135; +pub const ERROR_NOT_JOINED: DWORD = 136; +pub const ERROR_NOT_SUBSTED: DWORD = 137; +pub const ERROR_JOIN_TO_JOIN: DWORD = 138; +pub const ERROR_SUBST_TO_SUBST: DWORD = 139; +pub const ERROR_JOIN_TO_SUBST: DWORD = 140; +pub const ERROR_SUBST_TO_JOIN: DWORD = 141; +pub const ERROR_BUSY_DRIVE: DWORD = 142; +pub const ERROR_SAME_DRIVE: DWORD = 143; +pub const ERROR_DIR_NOT_ROOT: DWORD = 144; +pub const ERROR_DIR_NOT_EMPTY: DWORD = 145; +pub const ERROR_IS_SUBST_PATH: DWORD = 146; +pub const ERROR_IS_JOIN_PATH: DWORD = 147; +pub const ERROR_PATH_BUSY: DWORD = 148; +pub const ERROR_IS_SUBST_TARGET: DWORD = 149; +pub const ERROR_SYSTEM_TRACE: DWORD = 150; +pub const ERROR_INVALID_EVENT_COUNT: DWORD = 151; +pub const ERROR_TOO_MANY_MUXWAITERS: DWORD = 152; +pub const ERROR_INVALID_LIST_FORMAT: DWORD = 153; +pub const ERROR_LABEL_TOO_LONG: DWORD = 154; +pub const ERROR_TOO_MANY_TCBS: DWORD = 155; +pub const ERROR_SIGNAL_REFUSED: DWORD = 156; +pub const ERROR_DISCARDED: DWORD = 157; +pub const ERROR_NOT_LOCKED: DWORD = 158; +pub const ERROR_BAD_THREADID_ADDR: DWORD = 159; +pub const ERROR_BAD_ARGUMENTS: DWORD = 160; +pub const ERROR_BAD_PATHNAME: DWORD = 161; +pub const ERROR_SIGNAL_PENDING: DWORD = 162; +pub const ERROR_MAX_THRDS_REACHED: DWORD = 164; +pub const ERROR_LOCK_FAILED: DWORD = 167; +pub const ERROR_BUSY: DWORD = 170; +pub const ERROR_CANCEL_VIOLATION: DWORD = 173; +pub const ERROR_ATOMIC_LOCKS_NOT_SUPPORTED: DWORD = 174; +pub const ERROR_INVALID_SEGMENT_NUMBER: DWORD = 180; +pub const ERROR_INVALID_ORDINAL: DWORD = 182; +pub const ERROR_ALREADY_EXISTS: DWORD = 183; +pub const ERROR_INVALID_FLAG_NUMBER: DWORD = 186; +pub const ERROR_SEM_NOT_FOUND: DWORD = 187; +pub const ERROR_INVALID_STARTING_CODESEG: DWORD = 188; +pub const ERROR_INVALID_STACKSEG: DWORD = 189; +pub const ERROR_INVALID_MODULETYPE: DWORD = 190; +pub const ERROR_INVALID_EXE_SIGNATURE: DWORD = 191; +pub const ERROR_EXE_MARKED_INVALID: DWORD = 192; +pub const ERROR_BAD_EXE_FORMAT: DWORD = 193; +pub const ERROR_ITERATED_DATA_EXCEEDS_64k: DWORD = 194; +pub const ERROR_INVALID_MINALLOCSIZE: DWORD = 195; +pub const ERROR_DYNLINK_FROM_INVALID_RING: DWORD = 196; +pub const ERROR_IOPL_NOT_ENABLED: DWORD = 197; +pub const ERROR_INVALID_SEGDPL: DWORD = 198; +pub const ERROR_AUTODATASEG_EXCEEDS_64k: DWORD = 199; +pub const ERROR_RING2SEG_MUST_BE_MOVABLE: DWORD = 200; +pub const ERROR_RELOC_CHAIN_XEEDS_SEGLIM: DWORD = 201; +pub const ERROR_INFLOOP_IN_RELOC_CHAIN: DWORD = 202; +pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; +pub const ERROR_NO_SIGNAL_SENT: DWORD = 205; +pub const ERROR_FILENAME_EXCED_RANGE: DWORD = 206; +pub const ERROR_RING2_STACK_IN_USE: DWORD = 207; +pub const ERROR_META_EXPANSION_TOO_LONG: DWORD = 208; +pub const ERROR_INVALID_SIGNAL_NUMBER: DWORD = 209; +pub const ERROR_THREAD_1_INACTIVE: DWORD = 210; +pub const ERROR_LOCKED: DWORD = 212; +pub const ERROR_TOO_MANY_MODULES: DWORD = 214; +pub const ERROR_NESTING_NOT_ALLOWED: DWORD = 215; +pub const ERROR_EXE_MACHINE_TYPE_MISMATCH: DWORD = 216; +pub const ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY: DWORD = 217; +pub const ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY: DWORD = 218; +pub const ERROR_FILE_CHECKED_OUT: DWORD = 220; +pub const ERROR_CHECKOUT_REQUIRED: DWORD = 221; +pub const ERROR_BAD_FILE_TYPE: DWORD = 222; +pub const ERROR_FILE_TOO_LARGE: DWORD = 223; +pub const ERROR_FORMS_AUTH_REQUIRED: DWORD = 224; +pub const ERROR_PIPE_LOCAL: DWORD = 229; +pub const ERROR_BAD_PIPE: DWORD = 230; +pub const ERROR_PIPE_BUSY: DWORD = 231; +pub const ERROR_NO_DATA: DWORD = 232; +pub const ERROR_PIPE_NOT_CONNECTED: DWORD = 233; +pub const ERROR_MORE_DATA: DWORD = 234; +pub const ERROR_VC_DISCONNECTED: DWORD = 240; +pub const ERROR_INVALID_EA_NAME: DWORD = 254; +pub const ERROR_EA_LIST_INCONSISTENT: DWORD = 255; +pub const ERROR_NO_MORE_ITEMS: DWORD = 259; +pub const ERROR_CANNOT_COPY: DWORD = 266; +pub const ERROR_DIRECTORY: DWORD = 267; +pub const ERROR_EAS_DIDNT_FIT: DWORD = 275; +pub const ERROR_EA_FILE_CORRUPT: DWORD = 276; +pub const ERROR_EA_TABLE_FULL: DWORD = 277; +pub const ERROR_INVALID_EA_HANDLE: DWORD = 278; +pub const ERROR_EAS_NOT_SUPPORTED: DWORD = 282; +pub const ERROR_NOT_OWNER: DWORD = 288; +pub const ERROR_TOO_MANY_POSTS: DWORD = 298; +pub const ERROR_PARTIAL_COPY: DWORD = 299; +pub const ERROR_OPLOCK_NOT_GRANTED: DWORD = 300; +pub const ERROR_INVALID_OPLOCK_PROTOCOL: DWORD = 301; +pub const ERROR_DISK_TOO_FRAGMENTED: DWORD = 302; +pub const ERROR_DELETE_PENDING: DWORD = 303; +pub const ERROR_INVALID_TOKEN: DWORD = 315; +pub const ERROR_MR_MID_NOT_FOUND: DWORD = 317; +pub const ERROR_SCOPE_NOT_FOUND: DWORD = 318; +pub const ERROR_INVALID_ADDRESS: DWORD = 487; +pub const ERROR_ARITHMETIC_OVERFLOW: DWORD = 534; +pub const ERROR_PIPE_CONNECTED: DWORD = 535; +pub const ERROR_PIPE_LISTENING: DWORD = 536; +pub const ERROR_WAKE_SYSTEM: DWORD = 730; +pub const ERROR_WAIT_1: DWORD = 731; +pub const ERROR_WAIT_2: DWORD = 732; +pub const ERROR_WAIT_3: DWORD = 733; +pub const ERROR_WAIT_63: DWORD = 734; +pub const ERROR_ABANDONED_WAIT_0: DWORD = 735; +pub const ERROR_ABANDONED_WAIT_63: DWORD = 736; +pub const ERROR_USER_APC: DWORD = 737; +pub const ERROR_KERNEL_APC: DWORD = 738; +pub const ERROR_ALERTED: DWORD = 739; +pub const ERROR_EA_ACCESS_DENIED: DWORD = 994; +pub const ERROR_OPERATION_ABORTED: DWORD = 995; +pub const ERROR_IO_INCOMPLETE: DWORD = 996; +pub const ERROR_IO_PENDING: DWORD = 997; +pub const ERROR_NOACCESS: DWORD = 998; +pub const ERROR_SWAPERROR: DWORD = 999; +pub const ERROR_STACK_OVERFLOW: DWORD = 1001; +pub const ERROR_INVALID_MESSAGE: DWORD = 1002; +pub const ERROR_CAN_NOT_COMPLETE: DWORD = 1003; +pub const ERROR_INVALID_FLAGS: DWORD = 1004; +pub const ERROR_UNRECOGNIZED_VOLUME: DWORD = 1005; +pub const ERROR_FILE_INVALID: DWORD = 1006; +pub const ERROR_FULLSCREEN_MODE: DWORD = 1007; +pub const ERROR_NO_TOKEN: DWORD = 1008; +pub const ERROR_BADDB: DWORD = 1009; +pub const ERROR_BADKEY: DWORD = 1010; +pub const ERROR_CANTOPEN: DWORD = 1011; +pub const ERROR_CANTREAD: DWORD = 1012; +pub const ERROR_CANTWRITE: DWORD = 1013; +pub const ERROR_REGISTRY_RECOVERED: DWORD = 1014; +pub const ERROR_REGISTRY_CORRUPT: DWORD = 1015; +pub const ERROR_REGISTRY_IO_FAILED: DWORD = 1016; +pub const ERROR_NOT_REGISTRY_FILE: DWORD = 1017; +pub const ERROR_KEY_DELETED: DWORD = 1018; +pub const ERROR_NO_LOG_SPACE: DWORD = 1019; +pub const ERROR_KEY_HAS_CHILDREN: DWORD = 1020; +pub const ERROR_CHILD_MUST_BE_VOLATILE: DWORD = 1021; +pub const ERROR_NOTIFY_ENUM_DIR: DWORD = 1022; +pub const ERROR_DEPENDENT_SERVICES_RUNNING: DWORD = 1051; +pub const ERROR_INVALID_SERVICE_CONTROL: DWORD = 1052; +pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; +pub const ERROR_SERVICE_NO_THREAD: DWORD = 1054; +pub const ERROR_SERVICE_DATABASE_LOCKED: DWORD = 1055; +pub const ERROR_SERVICE_ALREADY_RUNNING: DWORD = 1056; +pub const ERROR_INVALID_SERVICE_ACCOUNT: DWORD = 1057; +pub const ERROR_SERVICE_DISABLED: DWORD = 1058; +pub const ERROR_CIRCULAR_DEPENDENCY: DWORD = 1059; +pub const ERROR_SERVICE_DOES_NOT_EXIST: DWORD = 1060; +pub const ERROR_SERVICE_CANNOT_ACCEPT_CTRL: DWORD = 1061; +pub const ERROR_SERVICE_NOT_ACTIVE: DWORD = 1062; +pub const ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: DWORD = 1063; +pub const ERROR_EXCEPTION_IN_SERVICE: DWORD = 1064; +pub const ERROR_DATABASE_DOES_NOT_EXIST: DWORD = 1065; +pub const ERROR_SERVICE_SPECIFIC_ERROR: DWORD = 1066; +pub const ERROR_PROCESS_ABORTED: DWORD = 1067; +pub const ERROR_SERVICE_DEPENDENCY_FAIL: DWORD = 1068; +pub const ERROR_SERVICE_LOGON_FAILED: DWORD = 1069; +pub const ERROR_SERVICE_START_HANG: DWORD = 1070; +pub const ERROR_INVALID_SERVICE_LOCK: DWORD = 1071; +pub const ERROR_SERVICE_MARKED_FOR_DELETE: DWORD = 1072; +pub const ERROR_SERVICE_EXISTS: DWORD = 1073; +pub const ERROR_ALREADY_RUNNING_LKG: DWORD = 1074; +pub const ERROR_SERVICE_DEPENDENCY_DELETED: DWORD = 1075; +pub const ERROR_BOOT_ALREADY_ACCEPTED: DWORD = 1076; +pub const ERROR_SERVICE_NEVER_STARTED: DWORD = 1077; +pub const ERROR_DUPLICATE_SERVICE_NAME: DWORD = 1078; +pub const ERROR_DIFFERENT_SERVICE_ACCOUNT: DWORD = 1079; +pub const ERROR_CANNOT_DETECT_DRIVER_FAILURE: DWORD = 1080; +pub const ERROR_CANNOT_DETECT_PROCESS_ABORT: DWORD = 1081; +pub const ERROR_NO_RECOVERY_PROGRAM: DWORD = 1082; +pub const ERROR_SERVICE_NOT_IN_EXE: DWORD = 1083; +pub const ERROR_NOT_SAFEBOOT_SERVICE: DWORD = 1084; +pub const ERROR_END_OF_MEDIA: DWORD = 1100; +pub const ERROR_FILEMARK_DETECTED: DWORD = 1101; +pub const ERROR_BEGINNING_OF_MEDIA: DWORD = 1102; +pub const ERROR_SETMARK_DETECTED: DWORD = 1103; +pub const ERROR_NO_DATA_DETECTED: DWORD = 1104; +pub const ERROR_PARTITION_FAILURE: DWORD = 1105; +pub const ERROR_INVALID_BLOCK_LENGTH: DWORD = 1106; +pub const ERROR_DEVICE_NOT_PARTITIONED: DWORD = 1107; +pub const ERROR_UNABLE_TO_LOCK_MEDIA: DWORD = 1108; +pub const ERROR_UNABLE_TO_UNLOAD_MEDIA: DWORD = 1109; +pub const ERROR_MEDIA_CHANGED: DWORD = 1110; +pub const ERROR_BUS_RESET: DWORD = 1111; +pub const ERROR_NO_MEDIA_IN_DRIVE: DWORD = 1112; +pub const ERROR_NO_UNICODE_TRANSLATION: DWORD = 1113; +pub const ERROR_DLL_INIT_FAILED: DWORD = 1114; +pub const ERROR_SHUTDOWN_IN_PROGRESS: DWORD = 1115; +pub const ERROR_NO_SHUTDOWN_IN_PROGRESS: DWORD = 1116; +pub const ERROR_IO_DEVICE: DWORD = 1117; +pub const ERROR_SERIAL_NO_DEVICE: DWORD = 1118; +pub const ERROR_IRQ_BUSY: DWORD = 1119; +pub const ERROR_MORE_WRITES: DWORD = 1120; +pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; +pub const ERROR_FLOPPY_ID_MARK_NOT_FOUND: DWORD = 1122; +pub const ERROR_FLOPPY_WRONG_CYLINDER: DWORD = 1123; +pub const ERROR_FLOPPY_UNKNOWN_ERROR: DWORD = 1124; +pub const ERROR_FLOPPY_BAD_REGISTERS: DWORD = 1125; +pub const ERROR_DISK_RECALIBRATE_FAILED: DWORD = 1126; +pub const ERROR_DISK_OPERATION_FAILED: DWORD = 1127; +pub const ERROR_DISK_RESET_FAILED: DWORD = 1128; +pub const ERROR_EOM_OVERFLOW: DWORD = 1129; +pub const ERROR_NOT_ENOUGH_SERVER_MEMORY: DWORD = 1130; +pub const ERROR_POSSIBLE_DEADLOCK: DWORD = 1131; +pub const ERROR_MAPPED_ALIGNMENT: DWORD = 1132; +pub const ERROR_SET_POWER_STATE_VETOED: DWORD = 1140; +pub const ERROR_SET_POWER_STATE_FAILED: DWORD = 1141; +pub const ERROR_TOO_MANY_LINKS: DWORD = 1142; +pub const ERROR_OLD_WIN_VERSION: DWORD = 1150; +pub const ERROR_APP_WRONG_OS: DWORD = 1151; +pub const ERROR_SINGLE_INSTANCE_APP: DWORD = 1152; +pub const ERROR_RMODE_APP: DWORD = 1153; +pub const ERROR_INVALID_DLL: DWORD = 1154; +pub const ERROR_NO_ASSOCIATION: DWORD = 1155; +pub const ERROR_DDE_FAIL: DWORD = 1156; +pub const ERROR_DLL_NOT_FOUND: DWORD = 1157; +pub const ERROR_NO_MORE_USER_HANDLES: DWORD = 1158; +pub const ERROR_MESSAGE_SYNC_ONLY: DWORD = 1159; +pub const ERROR_SOURCE_ELEMENT_EMPTY: DWORD = 1160; +pub const ERROR_DESTINATION_ELEMENT_FULL: DWORD = 1161; +pub const ERROR_ILLEGAL_ELEMENT_ADDRESS: DWORD = 1162; +pub const ERROR_MAGAZINE_NOT_PRESENT: DWORD = 1163; +pub const ERROR_DEVICE_REINITIALIZATION_NEEDED: DWORD = 1164; +pub const ERROR_DEVICE_REQUIRES_CLEANING: DWORD = 1165; +pub const ERROR_DEVICE_DOOR_OPEN: DWORD = 1166; +pub const ERROR_DEVICE_NOT_CONNECTED: DWORD = 1167; +pub const ERROR_NOT_FOUND: DWORD = 1168; +pub const ERROR_NO_MATCH: DWORD = 1169; +pub const ERROR_SET_NOT_FOUND: DWORD = 1170; +pub const ERROR_POINT_NOT_FOUND: DWORD = 1171; +pub const ERROR_NO_TRACKING_SERVICE: DWORD = 1172; +pub const ERROR_NO_VOLUME_ID: DWORD = 1173; +pub const ERROR_UNABLE_TO_REMOVE_REPLACED: DWORD = 1175; +pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT: DWORD = 1176; +pub const ERROR_UNABLE_TO_MOVE_REPLACEMENT_2: DWORD = 1177; +pub const ERROR_JOURNAL_DELETE_IN_PROGRESS: DWORD = 1178; +pub const ERROR_JOURNAL_NOT_ACTIVE: DWORD = 1179; +pub const ERROR_POTENTIAL_FILE_FOUND: DWORD = 1180; +pub const ERROR_JOURNAL_ENTRY_DELETED: DWORD = 1181; +pub const ERROR_BAD_DEVICE: DWORD = 1200; +pub const ERROR_CONNECTION_UNAVAIL: DWORD = 1201; +pub const ERROR_DEVICE_ALREADY_REMEMBERED: DWORD = 1202; +pub const ERROR_NO_NET_OR_BAD_PATH: DWORD = 1203; +pub const ERROR_BAD_PROVIDER: DWORD = 1204; +pub const ERROR_CANNOT_OPEN_PROFILE: DWORD = 1205; +pub const ERROR_BAD_PROFILE: DWORD = 1206; +pub const ERROR_NOT_CONTAINER: DWORD = 1207; +pub const ERROR_EXTENDED_ERROR: DWORD = 1208; +pub const ERROR_INVALID_GROUPNAME: DWORD = 1209; +pub const ERROR_INVALID_COMPUTERNAME: DWORD = 1210; +pub const ERROR_INVALID_EVENTNAME: DWORD = 1211; +pub const ERROR_INVALID_DOMAINNAME: DWORD = 1212; +pub const ERROR_INVALID_SERVICENAME: DWORD = 1213; +pub const ERROR_INVALID_NETNAME: DWORD = 1214; +pub const ERROR_INVALID_SHARENAME: DWORD = 1215; +pub const ERROR_INVALID_PASSWORDNAME: DWORD = 1216; +pub const ERROR_INVALID_MESSAGENAME: DWORD = 1217; +pub const ERROR_INVALID_MESSAGEDEST: DWORD = 1218; +pub const ERROR_SESSION_CREDENTIAL_CONFLICT: DWORD = 1219; +pub const ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: DWORD = 1220; +pub const ERROR_DUP_DOMAINNAME: DWORD = 1221; +pub const ERROR_NO_NETWORK: DWORD = 1222; +pub const ERROR_CANCELLED: DWORD = 1223; +pub const ERROR_USER_MAPPED_FILE: DWORD = 1224; +pub const ERROR_CONNECTION_REFUSED: DWORD = 1225; +pub const ERROR_GRACEFUL_DISCONNECT: DWORD = 1226; +pub const ERROR_ADDRESS_ALREADY_ASSOCIATED: DWORD = 1227; +pub const ERROR_ADDRESS_NOT_ASSOCIATED: DWORD = 1228; +pub const ERROR_CONNECTION_INVALID: DWORD = 1229; +pub const ERROR_CONNECTION_ACTIVE: DWORD = 1230; +pub const ERROR_NETWORK_UNREACHABLE: DWORD = 1231; +pub const ERROR_HOST_UNREACHABLE: DWORD = 1232; +pub const ERROR_PROTOCOL_UNREACHABLE: DWORD = 1233; +pub const ERROR_PORT_UNREACHABLE: DWORD = 1234; +pub const ERROR_REQUEST_ABORTED: DWORD = 1235; +pub const ERROR_CONNECTION_ABORTED: DWORD = 1236; +pub const ERROR_RETRY: DWORD = 1237; +pub const ERROR_CONNECTION_COUNT_LIMIT: DWORD = 1238; +pub const ERROR_LOGIN_TIME_RESTRICTION: DWORD = 1239; +pub const ERROR_LOGIN_WKSTA_RESTRICTION: DWORD = 1240; +pub const ERROR_INCORRECT_ADDRESS: DWORD = 1241; +pub const ERROR_ALREADY_REGISTERED: DWORD = 1242; +pub const ERROR_SERVICE_NOT_FOUND: DWORD = 1243; +pub const ERROR_NOT_AUTHENTICATED: DWORD = 1244; +pub const ERROR_NOT_LOGGED_ON: DWORD = 1245; +pub const ERROR_CONTINUE: DWORD = 1246; +pub const ERROR_ALREADY_INITIALIZED: DWORD = 1247; +pub const ERROR_NO_MORE_DEVICES: DWORD = 1248; +pub const ERROR_NO_SUCH_SITE: DWORD = 1249; +pub const ERROR_DOMAIN_CONTROLLER_EXISTS: DWORD = 1250; +pub const ERROR_ONLY_IF_CONNECTED: DWORD = 1251; +pub const ERROR_OVERRIDE_NOCHANGES: DWORD = 1252; +pub const ERROR_BAD_USER_PROFILE: DWORD = 1253; +pub const ERROR_NOT_SUPPORTED_ON_SBS: DWORD = 1254; +pub const ERROR_SERVER_SHUTDOWN_IN_PROGRESS: DWORD = 1255; +pub const ERROR_HOST_DOWN: DWORD = 1256; +pub const ERROR_NON_ACCOUNT_SID: DWORD = 1257; +pub const ERROR_NON_DOMAIN_SID: DWORD = 1258; +pub const ERROR_APPHELP_BLOCK: DWORD = 1259; +pub const ERROR_ACCESS_DISABLED_BY_POLICY: DWORD = 1260; +pub const ERROR_REG_NAT_CONSUMPTION: DWORD = 1261; +pub const ERROR_CSCSHARE_OFFLINE: DWORD = 1262; +pub const ERROR_PKINIT_FAILURE: DWORD = 1263; +pub const ERROR_SMARTCARD_SUBSYSTEM_FAILURE: DWORD = 1264; +pub const ERROR_DOWNGRADE_DETECTED: DWORD = 1265; +pub const ERROR_MACHINE_LOCKED: DWORD = 1271; +pub const ERROR_CALLBACK_SUPPLIED_INVALID_DATA: DWORD = 1273; +pub const ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED: DWORD = 1274; +pub const ERROR_DRIVER_BLOCKED: DWORD = 1275; +pub const ERROR_INVALID_IMPORT_OF_NON_DLL: DWORD = 1276; +pub const ERROR_ACCESS_DISABLED_WEBBLADE: DWORD = 1277; +pub const ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER: DWORD = 1278; +pub const ERROR_RECOVERY_FAILURE: DWORD = 1279; +pub const ERROR_ALREADY_FIBER: DWORD = 1280; +pub const ERROR_ALREADY_THREAD: DWORD = 1281; +pub const ERROR_STACK_BUFFER_OVERRUN: DWORD = 1282; +pub const ERROR_PARAMETER_QUOTA_EXCEEDED: DWORD = 1283; +pub const ERROR_DEBUGGER_INACTIVE: DWORD = 1284; +pub const ERROR_DELAY_LOAD_FAILED: DWORD = 1285; +pub const ERROR_VDM_DISALLOWED: DWORD = 1286; +pub const ERROR_UNIDENTIFIED_ERROR: DWORD = 1287; +pub const ERROR_NOT_ALL_ASSIGNED: DWORD = 1300; +pub const ERROR_SOME_NOT_MAPPED: DWORD = 1301; +pub const ERROR_NO_QUOTAS_FOR_ACCOUNT: DWORD = 1302; +pub const ERROR_LOCAL_USER_SESSION_KEY: DWORD = 1303; +pub const ERROR_NULL_LM_PASSWORD: DWORD = 1304; +pub const ERROR_UNKNOWN_REVISION: DWORD = 1305; +pub const ERROR_REVISION_MISMATCH: DWORD = 1306; +pub const ERROR_INVALID_OWNER: DWORD = 1307; +pub const ERROR_INVALID_PRIMARY_GROUP: DWORD = 1308; +pub const ERROR_NO_IMPERSONATION_TOKEN: DWORD = 1309; +pub const ERROR_CANT_DISABLE_MANDATORY: DWORD = 1310; +pub const ERROR_NO_LOGON_SERVERS: DWORD = 1311; +pub const ERROR_NO_SUCH_LOGON_SESSION: DWORD = 1312; +pub const ERROR_NO_SUCH_PRIVILEGE: DWORD = 1313; +pub const ERROR_PRIVILEGE_NOT_HELD: DWORD = 1314; +pub const ERROR_INVALID_ACCOUNT_NAME: DWORD = 1315; +pub const ERROR_USER_EXISTS: DWORD = 1316; +pub const ERROR_NO_SUCH_USER: DWORD = 1317; +pub const ERROR_GROUP_EXISTS: DWORD = 1318; +pub const ERROR_NO_SUCH_GROUP: DWORD = 1319; +pub const ERROR_MEMBER_IN_GROUP: DWORD = 1320; +pub const ERROR_MEMBER_NOT_IN_GROUP: DWORD = 1321; +pub const ERROR_LAST_ADMIN: DWORD = 1322; +pub const ERROR_WRONG_PASSWORD: DWORD = 1323; +pub const ERROR_ILL_FORMED_PASSWORD: DWORD = 1324; +pub const ERROR_PASSWORD_RESTRICTION: DWORD = 1325; +pub const ERROR_LOGON_FAILURE: DWORD = 1326; +pub const ERROR_ACCOUNT_RESTRICTION: DWORD = 1327; +pub const ERROR_INVALID_LOGON_HOURS: DWORD = 1328; +pub const ERROR_INVALID_WORKSTATION: DWORD = 1329; +pub const ERROR_PASSWORD_EXPIRED: DWORD = 1330; +pub const ERROR_ACCOUNT_DISABLED: DWORD = 1331; +pub const ERROR_NONE_MAPPED: DWORD = 1332; +pub const ERROR_TOO_MANY_LUIDS_REQUESTED: DWORD = 1333; +pub const ERROR_LUIDS_EXHAUSTED: DWORD = 1334; +pub const ERROR_INVALID_SUB_AUTHORITY: DWORD = 1335; +pub const ERROR_INVALID_ACL: DWORD = 1336; +pub const ERROR_INVALID_SID: DWORD = 1337; +pub const ERROR_INVALID_SECURITY_DESCR: DWORD = 1338; +pub const ERROR_BAD_INHERITANCE_ACL: DWORD = 1340; +pub const ERROR_SERVER_DISABLED: DWORD = 1341; +pub const ERROR_SERVER_NOT_DISABLED: DWORD = 1342; +pub const ERROR_INVALID_ID_AUTHORITY: DWORD = 1343; +pub const ERROR_ALLOTTED_SPACE_EXCEEDED: DWORD = 1344; +pub const ERROR_INVALID_GROUP_ATTRIBUTES: DWORD = 1345; +pub const ERROR_BAD_IMPERSONATION_LEVEL: DWORD = 1346; +pub const ERROR_CANT_OPEN_ANONYMOUS: DWORD = 1347; +pub const ERROR_BAD_VALIDATION_CLASS: DWORD = 1348; +pub const ERROR_BAD_TOKEN_TYPE: DWORD = 1349; +pub const ERROR_NO_SECURITY_ON_OBJECT: DWORD = 1350; +pub const ERROR_CANT_ACCESS_DOMAIN_INFO: DWORD = 1351; +pub const ERROR_INVALID_SERVER_STATE: DWORD = 1352; +pub const ERROR_INVALID_DOMAIN_STATE: DWORD = 1353; +pub const ERROR_INVALID_DOMAIN_ROLE: DWORD = 1354; +pub const ERROR_NO_SUCH_DOMAIN: DWORD = 1355; +pub const ERROR_DOMAIN_EXISTS: DWORD = 1356; +pub const ERROR_DOMAIN_LIMIT_EXCEEDED: DWORD = 1357; +pub const ERROR_INTERNAL_DB_CORRUPTION: DWORD = 1358; +pub const ERROR_INTERNAL_ERROR: DWORD = 1359; +pub const ERROR_GENERIC_NOT_MAPPED: DWORD = 1360; +pub const ERROR_BAD_DESCRIPTOR_FORMAT: DWORD = 1361; +pub const ERROR_NOT_LOGON_PROCESS: DWORD = 1362; +pub const ERROR_LOGON_SESSION_EXISTS: DWORD = 1363; +pub const ERROR_NO_SUCH_PACKAGE: DWORD = 1364; +pub const ERROR_BAD_LOGON_SESSION_STATE: DWORD = 1365; +pub const ERROR_LOGON_SESSION_COLLISION: DWORD = 1366; +pub const ERROR_INVALID_LOGON_TYPE: DWORD = 1367; +pub const ERROR_CANNOT_IMPERSONATE: DWORD = 1368; +pub const ERROR_RXACT_INVALID_STATE: DWORD = 1369; +pub const ERROR_RXACT_COMMIT_FAILURE: DWORD = 1370; +pub const ERROR_SPECIAL_ACCOUNT: DWORD = 1371; +pub const ERROR_SPECIAL_GROUP: DWORD = 1372; +pub const ERROR_SPECIAL_USER: DWORD = 1373; +pub const ERROR_MEMBERS_PRIMARY_GROUP: DWORD = 1374; +pub const ERROR_TOKEN_ALREADY_IN_USE: DWORD = 1375; +pub const ERROR_NO_SUCH_ALIAS: DWORD = 1376; +pub const ERROR_MEMBER_NOT_IN_ALIAS: DWORD = 1377; +pub const ERROR_MEMBER_IN_ALIAS: DWORD = 1378; +pub const ERROR_ALIAS_EXISTS: DWORD = 1379; +pub const ERROR_LOGON_NOT_GRANTED: DWORD = 1380; +pub const ERROR_TOO_MANY_SECRETS: DWORD = 1381; +pub const ERROR_SECRET_TOO_LONG: DWORD = 1382; +pub const ERROR_INTERNAL_DB_ERROR: DWORD = 1383; +pub const ERROR_TOO_MANY_CONTEXT_IDS: DWORD = 1384; +pub const ERROR_LOGON_TYPE_NOT_GRANTED: DWORD = 1385; +pub const ERROR_NT_CROSS_ENCRYPTION_REQUIRED: DWORD = 1386; +pub const ERROR_NO_SUCH_MEMBER: DWORD = 1387; +pub const ERROR_INVALID_MEMBER: DWORD = 1388; +pub const ERROR_TOO_MANY_SIDS: DWORD = 1389; +pub const ERROR_LM_CROSS_ENCRYPTION_REQUIRED: DWORD = 1390; +pub const ERROR_NO_INHERITANCE: DWORD = 1391; +pub const ERROR_FILE_CORRUPT: DWORD = 1392; +pub const ERROR_DISK_CORRUPT: DWORD = 1393; +pub const ERROR_NO_USER_SESSION_KEY: DWORD = 1394; +pub const ERROR_LICENSE_QUOTA_EXCEEDED: DWORD = 1395; +pub const ERROR_WRONG_TARGET_NAME: DWORD = 1396; +pub const ERROR_MUTUAL_AUTH_FAILED: DWORD = 1397; +pub const ERROR_TIME_SKEW: DWORD = 1398; +pub const ERROR_CURRENT_DOMAIN_NOT_ALLOWED: DWORD = 1399; +pub const ERROR_INVALID_WINDOW_HANDLE: DWORD = 1400; +pub const ERROR_INVALID_MENU_HANDLE: DWORD = 1401; +pub const ERROR_INVALID_CURSOR_HANDLE: DWORD = 1402; +pub const ERROR_INVALID_ACCEL_HANDLE: DWORD = 1403; +pub const ERROR_INVALID_HOOK_HANDLE: DWORD = 1404; +pub const ERROR_INVALID_DWP_HANDLE: DWORD = 1405; +pub const ERROR_TLW_WITH_WSCHILD: DWORD = 1406; +pub const ERROR_CANNOT_FIND_WND_CLASS: DWORD = 1407; +pub const ERROR_WINDOW_OF_OTHER_THREAD: DWORD = 1408; +pub const ERROR_HOTKEY_ALREADY_REGISTERED: DWORD = 1409; +pub const ERROR_CLASS_ALREADY_EXISTS: DWORD = 1410; +pub const ERROR_CLASS_DOES_NOT_EXIST: DWORD = 1411; +pub const ERROR_CLASS_HAS_WINDOWS: DWORD = 1412; +pub const ERROR_INVALID_INDEX: DWORD = 1413; +pub const ERROR_INVALID_ICON_HANDLE: DWORD = 1414; +pub const ERROR_PRIVATE_DIALOG_INDEX: DWORD = 1415; +pub const ERROR_LISTBOX_ID_NOT_FOUND: DWORD = 1416; +pub const ERROR_NO_WILDCARD_CHARACTERS: DWORD = 1417; +pub const ERROR_CLIPBOARD_NOT_OPEN: DWORD = 1418; +pub const ERROR_HOTKEY_NOT_REGISTERED: DWORD = 1419; +pub const ERROR_WINDOW_NOT_DIALOG: DWORD = 1420; +pub const ERROR_CONTROL_ID_NOT_FOUND: DWORD = 1421; +pub const ERROR_INVALID_COMBOBOX_MESSAGE: DWORD = 1422; +pub const ERROR_WINDOW_NOT_COMBOBOX: DWORD = 1423; +pub const ERROR_INVALID_EDIT_HEIGHT: DWORD = 1424; +pub const ERROR_DC_NOT_FOUND: DWORD = 1425; +pub const ERROR_INVALID_HOOK_FILTER: DWORD = 1426; +pub const ERROR_INVALID_FILTER_PROC: DWORD = 1427; +pub const ERROR_HOOK_NEEDS_HMOD: DWORD = 1428; +pub const ERROR_GLOBAL_ONLY_HOOK: DWORD = 1429; +pub const ERROR_JOURNAL_HOOK_SET: DWORD = 1430; +pub const ERROR_HOOK_NOT_INSTALLED: DWORD = 1431; +pub const ERROR_INVALID_LB_MESSAGE: DWORD = 1432; +pub const ERROR_SETCOUNT_ON_BAD_LB: DWORD = 1433; +pub const ERROR_LB_WITHOUT_TABSTOPS: DWORD = 1434; +pub const ERROR_DESTROY_OBJECT_OF_OTHER_THREAD: DWORD = 1435; +pub const ERROR_CHILD_WINDOW_MENU: DWORD = 1436; +pub const ERROR_NO_SYSTEM_MENU: DWORD = 1437; +pub const ERROR_INVALID_MSGBOX_STYLE: DWORD = 1438; +pub const ERROR_INVALID_SPI_VALUE: DWORD = 1439; +pub const ERROR_SCREEN_ALREADY_LOCKED: DWORD = 1440; +pub const ERROR_HWNDS_HAVE_DIFF_PARENT: DWORD = 1441; +pub const ERROR_NOT_CHILD_WINDOW: DWORD = 1442; +pub const ERROR_INVALID_GW_COMMAND: DWORD = 1443; +pub const ERROR_INVALID_THREAD_ID: DWORD = 1444; +pub const ERROR_NON_MDICHILD_WINDOW: DWORD = 1445; +pub const ERROR_POPUP_ALREADY_ACTIVE: DWORD = 1446; +pub const ERROR_NO_SCROLLBARS: DWORD = 1447; +pub const ERROR_INVALID_SCROLLBAR_RANGE: DWORD = 1448; +pub const ERROR_INVALID_SHOWWIN_COMMAND: DWORD = 1449; +pub const ERROR_NO_SYSTEM_RESOURCES: DWORD = 1450; +pub const ERROR_NONPAGED_SYSTEM_RESOURCES: DWORD = 1451; +pub const ERROR_PAGED_SYSTEM_RESOURCES: DWORD = 1452; +pub const ERROR_WORKING_SET_QUOTA: DWORD = 1453; +pub const ERROR_PAGEFILE_QUOTA: DWORD = 1454; +pub const ERROR_COMMITMENT_LIMIT: DWORD = 1455; +pub const ERROR_MENU_ITEM_NOT_FOUND: DWORD = 1456; +pub const ERROR_INVALID_KEYBOARD_HANDLE: DWORD = 1457; +pub const ERROR_HOOK_TYPE_NOT_ALLOWED: DWORD = 1458; +pub const ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION: DWORD = 1459; +pub const ERROR_TIMEOUT: DWORD = 1460; +pub const ERROR_INVALID_MONITOR_HANDLE: DWORD = 1461; +pub const ERROR_INCORRECT_SIZE: DWORD = 1462; +pub const ERROR_SYMLINK_CLASS_DISABLED: DWORD = 1463; +pub const ERROR_SYMLINK_NOT_SUPPORTED: DWORD = 1464; +pub const ERROR_XML_PARSE_ERROR: DWORD = 1465; +pub const ERROR_XMLDSIG_ERROR: DWORD = 1466; +pub const ERROR_RESTART_APPLICATION: DWORD = 1467; +pub const ERROR_WRONG_COMPARTMENT: DWORD = 1468; +pub const ERROR_AUTHIP_FAILURE: DWORD = 1469; +pub const ERROR_NO_NVRAM_RESOURCES: DWORD = 1470; +pub const ERROR_NOT_GUI_PROCESS: DWORD = 1471; +pub const ERROR_EVENTLOG_FILE_CORRUPT: DWORD = 1500; +pub const ERROR_EVENTLOG_CANT_START: DWORD = 1501; +pub const ERROR_LOG_FILE_FULL: DWORD = 1502; +pub const ERROR_EVENTLOG_FILE_CHANGED: DWORD = 1503; +pub const ERROR_INSTALL_SERVICE_FAILURE: DWORD = 1601; +pub const ERROR_INSTALL_USEREXIT: DWORD = 1602; +pub const ERROR_INSTALL_FAILURE: DWORD = 1603; +pub const ERROR_INSTALL_SUSPEND: DWORD = 1604; +pub const ERROR_UNKNOWN_PRODUCT: DWORD = 1605; +pub const ERROR_UNKNOWN_FEATURE: DWORD = 1606; +pub const ERROR_UNKNOWN_COMPONENT: DWORD = 1607; +pub const ERROR_UNKNOWN_PROPERTY: DWORD = 1608; +pub const ERROR_INVALID_HANDLE_STATE: DWORD = 1609; +pub const ERROR_BAD_CONFIGURATION: DWORD = 1610; +pub const ERROR_INDEX_ABSENT: DWORD = 1611; +pub const ERROR_INSTALL_SOURCE_ABSENT: DWORD = 1612; +pub const ERROR_INSTALL_PACKAGE_VERSION: DWORD = 1613; +pub const ERROR_PRODUCT_UNINSTALLED: DWORD = 1614; +pub const ERROR_BAD_QUERY_SYNTAX: DWORD = 1615; +pub const ERROR_INVALID_FIELD: DWORD = 1616; +pub const ERROR_DEVICE_REMOVED: DWORD = 1617; +pub const ERROR_INSTALL_ALREADY_RUNNING: DWORD = 1618; +pub const ERROR_INSTALL_PACKAGE_OPEN_FAILED: DWORD = 1619; +pub const ERROR_INSTALL_PACKAGE_INVALID: DWORD = 1620; +pub const ERROR_INSTALL_UI_FAILURE: DWORD = 1621; +pub const ERROR_INSTALL_LOG_FAILURE: DWORD = 1622; +pub const ERROR_INSTALL_LANGUAGE_UNSUPPORTED: DWORD = 1623; +pub const ERROR_INSTALL_TRANSFORM_FAILURE: DWORD = 1624; +pub const ERROR_INSTALL_PACKAGE_REJECTED: DWORD = 1625; +pub const ERROR_FUNCTION_NOT_CALLED: DWORD = 1626; +pub const ERROR_FUNCTION_FAILED: DWORD = 1627; +pub const ERROR_INVALID_TABLE: DWORD = 1628; +pub const ERROR_DATATYPE_MISMATCH: DWORD = 1629; +pub const ERROR_UNSUPPORTED_TYPE: DWORD = 1630; +pub const ERROR_CREATE_FAILED: DWORD = 1631; +pub const ERROR_INSTALL_TEMP_UNWRITABLE: DWORD = 1632; +pub const ERROR_INSTALL_PLATFORM_UNSUPPORTED: DWORD = 1633; +pub const ERROR_INSTALL_NOTUSED: DWORD = 1634; +pub const ERROR_PATCH_PACKAGE_OPEN_FAILED: DWORD = 1635; +pub const ERROR_PATCH_PACKAGE_INVALID: DWORD = 1636; +pub const ERROR_PATCH_PACKAGE_UNSUPPORTED: DWORD = 1637; +pub const ERROR_PRODUCT_VERSION: DWORD = 1638; +pub const ERROR_INVALID_COMMAND_LINE: DWORD = 1639; +pub const ERROR_INSTALL_REMOTE_DISALLOWED: DWORD = 1640; +pub const ERROR_SUCCESS_REBOOT_INITIATED: DWORD = 1641; +pub const ERROR_PATCH_TARGET_NOT_FOUND: DWORD = 1642; +pub const ERROR_PATCH_PACKAGE_REJECTED: DWORD = 1643; +pub const ERROR_INSTALL_TRANSFORM_REJECTED: DWORD = 1644; +pub const ERROR_INSTALL_REMOTE_PROHIBITED: DWORD = 1645; +pub const ERROR_INVALID_USER_BUFFER: DWORD = 1784; +pub const ERROR_UNRECOGNIZED_MEDIA: DWORD = 1785; +pub const ERROR_NO_TRUST_LSA_SECRET: DWORD = 1786; +pub const ERROR_NO_TRUST_SAM_ACCOUNT: DWORD = 1787; +pub const ERROR_TRUSTED_DOMAIN_FAILURE: DWORD = 1788; +pub const ERROR_TRUSTED_RELATIONSHIP_FAILURE: DWORD = 1789; +pub const ERROR_TRUST_FAILURE: DWORD = 1790; +pub const ERROR_NETLOGON_NOT_STARTED: DWORD = 1792; +pub const ERROR_ACCOUNT_EXPIRED: DWORD = 1793; +pub const ERROR_REDIRECTOR_HAS_OPEN_HANDLES: DWORD = 1794; +pub const ERROR_PRINTER_DRIVER_ALREADY_INSTALLED: DWORD = 1795; +pub const ERROR_UNKNOWN_PORT: DWORD = 1796; +pub const ERROR_UNKNOWN_PRINTER_DRIVER: DWORD = 1797; +pub const ERROR_UNKNOWN_PRINTPROCESSOR: DWORD = 1798; +pub const ERROR_INVALID_SEPARATOR_FILE: DWORD = 1799; +pub const ERROR_INVALID_PRIORITY: DWORD = 1800; +pub const ERROR_INVALID_PRINTER_NAME: DWORD = 1801; +pub const ERROR_PRINTER_ALREADY_EXISTS: DWORD = 1802; +pub const ERROR_INVALID_PRINTER_COMMAND: DWORD = 1803; +pub const ERROR_INVALID_DATATYPE: DWORD = 1804; +pub const ERROR_INVALID_ENVIRONMENT: DWORD = 1805; +pub const ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT: DWORD = 1807; +pub const ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT: DWORD = 1808; +pub const ERROR_NOLOGON_SERVER_TRUST_ACCOUNT: DWORD = 1809; +pub const ERROR_DOMAIN_TRUST_INCONSISTENT: DWORD = 1810; +pub const ERROR_SERVER_HAS_OPEN_HANDLES: DWORD = 1811; +pub const ERROR_RESOURCE_DATA_NOT_FOUND: DWORD = 1812; +pub const ERROR_RESOURCE_TYPE_NOT_FOUND: DWORD = 1813; +pub const ERROR_RESOURCE_NAME_NOT_FOUND: DWORD = 1814; +pub const ERROR_RESOURCE_LANG_NOT_FOUND: DWORD = 1815; +pub const ERROR_NOT_ENOUGH_QUOTA: DWORD = 1816; +pub const ERROR_INVALID_TIME: DWORD = 1901; +pub const ERROR_INVALID_FORM_NAME: DWORD = 1902; +pub const ERROR_INVALID_FORM_SIZE: DWORD = 1903; +pub const ERROR_ALREADY_WAITING: DWORD = 1904; +pub const ERROR_PRINTER_DELETED: DWORD = 1905; +pub const ERROR_INVALID_PRINTER_STATE: DWORD = 1906; +pub const ERROR_PASSWORD_MUST_CHANGE: DWORD = 1907; +pub const ERROR_DOMAIN_CONTROLLER_NOT_FOUND: DWORD = 1908; +pub const ERROR_ACCOUNT_LOCKED_OUT: DWORD = 1909; +pub const ERROR_NO_SITENAME: DWORD = 1919; +pub const ERROR_CANT_ACCESS_FILE: DWORD = 1920; +pub const ERROR_CANT_RESOLVE_FILENAME: DWORD = 1921; +pub const ERROR_KM_DRIVER_BLOCKED: DWORD = 1930; +pub const ERROR_CONTEXT_EXPIRED: DWORD = 1931; +pub const ERROR_PER_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1932; +pub const ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED: DWORD = 1933; +pub const ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED: DWORD = 1934; +pub const ERROR_AUTHENTICATION_FIREWALL_FAILED: DWORD = 1935; +pub const ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED: DWORD = 1936; +pub const ERROR_INVALID_PIXEL_FORMAT: DWORD = 2000; +pub const ERROR_BAD_DRIVER: DWORD = 2001; +pub const ERROR_INVALID_WINDOW_STYLE: DWORD = 2002; +pub const ERROR_METAFILE_NOT_SUPPORTED: DWORD = 2003; +pub const ERROR_TRANSFORM_NOT_SUPPORTED: DWORD = 2004; +pub const ERROR_CLIPPING_NOT_SUPPORTED: DWORD = 2005; +pub const ERROR_INVALID_CMM: DWORD = 2010; +pub const ERROR_INVALID_PROFILE: DWORD = 2011; +pub const ERROR_TAG_NOT_FOUND: DWORD = 2012; +pub const ERROR_TAG_NOT_PRESENT: DWORD = 2013; +pub const ERROR_DUPLICATE_TAG: DWORD = 2014; +pub const ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE: DWORD = 2015; +pub const ERROR_PROFILE_NOT_FOUND: DWORD = 2016; +pub const ERROR_INVALID_COLORSPACE: DWORD = 2017; +pub const ERROR_ICM_NOT_ENABLED: DWORD = 2018; +pub const ERROR_DELETING_ICM_XFORM: DWORD = 2019; +pub const ERROR_INVALID_TRANSFORM: DWORD = 2020; +pub const ERROR_COLORSPACE_MISMATCH: DWORD = 2021; +pub const ERROR_INVALID_COLORINDEX: DWORD = 2022; +pub const ERROR_CONNECTED_OTHER_PASSWORD: DWORD = 2108; +pub const ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT: DWORD = 2109; +pub const ERROR_BAD_USERNAME: DWORD = 2202; +pub const ERROR_NOT_CONNECTED: DWORD = 2250; +pub const ERROR_OPEN_FILES: DWORD = 2401; +pub const ERROR_ACTIVE_CONNECTIONS: DWORD = 2402; +pub const ERROR_DEVICE_IN_USE: DWORD = 2404; +pub const ERROR_UNKNOWN_PRINT_MONITOR: DWORD = 3000; +pub const ERROR_PRINTER_DRIVER_IN_USE: DWORD = 3001; +pub const ERROR_SPOOL_FILE_NOT_FOUND: DWORD = 3002; +pub const ERROR_SPL_NO_STARTDOC: DWORD = 3003; +pub const ERROR_SPL_NO_ADDJOB: DWORD = 3004; +pub const ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED: DWORD = 3005; +pub const ERROR_PRINT_MONITOR_ALREADY_INSTALLED: DWORD = 3006; +pub const ERROR_INVALID_PRINT_MONITOR: DWORD = 3007; +pub const ERROR_PRINT_MONITOR_IN_USE: DWORD = 3008; +pub const ERROR_PRINTER_HAS_JOBS_QUEUED: DWORD = 3009; +pub const ERROR_SUCCESS_REBOOT_REQUIRED: DWORD = 3010; +pub const ERROR_SUCCESS_RESTART_REQUIRED: DWORD = 3011; +pub const ERROR_PRINTER_NOT_FOUND: DWORD = 3012; +pub const ERROR_PRINTER_DRIVER_WARNED: DWORD = 3013; +pub const ERROR_PRINTER_DRIVER_BLOCKED: DWORD = 3014; +pub const ERROR_WINS_INTERNAL: DWORD = 4000; +pub const ERROR_CAN_NOT_DEL_LOCAL_WINS: DWORD = 4001; +pub const ERROR_STATIC_INIT: DWORD = 4002; +pub const ERROR_INC_BACKUP: DWORD = 4003; +pub const ERROR_FULL_BACKUP: DWORD = 4004; +pub const ERROR_REC_NON_EXISTENT: DWORD = 4005; +pub const ERROR_RPL_NOT_ALLOWED: DWORD = 4006; +pub const ERROR_DHCP_ADDRESS_CONFLICT: DWORD = 4100; +pub const ERROR_WMI_GUID_NOT_FOUND: DWORD = 4200; +pub const ERROR_WMI_INSTANCE_NOT_FOUND: DWORD = 4201; +pub const ERROR_WMI_ITEMID_NOT_FOUND: DWORD = 4202; +pub const ERROR_WMI_TRY_AGAIN: DWORD = 4203; +pub const ERROR_WMI_DP_NOT_FOUND: DWORD = 4204; +pub const ERROR_WMI_UNRESOLVED_INSTANCE_REF: DWORD = 4205; +pub const ERROR_WMI_ALREADY_ENABLED: DWORD = 4206; +pub const ERROR_WMI_GUID_DISCONNECTED: DWORD = 4207; +pub const ERROR_WMI_SERVER_UNAVAILABLE: DWORD = 4208; +pub const ERROR_WMI_DP_FAILED: DWORD = 4209; +pub const ERROR_WMI_INVALID_MOF: DWORD = 4210; +pub const ERROR_WMI_INVALID_REGINFO: DWORD = 4211; +pub const ERROR_WMI_ALREADY_DISABLED: DWORD = 4212; +pub const ERROR_WMI_READ_ONLY: DWORD = 4213; +pub const ERROR_WMI_SET_FAILURE: DWORD = 4214; +pub const ERROR_INVALID_MEDIA: DWORD = 4300; +pub const ERROR_INVALID_LIBRARY: DWORD = 4301; +pub const ERROR_INVALID_MEDIA_POOL: DWORD = 4302; +pub const ERROR_DRIVE_MEDIA_MISMATCH: DWORD = 4303; +pub const ERROR_MEDIA_OFFLINE: DWORD = 4304; +pub const ERROR_LIBRARY_OFFLINE: DWORD = 4305; +pub const ERROR_EMPTY: DWORD = 4306; +pub const ERROR_NOT_EMPTY: DWORD = 4307; +pub const ERROR_MEDIA_UNAVAILABLE: DWORD = 4308; +pub const ERROR_RESOURCE_DISABLED: DWORD = 4309; +pub const ERROR_INVALID_CLEANER: DWORD = 4310; +pub const ERROR_UNABLE_TO_CLEAN: DWORD = 4311; +pub const ERROR_OBJECT_NOT_FOUND: DWORD = 4312; +pub const ERROR_DATABASE_FAILURE: DWORD = 4313; +pub const ERROR_DATABASE_FULL: DWORD = 4314; +pub const ERROR_MEDIA_INCOMPATIBLE: DWORD = 4315; +pub const ERROR_RESOURCE_NOT_PRESENT: DWORD = 4316; +pub const ERROR_INVALID_OPERATION: DWORD = 4317; +pub const ERROR_MEDIA_NOT_AVAILABLE: DWORD = 4318; +pub const ERROR_DEVICE_NOT_AVAILABLE: DWORD = 4319; +pub const ERROR_REQUEST_REFUSED: DWORD = 4320; +pub const ERROR_INVALID_DRIVE_OBJECT: DWORD = 4321; +pub const ERROR_LIBRARY_FULL: DWORD = 4322; +pub const ERROR_MEDIUM_NOT_ACCESSIBLE: DWORD = 4323; +pub const ERROR_UNABLE_TO_LOAD_MEDIUM: DWORD = 4324; +pub const ERROR_UNABLE_TO_INVENTORY_DRIVE: DWORD = 4325; +pub const ERROR_UNABLE_TO_INVENTORY_SLOT: DWORD = 4326; +pub const ERROR_UNABLE_TO_INVENTORY_TRANSPORT: DWORD = 4327; +pub const ERROR_TRANSPORT_FULL: DWORD = 4328; +pub const ERROR_CONTROLLING_IEPORT: DWORD = 4329; +pub const ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA: DWORD = 4330; +pub const ERROR_CLEANER_SLOT_SET: DWORD = 4331; +pub const ERROR_CLEANER_SLOT_NOT_SET: DWORD = 4332; +pub const ERROR_CLEANER_CARTRIDGE_SPENT: DWORD = 4333; +pub const ERROR_UNEXPECTED_OMID: DWORD = 4334; +pub const ERROR_CANT_DELETE_LAST_ITEM: DWORD = 4335; +pub const ERROR_MESSAGE_EXCEEDS_MAX_SIZE: DWORD = 4336; +pub const ERROR_VOLUME_CONTAINS_SYS_FILES: DWORD = 4337; +pub const ERROR_INDIGENOUS_TYPE: DWORD = 4338; +pub const ERROR_NO_SUPPORTING_DRIVES: DWORD = 4339; +pub const ERROR_CLEANER_CARTRIDGE_INSTALLED: DWORD = 4340; +pub const ERROR_IEPORT_FULL: DWORD = 4341; +pub const ERROR_FILE_OFFLINE: DWORD = 4350; +pub const ERROR_REMOTE_STORAGE_NOT_ACTIVE: DWORD = 4351; +pub const ERROR_REMOTE_STORAGE_MEDIA_ERROR: DWORD = 4352; +pub const ERROR_NOT_A_REPARSE_POINT: DWORD = 4390; +pub const ERROR_REPARSE_ATTRIBUTE_CONFLICT: DWORD = 4391; +pub const ERROR_INVALID_REPARSE_DATA: DWORD = 4392; +pub const ERROR_REPARSE_TAG_INVALID: DWORD = 4393; +pub const ERROR_REPARSE_TAG_MISMATCH: DWORD = 4394; +pub const ERROR_VOLUME_NOT_SIS_ENABLED: DWORD = 4500; +pub const ERROR_DEPENDENT_RESOURCE_EXISTS: DWORD = 5001; +pub const ERROR_DEPENDENCY_NOT_FOUND: DWORD = 5002; +pub const ERROR_DEPENDENCY_ALREADY_EXISTS: DWORD = 5003; +pub const ERROR_RESOURCE_NOT_ONLINE: DWORD = 5004; +pub const ERROR_HOST_NODE_NOT_AVAILABLE: DWORD = 5005; +pub const ERROR_RESOURCE_NOT_AVAILABLE: DWORD = 5006; +pub const ERROR_RESOURCE_NOT_FOUND: DWORD = 5007; +pub const ERROR_SHUTDOWN_CLUSTER: DWORD = 5008; +pub const ERROR_CANT_EVICT_ACTIVE_NODE: DWORD = 5009; +pub const ERROR_OBJECT_ALREADY_EXISTS: DWORD = 5010; +pub const ERROR_OBJECT_IN_LIST: DWORD = 5011; +pub const ERROR_GROUP_NOT_AVAILABLE: DWORD = 5012; +pub const ERROR_GROUP_NOT_FOUND: DWORD = 5013; +pub const ERROR_GROUP_NOT_ONLINE: DWORD = 5014; +pub const ERROR_HOST_NODE_NOT_RESOURCE_OWNER: DWORD = 5015; +pub const ERROR_HOST_NODE_NOT_GROUP_OWNER: DWORD = 5016; +pub const ERROR_RESMON_CREATE_FAILED: DWORD = 5017; +pub const ERROR_RESMON_ONLINE_FAILED: DWORD = 5018; +pub const ERROR_RESOURCE_ONLINE: DWORD = 5019; +pub const ERROR_QUORUM_RESOURCE: DWORD = 5020; +pub const ERROR_NOT_QUORUM_CAPABLE: DWORD = 5021; +pub const ERROR_CLUSTER_SHUTTING_DOWN: DWORD = 5022; +pub const ERROR_INVALID_STATE: DWORD = 5023; +pub const ERROR_RESOURCE_PROPERTIES_STORED: DWORD = 5024; +pub const ERROR_NOT_QUORUM_CLASS: DWORD = 5025; +pub const ERROR_CORE_RESOURCE: DWORD = 5026; +pub const ERROR_QUORUM_RESOURCE_ONLINE_FAILED: DWORD = 5027; +pub const ERROR_QUORUMLOG_OPEN_FAILED: DWORD = 5028; +pub const ERROR_CLUSTERLOG_CORRUPT: DWORD = 5029; +pub const ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE: DWORD = 5030; +pub const ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE: DWORD = 5031; +pub const ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND: DWORD = 5032; +pub const ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE: DWORD = 5033; +pub const ERROR_QUORUM_OWNER_ALIVE: DWORD = 5034; +pub const ERROR_NETWORK_NOT_AVAILABLE: DWORD = 5035; +pub const ERROR_NODE_NOT_AVAILABLE: DWORD = 5036; +pub const ERROR_ALL_NODES_NOT_AVAILABLE: DWORD = 5037; +pub const ERROR_RESOURCE_FAILED: DWORD = 5038; +pub const ERROR_CLUSTER_INVALID_NODE: DWORD = 5039; +pub const ERROR_CLUSTER_NODE_EXISTS: DWORD = 5040; +pub const ERROR_CLUSTER_JOIN_IN_PROGRESS: DWORD = 5041; +pub const ERROR_CLUSTER_NODE_NOT_FOUND: DWORD = 5042; +pub const ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND: DWORD = 5043; +pub const ERROR_CLUSTER_NETWORK_EXISTS: DWORD = 5044; +pub const ERROR_CLUSTER_NETWORK_NOT_FOUND: DWORD = 5045; +pub const ERROR_CLUSTER_NETINTERFACE_EXISTS: DWORD = 5046; +pub const ERROR_CLUSTER_NETINTERFACE_NOT_FOUND: DWORD = 5047; +pub const ERROR_CLUSTER_INVALID_REQUEST: DWORD = 5048; +pub const ERROR_CLUSTER_INVALID_NETWORK_PROVIDER: DWORD = 5049; +pub const ERROR_CLUSTER_NODE_DOWN: DWORD = 5050; +pub const ERROR_CLUSTER_NODE_UNREACHABLE: DWORD = 5051; +pub const ERROR_CLUSTER_NODE_NOT_MEMBER: DWORD = 5052; +pub const ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS: DWORD = 5053; +pub const ERROR_CLUSTER_INVALID_NETWORK: DWORD = 5054; +pub const ERROR_CLUSTER_NODE_UP: DWORD = 5056; +pub const ERROR_CLUSTER_IPADDR_IN_USE: DWORD = 5057; +pub const ERROR_CLUSTER_NODE_NOT_PAUSED: DWORD = 5058; +pub const ERROR_CLUSTER_NO_SECURITY_CONTEXT: DWORD = 5059; +pub const ERROR_CLUSTER_NETWORK_NOT_INTERNAL: DWORD = 5060; +pub const ERROR_CLUSTER_NODE_ALREADY_UP: DWORD = 5061; +pub const ERROR_CLUSTER_NODE_ALREADY_DOWN: DWORD = 5062; +pub const ERROR_CLUSTER_NETWORK_ALREADY_ONLINE: DWORD = 5063; +pub const ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE: DWORD = 5064; +pub const ERROR_CLUSTER_NODE_ALREADY_MEMBER: DWORD = 5065; +pub const ERROR_CLUSTER_LAST_INTERNAL_NETWORK: DWORD = 5066; +pub const ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS: DWORD = 5067; +pub const ERROR_INVALID_OPERATION_ON_QUORUM: DWORD = 5068; +pub const ERROR_DEPENDENCY_NOT_ALLOWED: DWORD = 5069; +pub const ERROR_CLUSTER_NODE_PAUSED: DWORD = 5070; +pub const ERROR_NODE_CANT_HOST_RESOURCE: DWORD = 5071; +pub const ERROR_CLUSTER_NODE_NOT_READY: DWORD = 5072; +pub const ERROR_CLUSTER_NODE_SHUTTING_DOWN: DWORD = 5073; +pub const ERROR_CLUSTER_JOIN_ABORTED: DWORD = 5074; +pub const ERROR_CLUSTER_INCOMPATIBLE_VERSIONS: DWORD = 5075; +pub const ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED: DWORD = 5076; +pub const ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED: DWORD = 5077; +pub const ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND: DWORD = 5078; +pub const ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED: DWORD = 5079; +pub const ERROR_CLUSTER_RESNAME_NOT_FOUND: DWORD = 5080; +pub const ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED: DWORD = 5081; +pub const ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST: DWORD = 5082; +pub const ERROR_CLUSTER_DATABASE_SEQMISMATCH: DWORD = 5083; +pub const ERROR_RESMON_INVALID_STATE: DWORD = 5084; +pub const ERROR_CLUSTER_GUM_NOT_LOCKER: DWORD = 5085; +pub const ERROR_QUORUM_DISK_NOT_FOUND: DWORD = 5086; +pub const ERROR_DATABASE_BACKUP_CORRUPT: DWORD = 5087; +pub const ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT: DWORD = 5088; +pub const ERROR_RESOURCE_PROPERTY_UNCHANGEABLE: DWORD = 5089; +pub const ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE: DWORD = 5890; +pub const ERROR_CLUSTER_QUORUMLOG_NOT_FOUND: DWORD = 5891; +pub const ERROR_CLUSTER_MEMBERSHIP_HALT: DWORD = 5892; +pub const ERROR_CLUSTER_INSTANCE_ID_MISMATCH: DWORD = 5893; +pub const ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP: DWORD = 5894; +pub const ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH: DWORD = 5895; +pub const ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP: DWORD = 5896; +pub const ERROR_CLUSTER_PARAMETER_MISMATCH: DWORD = 5897; +pub const ERROR_NODE_CANNOT_BE_CLUSTERED: DWORD = 5898; +pub const ERROR_CLUSTER_WRONG_OS_VERSION: DWORD = 5899; +pub const ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME: DWORD = 5900; +pub const ERROR_CLUSCFG_ALREADY_COMMITTED: DWORD = 5901; +pub const ERROR_CLUSCFG_ROLLBACK_FAILED: DWORD = 5902; +pub const ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT: DWORD = 5903; +pub const ERROR_CLUSTER_OLD_VERSION: DWORD = 5904; +pub const ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME: DWORD = 5905; +pub const ERROR_ENCRYPTION_FAILED: DWORD = 6000; +pub const ERROR_DECRYPTION_FAILED: DWORD = 6001; +pub const ERROR_FILE_ENCRYPTED: DWORD = 6002; +pub const ERROR_NO_RECOVERY_POLICY: DWORD = 6003; +pub const ERROR_NO_EFS: DWORD = 6004; +pub const ERROR_WRONG_EFS: DWORD = 6005; +pub const ERROR_NO_USER_KEYS: DWORD = 6006; +pub const ERROR_FILE_NOT_ENCRYPTED: DWORD = 6007; +pub const ERROR_NOT_EXPORT_FORMAT: DWORD = 6008; +pub const ERROR_FILE_READ_ONLY: DWORD = 6009; +pub const ERROR_DIR_EFS_DISALLOWED: DWORD = 6010; +pub const ERROR_EFS_SERVER_NOT_TRUSTED: DWORD = 6011; +pub const ERROR_BAD_RECOVERY_POLICY: DWORD = 6012; +pub const ERROR_EFS_ALG_BLOB_TOO_BIG: DWORD = 6013; +pub const ERROR_VOLUME_NOT_SUPPORT_EFS: DWORD = 6014; +pub const ERROR_EFS_DISABLED: DWORD = 6015; +pub const ERROR_EFS_VERSION_NOT_SUPPORT: DWORD = 6016; +pub const ERROR_NO_BROWSER_SERVERS_FOUND: DWORD = 6118; +pub const ERROR_CTX_WINSTATION_NAME_INVALID: DWORD = 7001; +pub const ERROR_CTX_INVALID_PD: DWORD = 7002; +pub const ERROR_CTX_PD_NOT_FOUND: DWORD = 7003; +pub const ERROR_CTX_WD_NOT_FOUND: DWORD = 7004; +pub const ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY: DWORD = 7005; +pub const ERROR_CTX_SERVICE_NAME_COLLISION: DWORD = 7006; +pub const ERROR_CTX_CLOSE_PENDING: DWORD = 7007; +pub const ERROR_CTX_NO_OUTBUF: DWORD = 7008; +pub const ERROR_CTX_MODEM_INF_NOT_FOUND: DWORD = 7009; +pub const ERROR_CTX_INVALID_MODEMNAME: DWORD = 7010; +pub const ERROR_CTX_MODEM_RESPONSE_ERROR: DWORD = 7011; +pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; +pub const ERROR_CTX_MODEM_RESPONSE_NO_CARRIER: DWORD = 7013; +pub const ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE: DWORD = 7014; +pub const ERROR_CTX_MODEM_RESPONSE_BUSY: DWORD = 7015; +pub const ERROR_CTX_MODEM_RESPONSE_VOICE: DWORD = 7016; +pub const ERROR_CTX_TD_ERROR: DWORD = 7017; +pub const ERROR_CTX_WINSTATION_NOT_FOUND: DWORD = 7022; +pub const ERROR_CTX_WINSTATION_ALREADY_EXISTS: DWORD = 7023; +pub const ERROR_CTX_WINSTATION_BUSY: DWORD = 7024; +pub const ERROR_CTX_BAD_VIDEO_MODE: DWORD = 7025; +pub const ERROR_CTX_GRAPHICS_INVALID: DWORD = 7035; +pub const ERROR_CTX_LOGON_DISABLED: DWORD = 7037; +pub const ERROR_CTX_NOT_CONSOLE: DWORD = 7038; +pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; +pub const ERROR_CTX_CONSOLE_DISCONNECT: DWORD = 7041; +pub const ERROR_CTX_CONSOLE_CONNECT: DWORD = 7042; +pub const ERROR_CTX_SHADOW_DENIED: DWORD = 7044; +pub const ERROR_CTX_WINSTATION_ACCESS_DENIED: DWORD = 7045; +pub const ERROR_CTX_INVALID_WD: DWORD = 7049; +pub const ERROR_CTX_SHADOW_INVALID: DWORD = 7050; +pub const ERROR_CTX_SHADOW_DISABLED: DWORD = 7051; +pub const ERROR_CTX_CLIENT_LICENSE_IN_USE: DWORD = 7052; +pub const ERROR_CTX_CLIENT_LICENSE_NOT_SET: DWORD = 7053; +pub const ERROR_CTX_LICENSE_NOT_AVAILABLE: DWORD = 7054; +pub const ERROR_CTX_LICENSE_CLIENT_INVALID: DWORD = 7055; +pub const ERROR_CTX_LICENSE_EXPIRED: DWORD = 7056; +pub const ERROR_CTX_SHADOW_NOT_RUNNING: DWORD = 7057; +pub const ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE: DWORD = 7058; +pub const ERROR_ACTIVATION_COUNT_EXCEEDED: DWORD = 7059; +pub const ERROR_DS_NOT_INSTALLED: DWORD = 8200; +pub const ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY: DWORD = 8201; +pub const ERROR_DS_NO_ATTRIBUTE_OR_VALUE: DWORD = 8202; +pub const ERROR_DS_INVALID_ATTRIBUTE_SYNTAX: DWORD = 8203; +pub const ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED: DWORD = 8204; +pub const ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS: DWORD = 8205; +pub const ERROR_DS_BUSY: DWORD = 8206; +pub const ERROR_DS_UNAVAILABLE: DWORD = 8207; +pub const ERROR_DS_NO_RIDS_ALLOCATED: DWORD = 8208; +pub const ERROR_DS_NO_MORE_RIDS: DWORD = 8209; +pub const ERROR_DS_INCORRECT_ROLE_OWNER: DWORD = 8210; +pub const ERROR_DS_RIDMGR_INIT_ERROR: DWORD = 8211; +pub const ERROR_DS_OBJ_CLASS_VIOLATION: DWORD = 8212; +pub const ERROR_DS_CANT_ON_NON_LEAF: DWORD = 8213; +pub const ERROR_DS_CANT_ON_RDN: DWORD = 8214; +pub const ERROR_DS_CANT_MOD_OBJ_CLASS: DWORD = 8215; +pub const ERROR_DS_CROSS_DOM_MOVE_ERROR: DWORD = 8216; +pub const ERROR_DS_GC_NOT_AVAILABLE: DWORD = 8217; +pub const ERROR_SHARED_POLICY: DWORD = 8218; +pub const ERROR_POLICY_OBJECT_NOT_FOUND: DWORD = 8219; +pub const ERROR_POLICY_ONLY_IN_DS: DWORD = 8220; +pub const ERROR_PROMOTION_ACTIVE: DWORD = 8221; +pub const ERROR_NO_PROMOTION_ACTIVE: DWORD = 8222; +pub const ERROR_DS_OPERATIONS_ERROR: DWORD = 8224; +pub const ERROR_DS_PROTOCOL_ERROR: DWORD = 8225; +pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; +pub const ERROR_DS_SIZELIMIT_EXCEEDED: DWORD = 8227; +pub const ERROR_DS_ADMIN_LIMIT_EXCEEDED: DWORD = 8228; +pub const ERROR_DS_COMPARE_FALSE: DWORD = 8229; +pub const ERROR_DS_COMPARE_TRUE: DWORD = 8230; +pub const ERROR_DS_AUTH_METHOD_NOT_SUPPORTED: DWORD = 8231; +pub const ERROR_DS_STRONG_AUTH_REQUIRED: DWORD = 8232; +pub const ERROR_DS_INAPPROPRIATE_AUTH: DWORD = 8233; +pub const ERROR_DS_AUTH_UNKNOWN: DWORD = 8234; +pub const ERROR_DS_REFERRAL: DWORD = 8235; +pub const ERROR_DS_UNAVAILABLE_CRIT_EXTENSION: DWORD = 8236; +pub const ERROR_DS_CONFIDENTIALITY_REQUIRED: DWORD = 8237; +pub const ERROR_DS_INAPPROPRIATE_MATCHING: DWORD = 8238; +pub const ERROR_DS_CONSTRAINT_VIOLATION: DWORD = 8239; +pub const ERROR_DS_NO_SUCH_OBJECT: DWORD = 8240; +pub const ERROR_DS_ALIAS_PROBLEM: DWORD = 8241; +pub const ERROR_DS_INVALID_DN_SYNTAX: DWORD = 8242; +pub const ERROR_DS_IS_LEAF: DWORD = 8243; +pub const ERROR_DS_ALIAS_DEREF_PROBLEM: DWORD = 8244; +pub const ERROR_DS_UNWILLING_TO_PERFORM: DWORD = 8245; +pub const ERROR_DS_LOOP_DETECT: DWORD = 8246; +pub const ERROR_DS_NAMING_VIOLATION: DWORD = 8247; +pub const ERROR_DS_OBJECT_RESULTS_TOO_LARGE: DWORD = 8248; +pub const ERROR_DS_AFFECTS_MULTIPLE_DSAS: DWORD = 8249; +pub const ERROR_DS_SERVER_DOWN: DWORD = 8250; +pub const ERROR_DS_LOCAL_ERROR: DWORD = 8251; +pub const ERROR_DS_ENCODING_ERROR: DWORD = 8252; +pub const ERROR_DS_DECODING_ERROR: DWORD = 8253; +pub const ERROR_DS_FILTER_UNKNOWN: DWORD = 8254; +pub const ERROR_DS_PARAM_ERROR: DWORD = 8255; +pub const ERROR_DS_NOT_SUPPORTED: DWORD = 8256; +pub const ERROR_DS_NO_RESULTS_RETURNED: DWORD = 8257; +pub const ERROR_DS_CONTROL_NOT_FOUND: DWORD = 8258; +pub const ERROR_DS_CLIENT_LOOP: DWORD = 8259; +pub const ERROR_DS_REFERRAL_LIMIT_EXCEEDED: DWORD = 8260; +pub const ERROR_DS_SORT_CONTROL_MISSING: DWORD = 8261; +pub const ERROR_DS_OFFSET_RANGE_ERROR: DWORD = 8262; +pub const ERROR_DS_ROOT_MUST_BE_NC: DWORD = 8301; +pub const ERROR_DS_ADD_REPLICA_INHIBITED: DWORD = 8302; +pub const ERROR_DS_ATT_NOT_DEF_IN_SCHEMA: DWORD = 8303; +pub const ERROR_DS_MAX_OBJ_SIZE_EXCEEDED: DWORD = 8304; +pub const ERROR_DS_OBJ_STRING_NAME_EXISTS: DWORD = 8305; +pub const ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA: DWORD = 8306; +pub const ERROR_DS_RDN_DOESNT_MATCH_SCHEMA: DWORD = 8307; +pub const ERROR_DS_NO_REQUESTED_ATTS_FOUND: DWORD = 8308; +pub const ERROR_DS_USER_BUFFER_TO_SMALL: DWORD = 8309; +pub const ERROR_DS_ATT_IS_NOT_ON_OBJ: DWORD = 8310; +pub const ERROR_DS_ILLEGAL_MOD_OPERATION: DWORD = 8311; +pub const ERROR_DS_OBJ_TOO_LARGE: DWORD = 8312; +pub const ERROR_DS_BAD_INSTANCE_TYPE: DWORD = 8313; +pub const ERROR_DS_MASTERDSA_REQUIRED: DWORD = 8314; +pub const ERROR_DS_OBJECT_CLASS_REQUIRED: DWORD = 8315; +pub const ERROR_DS_MISSING_REQUIRED_ATT: DWORD = 8316; +pub const ERROR_DS_ATT_NOT_DEF_FOR_CLASS: DWORD = 8317; +pub const ERROR_DS_ATT_ALREADY_EXISTS: DWORD = 8318; +pub const ERROR_DS_CANT_ADD_ATT_VALUES: DWORD = 8320; +pub const ERROR_DS_SINGLE_VALUE_CONSTRAINT: DWORD = 8321; +pub const ERROR_DS_RANGE_CONSTRAINT: DWORD = 8322; +pub const ERROR_DS_ATT_VAL_ALREADY_EXISTS: DWORD = 8323; +pub const ERROR_DS_CANT_REM_MISSING_ATT: DWORD = 8324; +pub const ERROR_DS_CANT_REM_MISSING_ATT_VAL: DWORD = 8325; +pub const ERROR_DS_ROOT_CANT_BE_SUBREF: DWORD = 8326; +pub const ERROR_DS_NO_CHAINING: DWORD = 8327; +pub const ERROR_DS_NO_CHAINED_EVAL: DWORD = 8328; +pub const ERROR_DS_NO_PARENT_OBJECT: DWORD = 8329; +pub const ERROR_DS_PARENT_IS_AN_ALIAS: DWORD = 8330; +pub const ERROR_DS_CANT_MIX_MASTER_AND_REPS: DWORD = 8331; +pub const ERROR_DS_CHILDREN_EXIST: DWORD = 8332; +pub const ERROR_DS_OBJ_NOT_FOUND: DWORD = 8333; +pub const ERROR_DS_ALIASED_OBJ_MISSING: DWORD = 8334; +pub const ERROR_DS_BAD_NAME_SYNTAX: DWORD = 8335; +pub const ERROR_DS_ALIAS_POINTS_TO_ALIAS: DWORD = 8336; +pub const ERROR_DS_CANT_DEREF_ALIAS: DWORD = 8337; +pub const ERROR_DS_OUT_OF_SCOPE: DWORD = 8338; +pub const ERROR_DS_OBJECT_BEING_REMOVED: DWORD = 8339; +pub const ERROR_DS_CANT_DELETE_DSA_OBJ: DWORD = 8340; +pub const ERROR_DS_GENERIC_ERROR: DWORD = 8341; +pub const ERROR_DS_DSA_MUST_BE_INT_MASTER: DWORD = 8342; +pub const ERROR_DS_CLASS_NOT_DSA: DWORD = 8343; +pub const ERROR_DS_INSUFF_ACCESS_RIGHTS: DWORD = 8344; +pub const ERROR_DS_ILLEGAL_SUPERIOR: DWORD = 8345; +pub const ERROR_DS_ATTRIBUTE_OWNED_BY_SAM: DWORD = 8346; +pub const ERROR_DS_NAME_TOO_MANY_PARTS: DWORD = 8347; +pub const ERROR_DS_NAME_TOO_LONG: DWORD = 8348; +pub const ERROR_DS_NAME_VALUE_TOO_LONG: DWORD = 8349; +pub const ERROR_DS_NAME_UNPARSEABLE: DWORD = 8350; +pub const ERROR_DS_NAME_TYPE_UNKNOWN: DWORD = 8351; +pub const ERROR_DS_NOT_AN_OBJECT: DWORD = 8352; +pub const ERROR_DS_SEC_DESC_TOO_SHORT: DWORD = 8353; +pub const ERROR_DS_SEC_DESC_INVALID: DWORD = 8354; +pub const ERROR_DS_NO_DELETED_NAME: DWORD = 8355; +pub const ERROR_DS_SUBREF_MUST_HAVE_PARENT: DWORD = 8356; +pub const ERROR_DS_NCNAME_MUST_BE_NC: DWORD = 8357; +pub const ERROR_DS_CANT_ADD_SYSTEM_ONLY: DWORD = 8358; +pub const ERROR_DS_CLASS_MUST_BE_CONCRETE: DWORD = 8359; +pub const ERROR_DS_INVALID_DMD: DWORD = 8360; +pub const ERROR_DS_OBJ_GUID_EXISTS: DWORD = 8361; +pub const ERROR_DS_NOT_ON_BACKLINK: DWORD = 8362; +pub const ERROR_DS_NO_CROSSREF_FOR_NC: DWORD = 8363; +pub const ERROR_DS_SHUTTING_DOWN: DWORD = 8364; +pub const ERROR_DS_UNKNOWN_OPERATION: DWORD = 8365; +pub const ERROR_DS_INVALID_ROLE_OWNER: DWORD = 8366; +pub const ERROR_DS_COULDNT_CONTACT_FSMO: DWORD = 8367; +pub const ERROR_DS_CROSS_NC_DN_RENAME: DWORD = 8368; +pub const ERROR_DS_CANT_MOD_SYSTEM_ONLY: DWORD = 8369; +pub const ERROR_DS_REPLICATOR_ONLY: DWORD = 8370; +pub const ERROR_DS_OBJ_CLASS_NOT_DEFINED: DWORD = 8371; +pub const ERROR_DS_OBJ_CLASS_NOT_SUBCLASS: DWORD = 8372; +pub const ERROR_DS_NAME_REFERENCE_INVALID: DWORD = 8373; +pub const ERROR_DS_CROSS_REF_EXISTS: DWORD = 8374; +pub const ERROR_DS_CANT_DEL_MASTER_CROSSREF: DWORD = 8375; +pub const ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD: DWORD = 8376; +pub const ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX: DWORD = 8377; +pub const ERROR_DS_DUP_RDN: DWORD = 8378; +pub const ERROR_DS_DUP_OID: DWORD = 8379; +pub const ERROR_DS_DUP_MAPI_ID: DWORD = 8380; +pub const ERROR_DS_DUP_SCHEMA_ID_GUID: DWORD = 8381; +pub const ERROR_DS_DUP_LDAP_DISPLAY_NAME: DWORD = 8382; +pub const ERROR_DS_SEMANTIC_ATT_TEST: DWORD = 8383; +pub const ERROR_DS_SYNTAX_MISMATCH: DWORD = 8384; +pub const ERROR_DS_EXISTS_IN_MUST_HAVE: DWORD = 8385; +pub const ERROR_DS_EXISTS_IN_MAY_HAVE: DWORD = 8386; +pub const ERROR_DS_NONEXISTENT_MAY_HAVE: DWORD = 8387; +pub const ERROR_DS_NONEXISTENT_MUST_HAVE: DWORD = 8388; +pub const ERROR_DS_AUX_CLS_TEST_FAIL: DWORD = 8389; +pub const ERROR_DS_NONEXISTENT_POSS_SUP: DWORD = 8390; +pub const ERROR_DS_SUB_CLS_TEST_FAIL: DWORD = 8391; +pub const ERROR_DS_BAD_RDN_ATT_ID_SYNTAX: DWORD = 8392; +pub const ERROR_DS_EXISTS_IN_AUX_CLS: DWORD = 8393; +pub const ERROR_DS_EXISTS_IN_SUB_CLS: DWORD = 8394; +pub const ERROR_DS_EXISTS_IN_POSS_SUP: DWORD = 8395; +pub const ERROR_DS_RECALCSCHEMA_FAILED: DWORD = 8396; +pub const ERROR_DS_TREE_DELETE_NOT_FINISHED: DWORD = 8397; +pub const ERROR_DS_CANT_DELETE: DWORD = 8398; +pub const ERROR_DS_ATT_SCHEMA_REQ_ID: DWORD = 8399; +pub const ERROR_DS_BAD_ATT_SCHEMA_SYNTAX: DWORD = 8400; +pub const ERROR_DS_CANT_CACHE_ATT: DWORD = 8401; +pub const ERROR_DS_CANT_CACHE_CLASS: DWORD = 8402; +pub const ERROR_DS_CANT_REMOVE_ATT_CACHE: DWORD = 8403; +pub const ERROR_DS_CANT_REMOVE_CLASS_CACHE: DWORD = 8404; +pub const ERROR_DS_CANT_RETRIEVE_DN: DWORD = 8405; +pub const ERROR_DS_MISSING_SUPREF: DWORD = 8406; +pub const ERROR_DS_CANT_RETRIEVE_INSTANCE: DWORD = 8407; +pub const ERROR_DS_CODE_INCONSISTENCY: DWORD = 8408; +pub const ERROR_DS_DATABASE_ERROR: DWORD = 8409; +pub const ERROR_DS_GOVERNSID_MISSING: DWORD = 8410; +pub const ERROR_DS_MISSING_EXPECTED_ATT: DWORD = 8411; +pub const ERROR_DS_NCNAME_MISSING_CR_REF: DWORD = 8412; +pub const ERROR_DS_SECURITY_CHECKING_ERROR: DWORD = 8413; +pub const ERROR_DS_SCHEMA_NOT_LOADED: DWORD = 8414; +pub const ERROR_DS_SCHEMA_ALLOC_FAILED: DWORD = 8415; +pub const ERROR_DS_ATT_SCHEMA_REQ_SYNTAX: DWORD = 8416; +pub const ERROR_DS_GCVERIFY_ERROR: DWORD = 8417; +pub const ERROR_DS_DRA_SCHEMA_MISMATCH: DWORD = 8418; +pub const ERROR_DS_CANT_FIND_DSA_OBJ: DWORD = 8419; +pub const ERROR_DS_CANT_FIND_EXPECTED_NC: DWORD = 8420; +pub const ERROR_DS_CANT_FIND_NC_IN_CACHE: DWORD = 8421; +pub const ERROR_DS_CANT_RETRIEVE_CHILD: DWORD = 8422; +pub const ERROR_DS_SECURITY_ILLEGAL_MODIFY: DWORD = 8423; +pub const ERROR_DS_CANT_REPLACE_HIDDEN_REC: DWORD = 8424; +pub const ERROR_DS_BAD_HIERARCHY_FILE: DWORD = 8425; +pub const ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED: DWORD = 8426; +pub const ERROR_DS_CONFIG_PARAM_MISSING: DWORD = 8427; +pub const ERROR_DS_COUNTING_AB_INDICES_FAILED: DWORD = 8428; +pub const ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED: DWORD = 8429; +pub const ERROR_DS_INTERNAL_FAILURE: DWORD = 8430; +pub const ERROR_DS_UNKNOWN_ERROR: DWORD = 8431; +pub const ERROR_DS_ROOT_REQUIRES_CLASS_TOP: DWORD = 8432; +pub const ERROR_DS_REFUSING_FSMO_ROLES: DWORD = 8433; +pub const ERROR_DS_MISSING_FSMO_SETTINGS: DWORD = 8434; +pub const ERROR_DS_UNABLE_TO_SURRENDER_ROLES: DWORD = 8435; +pub const ERROR_DS_DRA_GENERIC: DWORD = 8436; +pub const ERROR_DS_DRA_INVALID_PARAMETER: DWORD = 8437; +pub const ERROR_DS_DRA_BUSY: DWORD = 8438; +pub const ERROR_DS_DRA_BAD_DN: DWORD = 8439; +pub const ERROR_DS_DRA_BAD_NC: DWORD = 8440; +pub const ERROR_DS_DRA_DN_EXISTS: DWORD = 8441; +pub const ERROR_DS_DRA_INTERNAL_ERROR: DWORD = 8442; +pub const ERROR_DS_DRA_INCONSISTENT_DIT: DWORD = 8443; +pub const ERROR_DS_DRA_CONNECTION_FAILED: DWORD = 8444; +pub const ERROR_DS_DRA_BAD_INSTANCE_TYPE: DWORD = 8445; +pub const ERROR_DS_DRA_OUT_OF_MEM: DWORD = 8446; +pub const ERROR_DS_DRA_MAIL_PROBLEM: DWORD = 8447; +pub const ERROR_DS_DRA_REF_ALREADY_EXISTS: DWORD = 8448; +pub const ERROR_DS_DRA_REF_NOT_FOUND: DWORD = 8449; +pub const ERROR_DS_DRA_OBJ_IS_REP_SOURCE: DWORD = 8450; +pub const ERROR_DS_DRA_DB_ERROR: DWORD = 8451; +pub const ERROR_DS_DRA_NO_REPLICA: DWORD = 8452; +pub const ERROR_DS_DRA_ACCESS_DENIED: DWORD = 8453; +pub const ERROR_DS_DRA_NOT_SUPPORTED: DWORD = 8454; +pub const ERROR_DS_DRA_RPC_CANCELLED: DWORD = 8455; +pub const ERROR_DS_DRA_SOURCE_DISABLED: DWORD = 8456; +pub const ERROR_DS_DRA_SINK_DISABLED: DWORD = 8457; +pub const ERROR_DS_DRA_NAME_COLLISION: DWORD = 8458; +pub const ERROR_DS_DRA_SOURCE_REINSTALLED: DWORD = 8459; +pub const ERROR_DS_DRA_MISSING_PARENT: DWORD = 8460; +pub const ERROR_DS_DRA_PREEMPTED: DWORD = 8461; +pub const ERROR_DS_DRA_ABANDON_SYNC: DWORD = 8462; +pub const ERROR_DS_DRA_SHUTDOWN: DWORD = 8463; +pub const ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET: DWORD = 8464; +pub const ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA: DWORD = 8465; +pub const ERROR_DS_DRA_EXTN_CONNECTION_FAILED: DWORD = 8466; +pub const ERROR_DS_INSTALL_SCHEMA_MISMATCH: DWORD = 8467; +pub const ERROR_DS_DUP_LINK_ID: DWORD = 8468; +pub const ERROR_DS_NAME_ERROR_RESOLVING: DWORD = 8469; +pub const ERROR_DS_NAME_ERROR_NOT_FOUND: DWORD = 8470; +pub const ERROR_DS_NAME_ERROR_NOT_UNIQUE: DWORD = 8471; +pub const ERROR_DS_NAME_ERROR_NO_MAPPING: DWORD = 8472; +pub const ERROR_DS_NAME_ERROR_DOMAIN_ONLY: DWORD = 8473; +pub const ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING: DWORD = 8474; +pub const ERROR_DS_CONSTRUCTED_ATT_MOD: DWORD = 8475; +pub const ERROR_DS_WRONG_OM_OBJ_CLASS: DWORD = 8476; +pub const ERROR_DS_DRA_REPL_PENDING: DWORD = 8477; +pub const ERROR_DS_DS_REQUIRED: DWORD = 8478; +pub const ERROR_DS_INVALID_LDAP_DISPLAY_NAME: DWORD = 8479; +pub const ERROR_DS_NON_BASE_SEARCH: DWORD = 8480; +pub const ERROR_DS_CANT_RETRIEVE_ATTS: DWORD = 8481; +pub const ERROR_DS_BACKLINK_WITHOUT_LINK: DWORD = 8482; +pub const ERROR_DS_EPOCH_MISMATCH: DWORD = 8483; +pub const ERROR_DS_SRC_NAME_MISMATCH: DWORD = 8484; +pub const ERROR_DS_SRC_AND_DST_NC_IDENTICAL: DWORD = 8485; +pub const ERROR_DS_DST_NC_MISMATCH: DWORD = 8486; +pub const ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC: DWORD = 8487; +pub const ERROR_DS_SRC_GUID_MISMATCH: DWORD = 8488; +pub const ERROR_DS_CANT_MOVE_DELETED_OBJECT: DWORD = 8489; +pub const ERROR_DS_PDC_OPERATION_IN_PROGRESS: DWORD = 8490; +pub const ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD: DWORD = 8491; +pub const ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION: DWORD = 8492; +pub const ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS: DWORD = 8493; +pub const ERROR_DS_NC_MUST_HAVE_NC_PARENT: DWORD = 8494; +pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE: DWORD = 8495; +pub const ERROR_DS_DST_DOMAIN_NOT_NATIVE: DWORD = 8496; +pub const ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER: DWORD = 8497; +pub const ERROR_DS_CANT_MOVE_ACCOUNT_GROUP: DWORD = 8498; +pub const ERROR_DS_CANT_MOVE_RESOURCE_GROUP: DWORD = 8499; +pub const ERROR_DS_INVALID_SEARCH_FLAG: DWORD = 8500; +pub const ERROR_DS_NO_TREE_DELETE_ABOVE_NC: DWORD = 8501; +pub const ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE: DWORD = 8502; +pub const ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE: DWORD = 8503; +pub const ERROR_DS_SAM_INIT_FAILURE: DWORD = 8504; +pub const ERROR_DS_SENSITIVE_GROUP_VIOLATION: DWORD = 8505; +pub const ERROR_DS_CANT_MOD_PRIMARYGROUPID: DWORD = 8506; +pub const ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD: DWORD = 8507; +pub const ERROR_DS_NONSAFE_SCHEMA_CHANGE: DWORD = 8508; +pub const ERROR_DS_SCHEMA_UPDATE_DISALLOWED: DWORD = 8509; +pub const ERROR_DS_CANT_CREATE_UNDER_SCHEMA: DWORD = 8510; +pub const ERROR_DS_INSTALL_NO_SRC_SCH_VERSION: DWORD = 8511; +pub const ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE: DWORD = 8512; +pub const ERROR_DS_INVALID_GROUP_TYPE: DWORD = 8513; +pub const ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN: DWORD = 8514; +pub const ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN: DWORD = 8515; +pub const ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8516; +pub const ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8517; +pub const ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER: DWORD = 8518; +pub const ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER: DWORD = 8519; +pub const ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER: DWORD = 8520; +pub const ERROR_DS_HAVE_PRIMARY_MEMBERS: DWORD = 8521; +pub const ERROR_DS_STRING_SD_CONVERSION_FAILED: DWORD = 8522; +pub const ERROR_DS_NAMING_MASTER_GC: DWORD = 8523; +pub const ERROR_DS_DNS_LOOKUP_FAILURE: DWORD = 8524; +pub const ERROR_DS_COULDNT_UPDATE_SPNS: DWORD = 8525; +pub const ERROR_DS_CANT_RETRIEVE_SD: DWORD = 8526; +pub const ERROR_DS_KEY_NOT_UNIQUE: DWORD = 8527; +pub const ERROR_DS_WRONG_LINKED_ATT_SYNTAX: DWORD = 8528; +pub const ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD: DWORD = 8529; +pub const ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY: DWORD = 8530; +pub const ERROR_DS_CANT_START: DWORD = 8531; +pub const ERROR_DS_INIT_FAILURE: DWORD = 8532; +pub const ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION: DWORD = 8533; +pub const ERROR_DS_SOURCE_DOMAIN_IN_FOREST: DWORD = 8534; +pub const ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST: DWORD = 8535; +pub const ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED: DWORD = 8536; +pub const ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN: DWORD = 8537; +pub const ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER: DWORD = 8538; +pub const ERROR_DS_SRC_SID_EXISTS_IN_FOREST: DWORD = 8539; +pub const ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH: DWORD = 8540; +pub const ERROR_SAM_INIT_FAILURE: DWORD = 8541; +pub const ERROR_DS_DRA_SCHEMA_INFO_SHIP: DWORD = 8542; +pub const ERROR_DS_DRA_SCHEMA_CONFLICT: DWORD = 8543; +pub const ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT: DWORD = 8544; +pub const ERROR_DS_DRA_OBJ_NC_MISMATCH: DWORD = 8545; +pub const ERROR_DS_NC_STILL_HAS_DSAS: DWORD = 8546; +pub const ERROR_DS_GC_REQUIRED: DWORD = 8547; +pub const ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY: DWORD = 8548; +pub const ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS: DWORD = 8549; +pub const ERROR_DS_CANT_ADD_TO_GC: DWORD = 8550; +pub const ERROR_DS_NO_CHECKPOINT_WITH_PDC: DWORD = 8551; +pub const ERROR_DS_SOURCE_AUDITING_NOT_ENABLED: DWORD = 8552; +pub const ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC: DWORD = 8553; +pub const ERROR_DS_INVALID_NAME_FOR_SPN: DWORD = 8554; +pub const ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS: DWORD = 8555; +pub const ERROR_DS_UNICODEPWD_NOT_IN_QUOTES: DWORD = 8556; +pub const ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED: DWORD = 8557; +pub const ERROR_DS_MUST_BE_RUN_ON_DST_DC: DWORD = 8558; +pub const ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER: DWORD = 8559; +pub const ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ: DWORD = 8560; +pub const ERROR_DS_INIT_FAILURE_CONSOLE: DWORD = 8561; +pub const ERROR_DS_SAM_INIT_FAILURE_CONSOLE: DWORD = 8562; +pub const ERROR_DS_FOREST_VERSION_TOO_HIGH: DWORD = 8563; +pub const ERROR_DS_DOMAIN_VERSION_TOO_HIGH: DWORD = 8564; +pub const ERROR_DS_FOREST_VERSION_TOO_LOW: DWORD = 8565; +pub const ERROR_DS_DOMAIN_VERSION_TOO_LOW: DWORD = 8566; +pub const ERROR_DS_INCOMPATIBLE_VERSION: DWORD = 8567; +pub const ERROR_DS_LOW_DSA_VERSION: DWORD = 8568; +pub const ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN: DWORD = 8569; +pub const ERROR_DS_NOT_SUPPORTED_SORT_ORDER: DWORD = 8570; +pub const ERROR_DS_NAME_NOT_UNIQUE: DWORD = 8571; +pub const ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4: DWORD = 8572; +pub const ERROR_DS_OUT_OF_VERSION_STORE: DWORD = 8573; +pub const ERROR_DS_INCOMPATIBLE_CONTROLS_USED: DWORD = 8574; +pub const ERROR_DS_NO_REF_DOMAIN: DWORD = 8575; +pub const ERROR_DS_RESERVED_LINK_ID: DWORD = 8576; +pub const ERROR_DS_LINK_ID_NOT_AVAILABLE: DWORD = 8577; +pub const ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER: DWORD = 8578; +pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE: DWORD = 8579; +pub const ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC: DWORD = 8580; +pub const ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG: DWORD = 8581; +pub const ERROR_DS_MODIFYDN_WRONG_GRANDPARENT: DWORD = 8582; +pub const ERROR_DS_NAME_ERROR_TRUST_REFERRAL: DWORD = 8583; +pub const ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER: DWORD = 8584; +pub const ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD: DWORD = 8585; +pub const ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2: DWORD = 8586; +pub const ERROR_DS_THREAD_LIMIT_EXCEEDED: DWORD = 8587; +pub const ERROR_DS_NOT_CLOSEST: DWORD = 8588; +pub const ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF: DWORD = 8589; +pub const ERROR_DS_SINGLE_USER_MODE_FAILED: DWORD = 8590; +pub const ERROR_DS_NTDSCRIPT_SYNTAX_ERROR: DWORD = 8591; +pub const ERROR_DS_NTDSCRIPT_PROCESS_ERROR: DWORD = 8592; +pub const ERROR_DS_DIFFERENT_REPL_EPOCHS: DWORD = 8593; +pub const ERROR_DS_DRS_EXTENSIONS_CHANGED: DWORD = 8594; +pub const ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR: DWORD = 8595; +pub const ERROR_DS_NO_MSDS_INTID: DWORD = 8596; +pub const ERROR_DS_DUP_MSDS_INTID: DWORD = 8597; +pub const ERROR_DS_EXISTS_IN_RDNATTID: DWORD = 8598; +pub const ERROR_DS_AUTHORIZATION_FAILED: DWORD = 8599; +pub const ERROR_DS_INVALID_SCRIPT: DWORD = 8600; +pub const ERROR_DS_REMOTE_CROSSREF_OP_FAILED: DWORD = 8601; +pub const ERROR_DS_CROSS_REF_BUSY: DWORD = 8602; +pub const ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN: DWORD = 8603; +pub const ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC: DWORD = 8604; +pub const ERROR_DS_DUPLICATE_ID_FOUND: DWORD = 8605; +pub const ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT: DWORD = 8606; +pub const ERROR_DS_GROUP_CONVERSION_ERROR: DWORD = 8607; +pub const ERROR_DS_CANT_MOVE_APP_BASIC_GROUP: DWORD = 8608; +pub const ERROR_DS_CANT_MOVE_APP_QUERY_GROUP: DWORD = 8609; +pub const ERROR_DS_ROLE_NOT_VERIFIED: DWORD = 8610; +pub const ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL: DWORD = 8611; +pub const ERROR_DS_DOMAIN_RENAME_IN_PROGRESS: DWORD = 8612; +pub const ERROR_DS_EXISTING_AD_CHILD_NC: DWORD = 8613; +pub const ERROR_DS_REPL_LIFETIME_EXCEEDED: DWORD = 8614; +pub const ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER: DWORD = 8615; +pub const ERROR_DS_LDAP_SEND_QUEUE_FULL: DWORD = 8616; +pub const ERROR_DS_DRA_OUT_SCHEDULE_WINDOW: DWORD = 8617; +pub const ERROR_SXS_SECTION_NOT_FOUND: DWORD = 14000; +pub const ERROR_SXS_CANT_GEN_ACTCTX: DWORD = 14001; +pub const ERROR_SXS_INVALID_ACTCTXDATA_FORMAT: DWORD = 14002; +pub const ERROR_SXS_ASSEMBLY_NOT_FOUND: DWORD = 14003; +pub const ERROR_SXS_MANIFEST_FORMAT_ERROR: DWORD = 14004; +pub const ERROR_SXS_MANIFEST_PARSE_ERROR: DWORD = 14005; +pub const ERROR_SXS_ACTIVATION_CONTEXT_DISABLED: DWORD = 14006; +pub const ERROR_SXS_KEY_NOT_FOUND: DWORD = 14007; +pub const ERROR_SXS_VERSION_CONFLICT: DWORD = 14008; +pub const ERROR_SXS_WRONG_SECTION_TYPE: DWORD = 14009; +pub const ERROR_SXS_THREAD_QUERIES_DISABLED: DWORD = 14010; +pub const ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET: DWORD = 14011; +pub const ERROR_SXS_UNKNOWN_ENCODING_GROUP: DWORD = 14012; +pub const ERROR_SXS_UNKNOWN_ENCODING: DWORD = 14013; +pub const ERROR_SXS_INVALID_XML_NAMESPACE_URI: DWORD = 14014; +pub const ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14015; +pub const ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED: DWORD = 14016; +pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14017; +pub const ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14018; +pub const ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE: DWORD = 14019; +pub const ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT: DWORD = 14020; +pub const ERROR_SXS_DUPLICATE_DLL_NAME: DWORD = 14021; +pub const ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME: DWORD = 14022; +pub const ERROR_SXS_DUPLICATE_CLSID: DWORD = 14023; +pub const ERROR_SXS_DUPLICATE_IID: DWORD = 14024; +pub const ERROR_SXS_DUPLICATE_TLBID: DWORD = 14025; +pub const ERROR_SXS_DUPLICATE_PROGID: DWORD = 14026; +pub const ERROR_SXS_DUPLICATE_ASSEMBLY_NAME: DWORD = 14027; +pub const ERROR_SXS_FILE_HASH_MISMATCH: DWORD = 14028; +pub const ERROR_SXS_POLICY_PARSE_ERROR: DWORD = 14029; +pub const ERROR_SXS_XML_E_MISSINGQUOTE: DWORD = 14030; +pub const ERROR_SXS_XML_E_COMMENTSYNTAX: DWORD = 14031; +pub const ERROR_SXS_XML_E_BADSTARTNAMECHAR: DWORD = 14032; +pub const ERROR_SXS_XML_E_BADNAMECHAR: DWORD = 14033; +pub const ERROR_SXS_XML_E_BADCHARINSTRING: DWORD = 14034; +pub const ERROR_SXS_XML_E_XMLDECLSYNTAX: DWORD = 14035; +pub const ERROR_SXS_XML_E_BADCHARDATA: DWORD = 14036; +pub const ERROR_SXS_XML_E_MISSINGWHITESPACE: DWORD = 14037; +pub const ERROR_SXS_XML_E_EXPECTINGTAGEND: DWORD = 14038; +pub const ERROR_SXS_XML_E_MISSINGSEMICOLON: DWORD = 14039; +pub const ERROR_SXS_XML_E_UNBALANCEDPAREN: DWORD = 14040; +pub const ERROR_SXS_XML_E_INTERNALERROR: DWORD = 14041; +pub const ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE: DWORD = 14042; +pub const ERROR_SXS_XML_E_INCOMPLETE_ENCODING: DWORD = 14043; +pub const ERROR_SXS_XML_E_MISSING_PAREN: DWORD = 14044; +pub const ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE: DWORD = 14045; +pub const ERROR_SXS_XML_E_MULTIPLE_COLONS: DWORD = 14046; +pub const ERROR_SXS_XML_E_INVALID_DECIMAL: DWORD = 14047; +pub const ERROR_SXS_XML_E_INVALID_HEXIDECIMAL: DWORD = 14048; +pub const ERROR_SXS_XML_E_INVALID_UNICODE: DWORD = 14049; +pub const ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK: DWORD = 14050; +pub const ERROR_SXS_XML_E_UNEXPECTEDENDTAG: DWORD = 14051; +pub const ERROR_SXS_XML_E_UNCLOSEDTAG: DWORD = 14052; +pub const ERROR_SXS_XML_E_DUPLICATEATTRIBUTE: DWORD = 14053; +pub const ERROR_SXS_XML_E_MULTIPLEROOTS: DWORD = 14054; +pub const ERROR_SXS_XML_E_INVALIDATROOTLEVEL: DWORD = 14055; +pub const ERROR_SXS_XML_E_BADXMLDECL: DWORD = 14056; +pub const ERROR_SXS_XML_E_MISSINGROOT: DWORD = 14057; +pub const ERROR_SXS_XML_E_UNEXPECTEDEOF: DWORD = 14058; +pub const ERROR_SXS_XML_E_BADPEREFINSUBSET: DWORD = 14059; +pub const ERROR_SXS_XML_E_UNCLOSEDSTARTTAG: DWORD = 14060; +pub const ERROR_SXS_XML_E_UNCLOSEDENDTAG: DWORD = 14061; +pub const ERROR_SXS_XML_E_UNCLOSEDSTRING: DWORD = 14062; +pub const ERROR_SXS_XML_E_UNCLOSEDCOMMENT: DWORD = 14063; +pub const ERROR_SXS_XML_E_UNCLOSEDDECL: DWORD = 14064; +pub const ERROR_SXS_XML_E_UNCLOSEDCDATA: DWORD = 14065; +pub const ERROR_SXS_XML_E_RESERVEDNAMESPACE: DWORD = 14066; +pub const ERROR_SXS_XML_E_INVALIDENCODING: DWORD = 14067; +pub const ERROR_SXS_XML_E_INVALIDSWITCH: DWORD = 14068; +pub const ERROR_SXS_XML_E_BADXMLCASE: DWORD = 14069; +pub const ERROR_SXS_XML_E_INVALID_STANDALONE: DWORD = 14070; +pub const ERROR_SXS_XML_E_UNEXPECTED_STANDALONE: DWORD = 14071; +pub const ERROR_SXS_XML_E_INVALID_VERSION: DWORD = 14072; +pub const ERROR_SXS_XML_E_MISSINGEQUALS: DWORD = 14073; +pub const ERROR_SXS_PROTECTION_RECOVERY_FAILED: DWORD = 14074; +pub const ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT: DWORD = 14075; +pub const ERROR_SXS_PROTECTION_CATALOG_NOT_VALID: DWORD = 14076; +pub const ERROR_SXS_UNTRANSLATABLE_HRESULT: DWORD = 14077; +pub const ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING: DWORD = 14078; +pub const ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE: DWORD = 14079; +pub const ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME: DWORD = 14080; +pub const ERROR_SXS_ASSEMBLY_MISSING: DWORD = 14081; +pub const ERROR_SXS_CORRUPT_ACTIVATION_STACK: DWORD = 14082; +pub const ERROR_SXS_CORRUPTION: DWORD = 14083; +pub const ERROR_SXS_EARLY_DEACTIVATION: DWORD = 14084; +pub const ERROR_SXS_INVALID_DEACTIVATION: DWORD = 14085; +pub const ERROR_SXS_MULTIPLE_DEACTIVATION: DWORD = 14086; +pub const ERROR_SXS_PROCESS_TERMINATION_REQUESTED: DWORD = 14087; +pub const ERROR_SXS_RELEASE_ACTIVATION_CONTEXT: DWORD = 14088; +pub const ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY: DWORD = 14089; +pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE: DWORD = 14090; +pub const ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME: DWORD = 14091; +pub const ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE: DWORD = 14092; +pub const ERROR_SXS_IDENTITY_PARSE_ERROR: DWORD = 14093; +pub const ERROR_MALFORMED_SUBSTITUTION_STRING: DWORD = 14094; +pub const ERROR_SXS_INCORRECT_PUBLIC_KEY_TOKEN: DWORD = 14095; +pub const ERROR_UNMAPPED_SUBSTITUTION_STRING: DWORD = 14096; +pub const ERROR_SXS_ASSEMBLY_NOT_LOCKED: DWORD = 14097; +pub const ERROR_SXS_COMPONENT_STORE_CORRUPT: DWORD = 14098; +pub const ERROR_ADVANCED_INSTALLER_FAILED: DWORD = 14099; +pub const ERROR_XML_ENCODING_MISMATCH: DWORD = 14100; +pub const ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT: DWORD = 14101; +pub const ERROR_SXS_IDENTITIES_DIFFERENT: DWORD = 14102; +pub const ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT: DWORD = 14103; +pub const ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY: DWORD = 14104; +pub const ERROR_SXS_MANIFEST_TOO_BIG: DWORD = 14105; +pub const ERROR_SXS_SETTING_NOT_REGISTERED: DWORD = 14106; +pub const ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE: DWORD = 14107; +pub const ERROR_SMI_PRIMITIVE_INSTALLER_FAILED: DWORD = 14108; +pub const ERROR_GENERIC_COMMAND_FAILED: DWORD = 14109; +pub const ERROR_SXS_FILE_HASH_MISSING: DWORD = 14110; +pub const ERROR_IPSEC_QM_POLICY_EXISTS: DWORD = 13000; +pub const ERROR_IPSEC_QM_POLICY_NOT_FOUND: DWORD = 13001; +pub const ERROR_IPSEC_QM_POLICY_IN_USE: DWORD = 13002; +pub const ERROR_IPSEC_MM_POLICY_EXISTS: DWORD = 13003; +pub const ERROR_IPSEC_MM_POLICY_NOT_FOUND: DWORD = 13004; +pub const ERROR_IPSEC_MM_POLICY_IN_USE: DWORD = 13005; +pub const ERROR_IPSEC_MM_FILTER_EXISTS: DWORD = 13006; +pub const ERROR_IPSEC_MM_FILTER_NOT_FOUND: DWORD = 13007; +pub const ERROR_IPSEC_TRANSPORT_FILTER_EXISTS: DWORD = 13008; +pub const ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND: DWORD = 13009; +pub const ERROR_IPSEC_MM_AUTH_EXISTS: DWORD = 13010; +pub const ERROR_IPSEC_MM_AUTH_NOT_FOUND: DWORD = 13011; +pub const ERROR_IPSEC_MM_AUTH_IN_USE: DWORD = 13012; +pub const ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND: DWORD = 13013; +pub const ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND: DWORD = 13014; +pub const ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND: DWORD = 13015; +pub const ERROR_IPSEC_TUNNEL_FILTER_EXISTS: DWORD = 13016; +pub const ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND: DWORD = 13017; +pub const ERROR_IPSEC_MM_FILTER_PENDING_DELETION: DWORD = 13018; +pub const ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION: DWORD = 13019; +pub const ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION: DWORD = 13020; +pub const ERROR_IPSEC_MM_POLICY_PENDING_DELETION: DWORD = 13021; +pub const ERROR_IPSEC_MM_AUTH_PENDING_DELETION: DWORD = 13022; +pub const ERROR_IPSEC_QM_POLICY_PENDING_DELETION: DWORD = 13023; +pub const ERROR_IPSEC_IKE_NEG_STATUS_BEGIN: DWORD = 13800; +pub const ERROR_IPSEC_IKE_AUTH_FAIL: DWORD = 13801; +pub const ERROR_IPSEC_IKE_ATTRIB_FAIL: DWORD = 13802; +pub const ERROR_IPSEC_IKE_NEGOTIATION_PENDING: DWORD = 13803; +pub const ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR: DWORD = 13804; +pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; +pub const ERROR_IPSEC_IKE_NO_CERT: DWORD = 13806; +pub const ERROR_IPSEC_IKE_SA_DELETED: DWORD = 13807; +pub const ERROR_IPSEC_IKE_SA_REAPED: DWORD = 13808; +pub const ERROR_IPSEC_IKE_MM_ACQUIRE_DROP: DWORD = 13809; +pub const ERROR_IPSEC_IKE_QM_ACQUIRE_DROP: DWORD = 13810; +pub const ERROR_IPSEC_IKE_QUEUE_DROP_MM: DWORD = 13811; +pub const ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM: DWORD = 13812; +pub const ERROR_IPSEC_IKE_DROP_NO_RESPONSE: DWORD = 13813; +pub const ERROR_IPSEC_IKE_MM_DELAY_DROP: DWORD = 13814; +pub const ERROR_IPSEC_IKE_QM_DELAY_DROP: DWORD = 13815; +pub const ERROR_IPSEC_IKE_ERROR: DWORD = 13816; +pub const ERROR_IPSEC_IKE_CRL_FAILED: DWORD = 13817; +pub const ERROR_IPSEC_IKE_INVALID_KEY_USAGE: DWORD = 13818; +pub const ERROR_IPSEC_IKE_INVALID_CERT_TYPE: DWORD = 13819; +pub const ERROR_IPSEC_IKE_NO_PRIVATE_KEY: DWORD = 13820; +pub const ERROR_IPSEC_IKE_DH_FAIL: DWORD = 13822; +pub const ERROR_IPSEC_IKE_INVALID_HEADER: DWORD = 13824; +pub const ERROR_IPSEC_IKE_NO_POLICY: DWORD = 13825; +pub const ERROR_IPSEC_IKE_INVALID_SIGNATURE: DWORD = 13826; +pub const ERROR_IPSEC_IKE_KERBEROS_ERROR: DWORD = 13827; +pub const ERROR_IPSEC_IKE_NO_PUBLIC_KEY: DWORD = 13828; +pub const ERROR_IPSEC_IKE_PROCESS_ERR: DWORD = 13829; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_SA: DWORD = 13830; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_PROP: DWORD = 13831; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_TRANS: DWORD = 13832; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_KE: DWORD = 13833; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_ID: DWORD = 13834; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT: DWORD = 13835; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ: DWORD = 13836; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_HASH: DWORD = 13837; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_SIG: DWORD = 13838; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_NONCE: DWORD = 13839; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY: DWORD = 13840; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_DELETE: DWORD = 13841; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR: DWORD = 13842; +pub const ERROR_IPSEC_IKE_INVALID_PAYLOAD: DWORD = 13843; +pub const ERROR_IPSEC_IKE_LOAD_SOFT_SA: DWORD = 13844; +pub const ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN: DWORD = 13845; +pub const ERROR_IPSEC_IKE_INVALID_COOKIE: DWORD = 13846; +pub const ERROR_IPSEC_IKE_NO_PEER_CERT: DWORD = 13847; +pub const ERROR_IPSEC_IKE_PEER_CRL_FAILED: DWORD = 13848; +pub const ERROR_IPSEC_IKE_POLICY_CHANGE: DWORD = 13849; +pub const ERROR_IPSEC_IKE_NO_MM_POLICY: DWORD = 13850; +pub const ERROR_IPSEC_IKE_NOTCBPRIV: DWORD = 13851; +pub const ERROR_IPSEC_IKE_SECLOADFAIL: DWORD = 13852; +pub const ERROR_IPSEC_IKE_FAILSSPINIT: DWORD = 13853; +pub const ERROR_IPSEC_IKE_FAILQUERYSSP: DWORD = 13854; +pub const ERROR_IPSEC_IKE_SRVACQFAIL: DWORD = 13855; +pub const ERROR_IPSEC_IKE_SRVQUERYCRED: DWORD = 13856; +pub const ERROR_IPSEC_IKE_GETSPIFAIL: DWORD = 13857; +pub const ERROR_IPSEC_IKE_INVALID_FILTER: DWORD = 13858; +pub const ERROR_IPSEC_IKE_OUT_OF_MEMORY: DWORD = 13859; +pub const ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED: DWORD = 13860; +pub const ERROR_IPSEC_IKE_INVALID_POLICY: DWORD = 13861; +pub const ERROR_IPSEC_IKE_UNKNOWN_DOI: DWORD = 13862; +pub const ERROR_IPSEC_IKE_INVALID_SITUATION: DWORD = 13863; +pub const ERROR_IPSEC_IKE_DH_FAILURE: DWORD = 13864; +pub const ERROR_IPSEC_IKE_INVALID_GROUP: DWORD = 13865; +pub const ERROR_IPSEC_IKE_ENCRYPT: DWORD = 13866; +pub const ERROR_IPSEC_IKE_DECRYPT: DWORD = 13867; +pub const ERROR_IPSEC_IKE_POLICY_MATCH: DWORD = 13868; +pub const ERROR_IPSEC_IKE_UNSUPPORTED_ID: DWORD = 13869; +pub const ERROR_IPSEC_IKE_INVALID_HASH: DWORD = 13870; +pub const ERROR_IPSEC_IKE_INVALID_HASH_ALG: DWORD = 13871; +pub const ERROR_IPSEC_IKE_INVALID_HASH_SIZE: DWORD = 13872; +pub const ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG: DWORD = 13873; +pub const ERROR_IPSEC_IKE_INVALID_AUTH_ALG: DWORD = 13874; +pub const ERROR_IPSEC_IKE_INVALID_SIG: DWORD = 13875; +pub const ERROR_IPSEC_IKE_LOAD_FAILED: DWORD = 13876; +pub const ERROR_IPSEC_IKE_RPC_DELETE: DWORD = 13877; +pub const ERROR_IPSEC_IKE_BENIGN_REINIT: DWORD = 13878; +pub const ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY: DWORD = 13879; +pub const ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN: DWORD = 13881; +pub const ERROR_IPSEC_IKE_MM_LIMIT: DWORD = 13882; +pub const ERROR_IPSEC_IKE_NEGOTIATION_DISABLED: DWORD = 13883; +/*pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13884)*/ +pub const ERROR_IPSEC_IKE_QM_LIMIT: DWORD = 13884; +pub const ERROR_IPSEC_IKE_MM_EXPIRED: DWORD = 13885; +pub const ERROR_IPSEC_IKE_PEER_MM_ASSUMED_INVALID: DWORD = 13886; +pub const ERROR_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH: DWORD = 13887; +pub const ERROR_IPSEC_IKE_UNEXPECTED_MESSAGE_ID: DWORD = 13888; +pub const ERROR_IPSEC_IKE_INVALID_AUTH_PAYLOAD: DWORD = 13889; +pub const ERROR_IPSEC_IKE_DOS_COOKIE_SENT: DWORD = 13890; +pub const ERROR_IPSEC_IKE_SHUTTING_DOWN: DWORD = 13891; +pub const ERROR_IPSEC_IKE_CGA_AUTH_FAILED: DWORD = 13892; +pub const ERROR_IPSEC_IKE_PROCESS_ERR_NATOA: DWORD = 13893; +pub const ERROR_IPSEC_IKE_INVALID_MM_FOR_QM: DWORD = 13894; +pub const ERROR_IPSEC_IKE_QM_EXPIRED: DWORD = 13895; +pub const ERROR_IPSEC_IKE_TOO_MANY_FILTERS: DWORD = 13896; +pub const ERROR_IPSEC_IKE_NEG_STATUS_END: DWORD = 13897; +pub const ERROR_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL: DWORD = 13898; +pub const ERROR_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE: DWORD = 13899; +pub const ERROR_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING: DWORD = 13900; +pub const ERROR_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING: DWORD = 13901; +pub const ERROR_IPSEC_IKE_COEXISTENCE_SUPPRESS: DWORD = 13902; +pub const ERROR_IPSEC_IKE_RATELIMIT_DROP: DWORD = 13903; +pub const ERROR_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE: DWORD = 13904; +pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE: DWORD = 13905; +pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE: DWORD = 13906; +pub const ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY: DWORD = 13907; +pub const ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE: DWORD = 13908; +pub const ERROR_IPSEC_IKE_NEG_STATUS_EXTENDED_END: DWORD = 13909; +pub const ERROR_IPSEC_BAD_SPI: DWORD = 13910; +pub const ERROR_IPSEC_SA_LIFETIME_EXPIRED: DWORD = 13911; +pub const ERROR_IPSEC_WRONG_SA: DWORD = 13912; +pub const ERROR_IPSEC_REPLAY_CHECK_FAILED: DWORD = 13913; +pub const ERROR_IPSEC_INVALID_PACKET: DWORD = 13914; +pub const ERROR_IPSEC_INTEGRITY_CHECK_FAILED: DWORD = 13915; +pub const ERROR_IPSEC_CLEAR_TEXT_DROP: DWORD = 13916; +pub const ERROR_IPSEC_AUTH_FIREWALL_DROP: DWORD = 13917; +pub const ERROR_IPSEC_THROTTLE_DROP: DWORD = 13918; +pub const ERROR_IPSEC_DOSP_BLOCK: DWORD = 13925; +pub const ERROR_IPSEC_DOSP_RECEIVED_MULTICAST: DWORD = 13926; +pub const ERROR_IPSEC_DOSP_INVALID_PACKET: DWORD = 13927; +pub const ERROR_IPSEC_DOSP_STATE_LOOKUP_FAILED: DWORD = 13928; +pub const ERROR_IPSEC_DOSP_MAX_ENTRIES: DWORD = 13929; +pub const ERROR_IPSEC_DOSP_KEYMOD_NOT_ALLOWED: DWORD = 13930; +pub const ERROR_IPSEC_DOSP_NOT_INSTALLED: DWORD = 13931; +pub const ERROR_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES: DWORD = 13932; +pub const ERROR_EVT_INVALID_CHANNEL_PATH: DWORD = 15000; +pub const ERROR_EVT_INVALID_QUERY: DWORD = 15001; +pub const ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND: DWORD = 15002; +pub const ERROR_EVT_EVENT_TEMPLATE_NOT_FOUND: DWORD = 15003; +pub const ERROR_EVT_INVALID_PUBLISHER_NAME: DWORD = 15004; +pub const ERROR_EVT_INVALID_EVENT_DATA: DWORD = 15005; +pub const ERROR_EVT_CHANNEL_NOT_FOUND: DWORD = 15007; +pub const ERROR_EVT_MALFORMED_XML_TEXT: DWORD = 15008; +pub const ERROR_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL: DWORD = 15009; +pub const ERROR_EVT_CONFIGURATION_ERROR: DWORD = 15010; +pub const ERROR_EVT_QUERY_RESULT_STALE: DWORD = 15011; +pub const ERROR_EVT_QUERY_RESULT_INVALID_POSITION: DWORD = 15012; +pub const ERROR_EVT_NON_VALIDATING_MSXML: DWORD = 15013; +pub const ERROR_EVT_FILTER_ALREADYSCOPED: DWORD = 15014; +pub const ERROR_EVT_FILTER_NOTELTSET: DWORD = 15015; +pub const ERROR_EVT_FILTER_INVARG: DWORD = 15016; +pub const ERROR_EVT_FILTER_INVTEST: DWORD = 15017; +pub const ERROR_EVT_FILTER_INVTYPE: DWORD = 15018; +pub const ERROR_EVT_FILTER_PARSEERR: DWORD = 15019; +pub const ERROR_EVT_FILTER_UNSUPPORTEDOP: DWORD = 15020; +pub const ERROR_EVT_FILTER_UNEXPECTEDTOKEN: DWORD = 15021; +pub const ERROR_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL: DWORD = 15022; +pub const ERROR_EVT_INVALID_CHANNEL_PROPERTY_VALUE: DWORD = 15023; +pub const ERROR_EVT_INVALID_PUBLISHER_PROPERTY_VALUE: DWORD = 15024; +pub const ERROR_EVT_CHANNEL_CANNOT_ACTIVATE: DWORD = 15025; +pub const ERROR_EVT_FILTER_TOO_COMPLEX: DWORD = 15026; +pub const ERROR_EVT_MESSAGE_NOT_FOUND: DWORD = 15027; +pub const ERROR_EVT_MESSAGE_ID_NOT_FOUND: DWORD = 15028; +pub const ERROR_EVT_UNRESOLVED_VALUE_INSERT: DWORD = 15029; +pub const ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: DWORD = 15030; +pub const ERROR_EVT_MAX_INSERTS_REACHED: DWORD = 15031; +pub const ERROR_EVT_EVENT_DEFINITION_NOT_FOUND: DWORD = 15032; +pub const ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND: DWORD = 15033; +pub const ERROR_EVT_VERSION_TOO_OLD: DWORD = 15034; +pub const ERROR_EVT_VERSION_TOO_NEW: DWORD = 15035; +pub const ERROR_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY: DWORD = 15036; +pub const ERROR_EVT_PUBLISHER_DISABLED: DWORD = 15037; +pub const ERROR_EVT_FILTER_OUT_OF_RANGE: DWORD = 15038; +pub const ERROR_EC_SUBSCRIPTION_CANNOT_ACTIVATE: DWORD = 15080; +pub const ERROR_EC_LOG_DISABLED: DWORD = 15081; +pub const ERROR_EC_CIRCULAR_FORWARDING: DWORD = 15082; +pub const ERROR_EC_CREDSTORE_FULL: DWORD = 15083; +pub const ERROR_EC_CRED_NOT_FOUND: DWORD = 15084; +pub const ERROR_EC_NO_ACTIVE_CHANNEL: DWORD = 15085; +pub const ERROR_MUI_FILE_NOT_FOUND: DWORD = 15100; +pub const ERROR_MUI_INVALID_FILE: DWORD = 15101; +pub const ERROR_MUI_INVALID_RC_CONFIG: DWORD = 15102; +pub const ERROR_MUI_INVALID_LOCALE_NAME: DWORD = 15103; +pub const ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME: DWORD = 15104; +pub const ERROR_MUI_FILE_NOT_LOADED: DWORD = 15105; +pub const ERROR_RESOURCE_ENUM_USER_STOP: DWORD = 15106; +pub const ERROR_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED: DWORD = 15107; +pub const ERROR_MUI_INTLSETTINGS_INVALID_LOCALE_NAME: DWORD = 15108; +pub const ERROR_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE: DWORD = 15110; +pub const ERROR_MRM_INVALID_PRICONFIG: DWORD = 15111; +pub const ERROR_MRM_INVALID_FILE_TYPE: DWORD = 15112; +pub const ERROR_MRM_UNKNOWN_QUALIFIER: DWORD = 15113; +pub const ERROR_MRM_INVALID_QUALIFIER_VALUE: DWORD = 15114; +pub const ERROR_MRM_NO_CANDIDATE: DWORD = 15115; +pub const ERROR_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE: DWORD = 15116; +pub const ERROR_MRM_RESOURCE_TYPE_MISMATCH: DWORD = 15117; +pub const ERROR_MRM_DUPLICATE_MAP_NAME: DWORD = 15118; +pub const ERROR_MRM_DUPLICATE_ENTRY: DWORD = 15119; +pub const ERROR_MRM_INVALID_RESOURCE_IDENTIFIER: DWORD = 15120; +pub const ERROR_MRM_FILEPATH_TOO_LONG: DWORD = 15121; +pub const ERROR_MRM_UNSUPPORTED_DIRECTORY_TYPE: DWORD = 15122; +pub const ERROR_MRM_INVALID_PRI_FILE: DWORD = 15126; +pub const ERROR_MRM_NAMED_RESOURCE_NOT_FOUND: DWORD = 15127; +pub const ERROR_MRM_MAP_NOT_FOUND: DWORD = 15135; +pub const ERROR_MRM_UNSUPPORTED_PROFILE_TYPE: DWORD = 15136; +pub const ERROR_MRM_INVALID_QUALIFIER_OPERATOR: DWORD = 15137; +pub const ERROR_MRM_INDETERMINATE_QUALIFIER_VALUE: DWORD = 15138; +pub const ERROR_MRM_AUTOMERGE_ENABLED: DWORD = 15139; +pub const ERROR_MRM_TOO_MANY_RESOURCES: DWORD = 15140; +pub const ERROR_MCA_INVALID_CAPABILITIES_STRING: DWORD = 15200; +pub const ERROR_MCA_INVALID_VCP_VERSION: DWORD = 15201; +pub const ERROR_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION: DWORD = 15202; +pub const ERROR_MCA_MCCS_VERSION_MISMATCH: DWORD = 15203; +pub const ERROR_MCA_UNSUPPORTED_MCCS_VERSION: DWORD = 15204; +pub const ERROR_MCA_INTERNAL_ERROR: DWORD = 15205; +pub const ERROR_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED: DWORD = 15206; +pub const ERROR_MCA_UNSUPPORTED_COLOR_TEMPERATURE: DWORD = 15207; +pub const ERROR_AMBIGUOUS_SYSTEM_DEVICE: DWORD = 15250; +pub const ERROR_SYSTEM_DEVICE_NOT_FOUND: DWORD = 15299; +pub const ERROR_HASH_NOT_SUPPORTED: DWORD = 15300; +pub const ERROR_HASH_NOT_PRESENT: DWORD = 15301; +pub const ERROR_SECONDARY_IC_PROVIDER_NOT_REGISTERED: DWORD = 15321; +pub const ERROR_GPIO_CLIENT_INFORMATION_INVALID: DWORD = 15322; +pub const ERROR_GPIO_VERSION_NOT_SUPPORTED: DWORD = 15323; +pub const ERROR_GPIO_INVALID_REGISTRATION_PACKET: DWORD = 15324; +pub const ERROR_GPIO_OPERATION_DENIED: DWORD = 15325; +pub const ERROR_GPIO_INCOMPATIBLE_CONNECT_MODE: DWORD = 15326; +pub const ERROR_GPIO_INTERRUPT_ALREADY_UNMASKED: DWORD = 15327; +pub const ERROR_CANNOT_SWITCH_RUNLEVEL: DWORD = 15400; +pub const ERROR_INVALID_RUNLEVEL_SETTING: DWORD = 15401; +pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; +pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; +pub const ERROR_RUNLEVEL_SWITCH_IN_PROGRESS: DWORD = 15404; +pub const ERROR_SERVICES_FAILED_AUTOSTART: DWORD = 15405; +pub const ERROR_COM_TASK_STOP_PENDING: DWORD = 15501; +pub const ERROR_INSTALL_OPEN_PACKAGE_FAILED: DWORD = 15600; +pub const ERROR_INSTALL_PACKAGE_NOT_FOUND: DWORD = 15601; +pub const ERROR_INSTALL_INVALID_PACKAGE: DWORD = 15602; +pub const ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED: DWORD = 15603; +pub const ERROR_INSTALL_OUT_OF_DISK_SPACE: DWORD = 15604; +pub const ERROR_INSTALL_NETWORK_FAILURE: DWORD = 15605; +pub const ERROR_INSTALL_REGISTRATION_FAILURE: DWORD = 15606; +pub const ERROR_INSTALL_DEREGISTRATION_FAILURE: DWORD = 15607; +pub const ERROR_INSTALL_CANCEL: DWORD = 15608; +pub const ERROR_INSTALL_FAILED: DWORD = 15609; +pub const ERROR_REMOVE_FAILED: DWORD = 15610; +pub const ERROR_PACKAGE_ALREADY_EXISTS: DWORD = 15611; +pub const ERROR_NEEDS_REMEDIATION: DWORD = 15612; +pub const ERROR_INSTALL_PREREQUISITE_FAILED: DWORD = 15613; +pub const ERROR_PACKAGE_REPOSITORY_CORRUPTED: DWORD = 15614; +pub const ERROR_INSTALL_POLICY_FAILURE: DWORD = 15615; +pub const ERROR_PACKAGE_UPDATING: DWORD = 15616; +pub const ERROR_DEPLOYMENT_BLOCKED_BY_POLICY: DWORD = 15617; +pub const ERROR_PACKAGES_IN_USE: DWORD = 15618; +pub const ERROR_RECOVERY_FILE_CORRUPT: DWORD = 15619; +pub const ERROR_INVALID_STAGED_SIGNATURE: DWORD = 15620; +pub const ERROR_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED: DWORD = 15621; +pub const ERROR_INSTALL_PACKAGE_DOWNGRADE: DWORD = 15622; +pub const ERROR_SYSTEM_NEEDS_REMEDIATION: DWORD = 15623; +pub const ERROR_APPX_INTEGRITY_FAILURE_CLR_NGEN: DWORD = 15624; +pub const ERROR_RESILIENCY_FILE_CORRUPT: DWORD = 15625; +pub const ERROR_INSTALL_FIREWALL_SERVICE_NOT_RUNNING: DWORD = 15626; +pub const ERROR_STATE_LOAD_STORE_FAILED: DWORD = 15800; +pub const ERROR_STATE_GET_VERSION_FAILED: DWORD = 15801; +pub const ERROR_STATE_SET_VERSION_FAILED: DWORD = 15802; +pub const ERROR_STATE_STRUCTURED_RESET_FAILED: DWORD = 15803; +pub const ERROR_STATE_OPEN_CONTAINER_FAILED: DWORD = 15804; +pub const ERROR_STATE_CREATE_CONTAINER_FAILED: DWORD = 15805; +pub const ERROR_STATE_DELETE_CONTAINER_FAILED: DWORD = 15806; +pub const ERROR_STATE_READ_SETTING_FAILED: DWORD = 15807; +pub const ERROR_STATE_WRITE_SETTING_FAILED: DWORD = 15808; +pub const ERROR_STATE_DELETE_SETTING_FAILED: DWORD = 15809; +pub const ERROR_STATE_QUERY_SETTING_FAILED: DWORD = 15810; +pub const ERROR_STATE_READ_COMPOSITE_SETTING_FAILED: DWORD = 15811; +pub const ERROR_STATE_WRITE_COMPOSITE_SETTING_FAILED: DWORD = 15812; +pub const ERROR_STATE_ENUMERATE_CONTAINER_FAILED: DWORD = 15813; +pub const ERROR_STATE_ENUMERATE_SETTINGS_FAILED: DWORD = 15814; +pub const ERROR_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15815; +pub const ERROR_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED: DWORD = 15816; +pub const ERROR_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15817; +pub const ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED: DWORD = 15818; +pub const ERROR_API_UNAVAILABLE: DWORD = 15841; +pub const ERROR_AUDITING_DISABLED: DWORD = 0xC0090001; +pub const ERROR_ALL_SIDS_FILTERED: DWORD = 0xC0090002; + +pub const WSABASEERR: c_int = 10000; +pub const WSAEINTR: c_int = WSABASEERR + 4; +pub const WSAEBADF: c_int = WSABASEERR + 9; +pub const WSAEACCES: c_int = WSABASEERR + 13; +pub const WSAEFAULT: c_int = WSABASEERR + 14; +pub const WSAEINVAL: c_int = WSABASEERR + 22; +pub const WSAEMFILE: c_int = WSABASEERR + 24; +pub const WSAEWOULDBLOCK: c_int = WSABASEERR + 35; +pub const WSAEINPROGRESS: c_int = WSABASEERR + 36; +pub const WSAEALREADY: c_int = WSABASEERR + 37; +pub const WSAENOTSOCK: c_int = WSABASEERR + 38; +pub const WSAEDESTADDRREQ: c_int = WSABASEERR + 39; +pub const WSAEMSGSIZE: c_int = WSABASEERR + 40; +pub const WSAEPROTOTYPE: c_int = WSABASEERR + 41; +pub const WSAENOPROTOOPT: c_int = WSABASEERR + 42; +pub const WSAEPROTONOSUPPORT: c_int = WSABASEERR + 43; +pub const WSAESOCKTNOSUPPORT: c_int = WSABASEERR + 44; +pub const WSAEOPNOTSUPP: c_int = WSABASEERR + 45; +pub const WSAEPFNOSUPPORT: c_int = WSABASEERR + 46; +pub const WSAEAFNOSUPPORT: c_int = WSABASEERR + 47; +pub const WSAEADDRINUSE: c_int = WSABASEERR + 48; +pub const WSAEADDRNOTAVAIL: c_int = WSABASEERR + 49; +pub const WSAENETDOWN: c_int = WSABASEERR + 50; +pub const WSAENETUNREACH: c_int = WSABASEERR + 51; +pub const WSAENETRESET: c_int = WSABASEERR + 52; +pub const WSAECONNABORTED: c_int = WSABASEERR + 53; +pub const WSAECONNRESET: c_int = WSABASEERR + 54; +pub const WSAENOBUFS: c_int = WSABASEERR + 55; +pub const WSAEISCONN: c_int = WSABASEERR + 56; +pub const WSAENOTCONN: c_int = WSABASEERR + 57; +pub const WSAESHUTDOWN: c_int = WSABASEERR + 58; +pub const WSAETOOMANYREFS: c_int = WSABASEERR + 59; +pub const WSAETIMEDOUT: c_int = WSABASEERR + 60; +pub const WSAECONNREFUSED: c_int = WSABASEERR + 61; +pub const WSAELOOP: c_int = WSABASEERR + 62; +pub const WSAENAMETOOLONG: c_int = WSABASEERR + 63; +pub const WSAEHOSTDOWN: c_int = WSABASEERR + 64; +pub const WSAEHOSTUNREACH: c_int = WSABASEERR + 65; +pub const WSAENOTEMPTY: c_int = WSABASEERR + 66; +pub const WSAEPROCLIM: c_int = WSABASEERR + 67; +pub const WSAEUSERS: c_int = WSABASEERR + 68; +pub const WSAEDQUOT: c_int = WSABASEERR + 69; +pub const WSAESTALE: c_int = WSABASEERR + 70; +pub const WSAEREMOTE: c_int = WSABASEERR + 71; +pub const WSASYSNOTREADY: c_int = WSABASEERR + 91; +pub const WSAVERNOTSUPPORTED: c_int = WSABASEERR + 92; +pub const WSANOTINITIALISED: c_int = WSABASEERR + 93; +pub const WSAEDISCON: c_int = WSABASEERR + 101; +pub const WSAENOMORE: c_int = WSABASEERR + 102; +pub const WSAECANCELLED: c_int = WSABASEERR + 103; +pub const WSAEINVALIDPROCTABLE: c_int = WSABASEERR + 104; +pub const WSAEINVALIDPROVIDER: c_int = WSABASEERR + 105; +pub const WSAEPROVIDERFAILEDINIT: c_int = WSABASEERR + 106; +pub const WSASYSCALLFAILURE: c_int = WSABASEERR + 107; +pub const WSASERVICE_NOT_FOUND: c_int = WSABASEERR + 108; +pub const WSATYPE_NOT_FOUND: c_int = WSABASEERR + 109; +pub const WSA_E_NO_MORE: c_int = WSABASEERR + 110; +pub const WSA_E_CANCELLED: c_int = WSABASEERR + 111; +pub const WSAEREFUSED: c_int = WSABASEERR + 112; +pub const WSAHOST_NOT_FOUND: c_int = WSABASEERR + 1001; +pub const WSATRY_AGAIN: c_int = WSABASEERR + 1002; +pub const WSANO_RECOVERY: c_int = WSABASEERR + 1003; +pub const WSANO_DATA: c_int = WSABASEERR + 1004; +pub const WSA_QOS_RECEIVERS: c_int = WSABASEERR + 1005; +pub const WSA_QOS_SENDERS: c_int = WSABASEERR + 1006; +pub const WSA_QOS_NO_SENDERS: c_int = WSABASEERR + 1007; +pub const WSA_QOS_NO_RECEIVERS: c_int = WSABASEERR + 1008; +pub const WSA_QOS_REQUEST_CONFIRMED: c_int = WSABASEERR + 1009; +pub const WSA_QOS_ADMISSION_FAILURE: c_int = WSABASEERR + 1010; +pub const WSA_QOS_POLICY_FAILURE: c_int = WSABASEERR + 1011; +pub const WSA_QOS_BAD_STYLE: c_int = WSABASEERR + 1012; +pub const WSA_QOS_BAD_OBJECT: c_int = WSABASEERR + 1013; +pub const WSA_QOS_TRAFFIC_CTRL_ERROR: c_int = WSABASEERR + 1014; +pub const WSA_QOS_GENERIC_ERROR: c_int = WSABASEERR + 1015; +pub const WSA_QOS_ESERVICETYPE: c_int = WSABASEERR + 1016; +pub const WSA_QOS_EFLOWSPEC: c_int = WSABASEERR + 1017; +pub const WSA_QOS_EPROVSPECBUF: c_int = WSABASEERR + 1018; +pub const WSA_QOS_EFILTERSTYLE: c_int = WSABASEERR + 1019; +pub const WSA_QOS_EFILTERTYPE: c_int = WSABASEERR + 1020; +pub const WSA_QOS_EFILTERCOUNT: c_int = WSABASEERR + 1021; +pub const WSA_QOS_EOBJLENGTH: c_int = WSABASEERR + 1022; +pub const WSA_QOS_EFLOWCOUNT: c_int = WSABASEERR + 1023; +pub const WSA_QOS_EUNKNOWNPSOBJ: c_int = WSABASEERR + 1024; +pub const WSA_QOS_EUNKOWNPSOBJ: c_int = WSA_QOS_EUNKNOWNPSOBJ; +pub const WSA_QOS_EPOLICYOBJ: c_int = WSABASEERR + 1025; +pub const WSA_QOS_EFLOWDESC: c_int = WSABASEERR + 1026; +pub const WSA_QOS_EPSFLOWSPEC: c_int = WSABASEERR + 1027; +pub const WSA_QOS_EPSFILTERSPEC: c_int = WSABASEERR + 1028; +pub const WSA_QOS_ESDMODEOBJ: c_int = WSABASEERR + 1029; +pub const WSA_QOS_ESHAPERATEOBJ: c_int = WSABASEERR + 1030; +pub const WSA_QOS_RESERVED_PETYPE: c_int = WSABASEERR + 1031; diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 2b6143de96..c677adae68 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -514,7 +514,7 @@ impl File { } _ => { return Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"Unsupported reparse point type", )); } @@ -961,9 +961,8 @@ pub fn try_exists(path: &Path) -> io::Result { // `ERROR_SHARING_VIOLATION` means that the file has been locked by // another process. This is often temporary so we simply report it // as the file existing. - io::ErrorKind::Other if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => { - Ok(true) - } + _ if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => Ok(true), + // Other errors such as `ERROR_ACCESS_DENIED` may indicate that the // file exists. However, these types of errors are usually more // permanent so we report them here. diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index f23e874f24..28fec817f8 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -61,16 +61,18 @@ pub unsafe fn cleanup() { } pub fn decode_error_kind(errno: i32) -> ErrorKind { + use ErrorKind::*; + match errno as c::DWORD { - c::ERROR_ACCESS_DENIED => return ErrorKind::PermissionDenied, - c::ERROR_ALREADY_EXISTS => return ErrorKind::AlreadyExists, - c::ERROR_FILE_EXISTS => return ErrorKind::AlreadyExists, - c::ERROR_BROKEN_PIPE => return ErrorKind::BrokenPipe, - c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, - c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, - c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, - c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput, - c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return ErrorKind::OutOfMemory, + c::ERROR_ACCESS_DENIED => return PermissionDenied, + c::ERROR_ALREADY_EXISTS => return AlreadyExists, + c::ERROR_FILE_EXISTS => return AlreadyExists, + c::ERROR_BROKEN_PIPE => return BrokenPipe, + c::ERROR_FILE_NOT_FOUND => return NotFound, + c::ERROR_PATH_NOT_FOUND => return NotFound, + c::ERROR_NO_DATA => return BrokenPipe, + c::ERROR_INVALID_PARAMETER => return InvalidInput, + c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory, c::ERROR_SEM_TIMEOUT | c::WAIT_TIMEOUT | c::ERROR_DRIVER_CANCEL_TIMEOUT @@ -86,24 +88,42 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { | c::DNS_ERROR_RECORD_TIMED_OUT | c::ERROR_IPSEC_IKE_TIMED_OUT | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT - | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, - c::ERROR_CALL_NOT_IMPLEMENTED => return ErrorKind::Unsupported, + | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return TimedOut, + c::ERROR_CALL_NOT_IMPLEMENTED => return Unsupported, + c::ERROR_HOST_UNREACHABLE => return HostUnreachable, + c::ERROR_NETWORK_UNREACHABLE => return NetworkUnreachable, + c::ERROR_DIRECTORY => return NotADirectory, + c::ERROR_DIRECTORY_NOT_SUPPORTED => return IsADirectory, + c::ERROR_DIR_NOT_EMPTY => return DirectoryNotEmpty, + c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem, + c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull, + c::ERROR_SEEK_ON_DEVICE => return NotSeekable, + c::ERROR_DISK_QUOTA_EXCEEDED => return FilesystemQuotaExceeded, + c::ERROR_FILE_TOO_LARGE => return FileTooLarge, + c::ERROR_BUSY => return ResourceBusy, + c::ERROR_POSSIBLE_DEADLOCK => return Deadlock, + c::ERROR_NOT_SAME_DEVICE => return CrossesDevices, + c::ERROR_TOO_MANY_LINKS => return TooManyLinks, + c::ERROR_FILENAME_EXCED_RANGE => return FilenameTooLong, _ => {} } match errno { - c::WSAEACCES => ErrorKind::PermissionDenied, - c::WSAEADDRINUSE => ErrorKind::AddrInUse, - c::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - c::WSAECONNABORTED => ErrorKind::ConnectionAborted, - c::WSAECONNREFUSED => ErrorKind::ConnectionRefused, - c::WSAECONNRESET => ErrorKind::ConnectionReset, - c::WSAEINVAL => ErrorKind::InvalidInput, - c::WSAENOTCONN => ErrorKind::NotConnected, - c::WSAEWOULDBLOCK => ErrorKind::WouldBlock, - c::WSAETIMEDOUT => ErrorKind::TimedOut, + c::WSAEACCES => PermissionDenied, + c::WSAEADDRINUSE => AddrInUse, + c::WSAEADDRNOTAVAIL => AddrNotAvailable, + c::WSAECONNABORTED => ConnectionAborted, + c::WSAECONNREFUSED => ConnectionRefused, + c::WSAECONNRESET => ConnectionReset, + c::WSAEINVAL => InvalidInput, + c::WSAENOTCONN => NotConnected, + c::WSAEWOULDBLOCK => WouldBlock, + c::WSAETIMEDOUT => TimedOut, + c::WSAEHOSTUNREACH => HostUnreachable, + c::WSAENETDOWN => NetworkDown, + c::WSAENETUNREACH => NetworkUnreachable, - _ => ErrorKind::Other, + _ => Uncategorized, } } diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 1ad13254c0..9cea5c5e63 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -12,7 +12,7 @@ use crate::sys_common::net; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; -use libc::{c_int, c_long, c_ulong, c_void}; +use libc::{c_int, c_long, c_ulong}; pub type wrlen_t = i32; @@ -93,153 +93,177 @@ where impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { - let fam = match *addr { + let family = match *addr { SocketAddr::V4(..) => c::AF_INET, SocketAddr::V6(..) => c::AF_INET6, }; let socket = unsafe { - match c::WSASocketW( - fam, + c::WSASocketW( + family, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT, - ) { - c::INVALID_SOCKET => match c::WSAGetLastError() { - c::WSAEPROTOTYPE | c::WSAEINVAL => { - match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) - { - c::INVALID_SOCKET => Err(last_error()), - n => { - let s = Socket(n); - s.set_no_inherit()?; - Ok(s) - } - } - } - n => Err(io::Error::from_raw_os_error(n)), - }, - n => Ok(Socket(n)), + ) + }; + + if socket != c::INVALID_SOCKET { + Ok(Self(socket)) + } else { + let error = unsafe { c::WSAGetLastError() }; + + if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL { + return Err(io::Error::from_raw_os_error(error)); + } + + let socket = + unsafe { c::WSASocketW(family, ty, 0, ptr::null_mut(), 0, c::WSA_FLAG_OVERLAPPED) }; + + if socket == c::INVALID_SOCKET { + return Err(last_error()); } - }?; - Ok(socket) + + let socket = Self(socket); + socket.set_no_inherit()?; + Ok(socket) + } } pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; - let r = unsafe { + let result = { let (addrp, len) = addr.into_inner(); - cvt(c::connect(self.0, addrp, len)) + let result = unsafe { c::connect(self.0, addrp, len) }; + cvt(result).map(drop) }; self.set_nonblocking(false)?; - match r { - Ok(_) => return Ok(()), - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {} - Err(e) => return Err(e), - } - - if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { - return Err(io::Error::new_const( - io::ErrorKind::InvalidInput, - &"cannot set a 0 duration timeout", - )); - } - - let mut timeout = c::timeval { - tv_sec: timeout.as_secs() as c_long, - tv_usec: (timeout.subsec_nanos() / 1000) as c_long, - }; - if timeout.tv_sec == 0 && timeout.tv_usec == 0 { - timeout.tv_usec = 1; - } + match result { + Err(ref error) if error.kind() == io::ErrorKind::WouldBlock => { + if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { + return Err(io::Error::new_const( + io::ErrorKind::InvalidInput, + &"cannot set a 0 duration timeout", + )); + } - let fds = unsafe { - let mut fds = mem::zeroed::(); - fds.fd_count = 1; - fds.fd_array[0] = self.0; - fds - }; + let mut timeout = c::timeval { + tv_sec: timeout.as_secs() as c_long, + tv_usec: (timeout.subsec_nanos() / 1000) as c_long, + }; - let mut writefds = fds; - let mut errorfds = fds; + if timeout.tv_sec == 0 && timeout.tv_usec == 0 { + timeout.tv_usec = 1; + } - let n = - unsafe { cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? }; + let fds = { + let mut fds = unsafe { mem::zeroed::() }; + fds.fd_count = 1; + fds.fd_array[0] = self.0; + fds + }; + + let mut writefds = fds; + let mut errorfds = fds; + + let count = { + let result = unsafe { + c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout) + }; + cvt(result)? + }; + + match count { + 0 => { + Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")) + } + _ => { + if writefds.fd_count != 1 { + if let Some(e) = self.take_error()? { + return Err(e); + } + } - match n { - 0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")), - _ => { - if writefds.fd_count != 1 { - if let Some(e) = self.take_error()? { - return Err(e); + Ok(()) } } - Ok(()) } + _ => result, } } pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result { - let socket = unsafe { - match c::accept(self.0, storage, len) { - c::INVALID_SOCKET => Err(last_error()), - n => Ok(Socket(n)), - } - }?; - Ok(socket) + let socket = unsafe { c::accept(self.0, storage, len) }; + + match socket { + c::INVALID_SOCKET => Err(last_error()), + _ => Ok(Self(socket)), + } } pub fn duplicate(&self) -> io::Result { + let mut info = unsafe { mem::zeroed::() }; + let result = unsafe { c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info) }; + cvt(result)?; let socket = unsafe { - let mut info: c::WSAPROTOCOL_INFO = mem::zeroed(); - cvt(c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info))?; - - match c::WSASocketW( + c::WSASocketW( info.iAddressFamily, info.iSocketType, info.iProtocol, &mut info, 0, c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT, - ) { - c::INVALID_SOCKET => match c::WSAGetLastError() { - c::WSAEPROTOTYPE | c::WSAEINVAL => { - match c::WSASocketW( - info.iAddressFamily, - info.iSocketType, - info.iProtocol, - &mut info, - 0, - c::WSA_FLAG_OVERLAPPED, - ) { - c::INVALID_SOCKET => Err(last_error()), - n => { - let s = Socket(n); - s.set_no_inherit()?; - Ok(s) - } - } - } - n => Err(io::Error::from_raw_os_error(n)), - }, - n => Ok(Socket(n)), + ) + }; + + if socket != c::INVALID_SOCKET { + Ok(Self(socket)) + } else { + let error = unsafe { c::WSAGetLastError() }; + + if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL { + return Err(io::Error::from_raw_os_error(error)); + } + + let socket = unsafe { + c::WSASocketW( + info.iAddressFamily, + info.iSocketType, + info.iProtocol, + &mut info, + 0, + c::WSA_FLAG_OVERLAPPED, + ) + }; + + if socket == c::INVALID_SOCKET { + return Err(last_error()); } - }?; - Ok(socket) + + let socket = Self(socket); + socket.set_no_inherit()?; + Ok(socket) + } } fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. - let len = cmp::min(buf.len(), i32::MAX as usize) as i32; - unsafe { - match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) { - -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), - -1 => Err(last_error()), - n => Ok(n as usize), + let length = cmp::min(buf.len(), i32::MAX as usize) as i32; + let result = unsafe { c::recv(self.0, buf.as_mut_ptr() as *mut _, length, flags) }; + + match result { + c::SOCKET_ERROR => { + let error = unsafe { c::WSAGetLastError() }; + + if error == c::WSAESHUTDOWN { + Ok(0) + } else { + Err(io::Error::from_raw_os_error(error)) + } } + _ => Ok(result as usize), } } @@ -250,23 +274,31 @@ impl Socket { pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. - let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD; + let length = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD; let mut nread = 0; let mut flags = 0; - unsafe { - let ret = c::WSARecv( + let result = unsafe { + c::WSARecv( self.0, bufs.as_mut_ptr() as *mut c::WSABUF, - len, + length, &mut nread, &mut flags, ptr::null_mut(), ptr::null_mut(), - ); - match ret { - 0 => Ok(nread as usize), - _ if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), - _ => Err(last_error()), + ) + }; + + match result { + 0 => Ok(nread as usize), + _ => { + let error = unsafe { c::WSAGetLastError() }; + + if error == c::WSAESHUTDOWN { + Ok(0) + } else { + Err(io::Error::from_raw_os_error(error)) + } } } } @@ -285,27 +317,34 @@ impl Socket { buf: &mut [u8], flags: c_int, ) -> io::Result<(usize, SocketAddr)> { - let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() }; + let mut storage = unsafe { mem::zeroed::() }; let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; - let len = cmp::min(buf.len(), ::MAX as usize) as wrlen_t; + let length = cmp::min(buf.len(), ::MAX as usize) as wrlen_t; // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. - unsafe { - match c::recvfrom( + let result = unsafe { + c::recvfrom( self.0, - buf.as_mut_ptr() as *mut c_void, - len, + buf.as_mut_ptr() as *mut _, + length, flags, &mut storage as *mut _ as *mut _, &mut addrlen, - ) { - -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => { + ) + }; + + match result { + c::SOCKET_ERROR => { + let error = unsafe { c::WSAGetLastError() }; + + if error == c::WSAESHUTDOWN { Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?)) + } else { + Err(io::Error::from_raw_os_error(error)) } - -1 => Err(last_error()), - n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)), } + _ => Ok((result as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)), } } @@ -318,20 +357,20 @@ impl Socket { } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { - let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD; + let length = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD; let mut nwritten = 0; - unsafe { - cvt(c::WSASend( + let result = unsafe { + c::WSASend( self.0, - bufs.as_ptr() as *const c::WSABUF as *mut c::WSABUF, - len, + bufs.as_ptr() as *const c::WSABUF as *mut _, + length, &mut nwritten, 0, ptr::null_mut(), ptr::null_mut(), - ))?; - } - Ok(nwritten as usize) + ) + }; + cvt(result).map(|_| nwritten as usize) } #[inline] @@ -384,14 +423,14 @@ impl Socket { Shutdown::Read => c::SD_RECEIVE, Shutdown::Both => c::SD_BOTH, }; - cvt(unsafe { c::shutdown(self.0, how) })?; - Ok(()) + let result = unsafe { c::shutdown(self.0, how) }; + cvt(result).map(drop) } pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_ulong; - let r = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) }; - if r == 0 { Ok(()) } else { Err(io::Error::last_os_error()) } + let result = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) }; + cvt(result).map(drop) } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 81dbea4a06..ae193b82e9 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests; -use crate::borrow::Borrow; +use crate::cmp; use crate::collections::BTreeMap; use crate::convert::{TryFrom, TryInto}; use crate::env; @@ -34,32 +34,115 @@ use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS}; // Command //////////////////////////////////////////////////////////////////////////////// -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Clone, Debug, Eq)] #[doc(hidden)] -pub struct EnvKey(OsString); +pub struct EnvKey { + os_string: OsString, + // This stores a UTF-16 encoded string to workaround the mismatch between + // Rust's OsString (WTF-8) and the Windows API string type (UTF-16). + // Normally converting on every API call is acceptable but here + // `c::CompareStringOrdinal` will be called for every use of `==`. + utf16: Vec, +} + +impl EnvKey { + fn new>(key: T) -> Self { + EnvKey::from(key.into()) + } +} + +// Comparing Windows environment variable keys[1] are behaviourally the +// composition of two operations[2]: +// +// 1. Case-fold both strings. This is done using a language-independent +// uppercase mapping that's unique to Windows (albeit based on data from an +// older Unicode spec). It only operates on individual UTF-16 code units so +// surrogates are left unchanged. This uppercase mapping can potentially change +// between Windows versions. +// +// 2. Perform an ordinal comparison of the strings. A comparison using ordinal +// is just a comparison based on the numerical value of each UTF-16 code unit[3]. +// +// Because the case-folding mapping is unique to Windows and not guaranteed to +// be stable, we ask the OS to compare the strings for us. This is done by +// calling `CompareStringOrdinal`[4] with `bIgnoreCase` set to `TRUE`. +// +// [1] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#choosing-a-stringcomparison-member-for-your-method-call +// [2] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#stringtoupper-and-stringtolower +// [3] https://docs.microsoft.com/en-us/dotnet/api/system.stringcomparison?view=net-5.0#System_StringComparison_Ordinal +// [4] https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-comparestringordinal +impl Ord for EnvKey { + fn cmp(&self, other: &Self) -> cmp::Ordering { + unsafe { + let result = c::CompareStringOrdinal( + self.utf16.as_ptr(), + self.utf16.len() as _, + other.utf16.as_ptr(), + other.utf16.len() as _, + c::TRUE, + ); + match result { + c::CSTR_LESS_THAN => cmp::Ordering::Less, + c::CSTR_EQUAL => cmp::Ordering::Equal, + c::CSTR_GREATER_THAN => cmp::Ordering::Greater, + // `CompareStringOrdinal` should never fail so long as the parameters are correct. + _ => panic!("comparing environment keys failed: {}", Error::last_os_error()), + } + } + } +} +impl PartialOrd for EnvKey { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl PartialEq for EnvKey { + fn eq(&self, other: &Self) -> bool { + if self.utf16.len() != other.utf16.len() { + false + } else { + self.cmp(other) == cmp::Ordering::Equal + } + } +} +impl PartialOrd for EnvKey { + fn partial_cmp(&self, other: &str) -> Option { + Some(self.cmp(&EnvKey::new(other))) + } +} +impl PartialEq for EnvKey { + fn eq(&self, other: &str) -> bool { + if self.os_string.len() != other.len() { + false + } else { + self.cmp(&EnvKey::new(other)) == cmp::Ordering::Equal + } + } +} +// Environment variable keys should preserve their original case even though +// they are compared using a caseless string mapping. impl From for EnvKey { - fn from(mut k: OsString) -> Self { - k.make_ascii_uppercase(); - EnvKey(k) + fn from(k: OsString) -> Self { + EnvKey { utf16: k.encode_wide().collect(), os_string: k } } } impl From for OsString { fn from(k: EnvKey) -> Self { - k.0 + k.os_string } } -impl Borrow for EnvKey { - fn borrow(&self) -> &OsStr { - &self.0 +impl From<&OsStr> for EnvKey { + fn from(k: &OsStr) -> Self { + Self::from(k.to_os_string()) } } impl AsRef for EnvKey { fn as_ref(&self) -> &OsStr { - &self.0 + &self.os_string } } @@ -73,7 +156,7 @@ fn ensure_no_nuls>(str: T) -> io::Result { pub struct Command { program: OsString, - args: Vec, + args: Vec, env: CommandEnv, cwd: Option, flags: u32, @@ -97,6 +180,14 @@ pub struct StdioPipes { pub stderr: Option, } +#[derive(Debug)] +enum Arg { + /// Add quotes (if needed) + Regular(OsString), + /// Append raw string without quoting + Raw(OsString), +} + impl Command { pub fn new(program: &OsStr) -> Command { Command { @@ -114,7 +205,7 @@ impl Command { } pub fn arg(&mut self, arg: &OsStr) { - self.args.push(arg.to_os_string()) + self.args.push(Arg::Regular(arg.to_os_string())) } pub fn env_mut(&mut self) -> &mut CommandEnv { &mut self.env @@ -139,6 +230,10 @@ impl Command { self.force_quotes_enabled = enabled; } + pub fn raw_arg(&mut self, command_str_to_append: &OsStr) { + self.args.push(Arg::Raw(command_str_to_append.to_os_string())) + } + pub fn get_program(&self) -> &OsStr { &self.program } @@ -166,7 +261,7 @@ impl Command { // to read the *child's* PATH if one is provided. See #15149 for more // details. let program = maybe_env.as_ref().and_then(|env| { - if let Some(v) = env.get(OsStr::new("PATH")) { + if let Some(v) = env.get(&EnvKey::new("PATH")) { // Split the value and test each path to see if the // program exists. for path in split_paths(&v) { @@ -207,7 +302,7 @@ impl Command { // the remaining portion of this spawn in a mutex. // // For more information, msdn also has an article about this race: - // http://support.microsoft.com/kb/315939 + // https://support.microsoft.com/kb/315939 static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new(); let _guard = unsafe { CREATE_PROCESS_LOCK.lock() }; @@ -251,9 +346,13 @@ impl Command { impl fmt::Debug for Command { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self.program)?; + self.program.fmt(f)?; for arg in &self.args { - write!(f, " {:?}", arg)?; + f.write_str(" ")?; + match arg { + Arg::Regular(s) => s.fmt(f), + Arg::Raw(s) => f.write_str(&s.to_string_lossy()), + }?; } Ok(()) } @@ -472,44 +571,63 @@ fn zeroed_process_information() -> c::PROCESS_INFORMATION { } } +enum Quote { + // Every arg is quoted + Always, + // Whitespace and empty args are quoted + Auto, + // Arg appended without any changes (#29494) + Never, +} + // Produces a wide string *without terminating null*; returns an error if // `prog` or any of the `args` contain a nul. -fn make_command_line(prog: &OsStr, args: &[OsString], force_quotes: bool) -> io::Result> { +fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Result> { // Encode the command and arguments in a command line string such // that the spawned process may recover them using CommandLineToArgvW. let mut cmd: Vec = Vec::new(); // Always quote the program name so CreateProcess doesn't interpret args as // part of the name if the binary wasn't found first time. - append_arg(&mut cmd, prog, true)?; + append_arg(&mut cmd, prog, Quote::Always)?; for arg in args { cmd.push(' ' as u16); - append_arg(&mut cmd, arg, force_quotes)?; + let (arg, quote) = match arg { + Arg::Regular(arg) => (arg, if force_quotes { Quote::Always } else { Quote::Auto }), + Arg::Raw(arg) => (arg, Quote::Never), + }; + append_arg(&mut cmd, arg, quote)?; } return Ok(cmd); - fn append_arg(cmd: &mut Vec, arg: &OsStr, force_quotes: bool) -> io::Result<()> { + fn append_arg(cmd: &mut Vec, arg: &OsStr, quote: Quote) -> io::Result<()> { // If an argument has 0 characters then we need to quote it to ensure // that it actually gets passed through on the command line or otherwise // it will be dropped entirely when parsed on the other end. ensure_no_nuls(arg)?; let arg_bytes = &arg.as_inner().inner.as_inner(); - let quote = force_quotes - || arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') - || arg_bytes.is_empty(); + let (quote, escape) = match quote { + Quote::Always => (true, true), + Quote::Auto => { + (arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') || arg_bytes.is_empty(), true) + } + Quote::Never => (false, false), + }; if quote { cmd.push('"' as u16); } let mut backslashes: usize = 0; for x in arg.encode_wide() { - if x == '\\' as u16 { - backslashes += 1; - } else { - if x == '"' as u16 { - // Add n+1 backslashes to total 2n+1 before internal '"'. - cmd.extend((0..=backslashes).map(|_| '\\' as u16)); + if escape { + if x == '\\' as u16 { + backslashes += 1; + } else { + if x == '"' as u16 { + // Add n+1 backslashes to total 2n+1 before internal '"'. + cmd.extend((0..=backslashes).map(|_| '\\' as u16)); + } + backslashes = 0; } - backslashes = 0; } cmd.push(x); } @@ -530,8 +648,15 @@ fn make_envp(maybe_env: Option>) -> io::Result<(*mut if let Some(env) = maybe_env { let mut blk = Vec::new(); + // If there are no environment variables to set then signal this by + // pushing a null. + if env.is_empty() { + blk.push(0); + } + for (k, v) in env { - blk.extend(ensure_no_nuls(k.0)?.encode_wide()); + ensure_no_nuls(k.os_string)?; + blk.extend(k.utf16); blk.push('=' as u16); blk.extend(ensure_no_nuls(v)?.encode_wide()); blk.push(0); @@ -555,13 +680,15 @@ fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec)> { } pub struct CommandArgs<'a> { - iter: crate::slice::Iter<'a, OsString>, + iter: crate::slice::Iter<'a, Arg>, } impl<'a> Iterator for CommandArgs<'a> { type Item = &'a OsStr; fn next(&mut self) -> Option<&'a OsStr> { - self.iter.next().map(|s| s.as_ref()) + self.iter.next().map(|arg| match arg { + Arg::Regular(s) | Arg::Raw(s) => s.as_ref(), + }) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs index 8830ae049c..3b65856dca 100644 --- a/library/std/src/sys/windows/process/tests.rs +++ b/library/std/src/sys/windows/process/tests.rs @@ -1,12 +1,35 @@ use super::make_command_line; +use super::Arg; +use crate::env; use crate::ffi::{OsStr, OsString}; +use crate::process::Command; + +#[test] +fn test_raw_args() { + let command_line = &make_command_line( + OsStr::new("quoted exe"), + &[ + Arg::Regular(OsString::from("quote me")), + Arg::Raw(OsString::from("quote me *not*")), + Arg::Raw(OsString::from("\t\\")), + Arg::Raw(OsString::from("internal \\\"backslash-\"quote")), + Arg::Regular(OsString::from("optional-quotes")), + ], + false, + ) + .unwrap(); + assert_eq!( + String::from_utf16(command_line).unwrap(), + "\"quoted exe\" \"quote me\" quote me *not* \t\\ internal \\\"backslash-\"quote optional-quotes" + ); +} #[test] fn test_make_command_line() { fn test_wrapper(prog: &str, args: &[&str], force_quotes: bool) -> String { let command_line = &make_command_line( OsStr::new(prog), - &args.iter().map(|a| OsString::from(a)).collect::>(), + &args.iter().map(|a| Arg::Regular(OsString::from(a))).collect::>(), force_quotes, ) .unwrap(); @@ -15,6 +38,11 @@ fn test_make_command_line() { assert_eq!(test_wrapper("prog", &["aaa", "bbb", "ccc"], false), "\"prog\" aaa bbb ccc"); + assert_eq!(test_wrapper("prog", &[r"C:\"], false), r#""prog" C:\"#); + assert_eq!(test_wrapper("prog", &[r"2slashes\\"], false), r#""prog" 2slashes\\"#); + assert_eq!(test_wrapper("prog", &[r" C:\"], false), r#""prog" " C:\\""#); + assert_eq!(test_wrapper("prog", &[r" 2slashes\\"], false), r#""prog" " 2slashes\\\\""#); + assert_eq!( test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa"], false), "\"C:\\Program Files\\blah\\blah.exe\" aaa" @@ -41,3 +69,62 @@ fn test_make_command_line() { "\"\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}\"" ); } + +// On Windows, environment args are case preserving but comparisons are case-insensitive. +// See: #85242 +#[test] +fn windows_env_unicode_case() { + let test_cases = [ + ("ä", "Ä"), + ("ß", "SS"), + ("Ä", "Ö"), + ("Ä", "Ö"), + ("I", "İ"), + ("I", "i"), + ("I", "ı"), + ("i", "I"), + ("i", "İ"), + ("i", "ı"), + ("İ", "I"), + ("İ", "i"), + ("İ", "ı"), + ("ı", "I"), + ("ı", "i"), + ("ı", "İ"), + ("ä", "Ä"), + ("ß", "SS"), + ("Ä", "Ö"), + ("Ä", "Ö"), + ("I", "İ"), + ("I", "i"), + ("I", "ı"), + ("i", "I"), + ("i", "İ"), + ("i", "ı"), + ("İ", "I"), + ("İ", "i"), + ("İ", "ı"), + ("ı", "I"), + ("ı", "i"), + ("ı", "İ"), + ]; + // Test that `cmd.env` matches `env::set_var` when setting two strings that + // may (or may not) be case-folded when compared. + for (a, b) in test_cases.iter() { + let mut cmd = Command::new("cmd"); + cmd.env(a, "1"); + cmd.env(b, "2"); + env::set_var(a, "1"); + env::set_var(b, "2"); + + for (key, value) in cmd.get_envs() { + assert_eq!( + env::var(key).ok(), + value.map(|s| s.to_string_lossy().into_owned()), + "command environment mismatch: {} {}", + a, + b + ); + } + } +} diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index 38839ea5e9..ef7a9733fd 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -1,5 +1,6 @@ use crate::ffi::CStr; use crate::io; +use crate::num::NonZeroUsize; use crate::ptr; use crate::sys::c; use crate::sys::handle::Handle; @@ -98,6 +99,21 @@ impl Thread { } } +pub fn available_concurrency() -> io::Result { + let res = unsafe { + let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed(); + c::GetSystemInfo(&mut sysinfo); + sysinfo.dwNumberOfProcessors as usize + }; + match res { + 0 => Err(io::Error::new_const( + io::ErrorKind::NotFound, + &"The number of hardware threads is not known for the target platform", + )), + cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }), + } +} + #[cfg_attr(test, allow(dead_code))] pub mod guard { pub type Guard = !; diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs index 065365e557..0bc5111466 100644 --- a/library/std/src/sys/windows/thread_local_key.rs +++ b/library/std/src/sys/windows/thread_local_key.rs @@ -35,7 +35,7 @@ pub type Dtor = unsafe extern "C" fn(*mut u8); // // For more details and nitty-gritty, see the code sections below! // -// [1]: http://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way +// [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 diff --git a/library/std/src/sys_common/bytestring.rs b/library/std/src/sys_common/bytestring.rs deleted file mode 100644 index 97fba60c27..0000000000 --- a/library/std/src/sys_common/bytestring.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![allow(dead_code)] - -#[cfg(test)] -mod tests; - -use crate::fmt::{Formatter, Result, Write}; -use core::str::lossy::{Utf8Lossy, Utf8LossyChunk}; - -pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter<'_>) -> Result { - // Writes out a valid unicode string with the correct escape sequences - fn write_str_escaped(f: &mut Formatter<'_>, s: &str) -> Result { - for c in s.chars().flat_map(|c| c.escape_debug()) { - f.write_char(c)? - } - Ok(()) - } - - f.write_str("\"")?; - for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(slice).chunks() { - write_str_escaped(f, valid)?; - for b in broken { - write!(f, "\\x{:02X}", b)?; - } - } - f.write_str("\"") -} diff --git a/library/std/src/sys_common/bytestring/tests.rs b/library/std/src/sys_common/bytestring/tests.rs deleted file mode 100644 index 1685f087d1..0000000000 --- a/library/std/src/sys_common/bytestring/tests.rs +++ /dev/null @@ -1,19 +0,0 @@ -use super::*; -use crate::fmt::{Debug, Formatter, Result}; - -#[test] -fn smoke() { - struct Helper<'a>(&'a [u8]); - - impl Debug for Helper<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - debug_fmt_bytestring(self.0, f) - } - } - - let input = b"\xF0hello,\tworld"; - let expected = r#""\xF0hello,\tworld""#; - let output = format!("{:?}", Helper(input)); - - assert!(output == expected); -} diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 1a9caa22c9..db83bad60d 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -21,7 +21,6 @@ mod tests; pub mod backtrace; -pub mod bytestring; pub mod condvar; pub mod fs; pub mod io; diff --git a/library/std/src/sys_common/os_str_bytes.rs b/library/std/src/sys_common/os_str_bytes.rs index 32705c432f..569600470d 100644 --- a/library/std/src/sys_common/os_str_bytes.rs +++ b/library/std/src/sys_common/os_str_bytes.rs @@ -2,36 +2,45 @@ //! systems: just a `Vec`/`[u8]`. use crate::borrow::Cow; -use crate::ffi::{OsStr, OsString}; use crate::fmt; +use crate::fmt::Write; use crate::mem; use crate::rc::Rc; -use crate::sealed::Sealed; use crate::str; use crate::sync::Arc; -use crate::sys_common::bytestring::debug_fmt_bytestring; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, IntoInner}; -use core::str::lossy::Utf8Lossy; +use core::str::lossy::{Utf8Lossy, Utf8LossyChunk}; + +#[cfg(test)] +mod tests; #[derive(Hash)] -pub(crate) struct Buf { +#[repr(transparent)] +pub struct Buf { pub inner: Vec, } -// FIXME: -// `Buf::as_slice` current implementation relies -// on `Slice` being layout-compatible with `[u8]`. -// When attribute privacy is implemented, `Slice` should be annotated as `#[repr(transparent)]`. -// Anyway, `Slice` representation and layout are considered implementation detail, are -// not documented and must not be relied upon. -pub(crate) struct Slice { +#[repr(transparent)] +pub struct Slice { pub inner: [u8], } impl fmt::Debug for Slice { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_fmt_bytestring(&self.inner, formatter) + // Writes out a valid unicode string with the correct escape sequences + + formatter.write_str("\"")?; + for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(&self.inner).chunks() { + for c in valid.chars().flat_map(|c| c.escape_debug()) { + formatter.write_char(c)? + } + + for b in broken { + write!(formatter, "\\x{:02X}", b)?; + } + } + formatter.write_str("\"") } } @@ -243,63 +252,3 @@ impl Slice { self.inner.eq_ignore_ascii_case(&other.inner) } } - -/// Platform-specific extensions to [`OsString`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStringExt: Sealed { - /// Creates an [`OsString`] from a byte vector. - /// - /// See the module documentation for an example. - #[stable(feature = "rust1", since = "1.0.0")] - fn from_vec(vec: Vec) -> Self; - - /// Yields the underlying byte vector of this [`OsString`]. - /// - /// See the module documentation for an example. - #[stable(feature = "rust1", since = "1.0.0")] - fn into_vec(self) -> Vec; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl OsStringExt for OsString { - fn from_vec(vec: Vec) -> OsString { - FromInner::from_inner(Buf { inner: vec }) - } - fn into_vec(self) -> Vec { - self.into_inner().inner - } -} - -/// Platform-specific extensions to [`OsStr`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStrExt: Sealed { - #[stable(feature = "rust1", since = "1.0.0")] - /// Creates an [`OsStr`] from a byte slice. - /// - /// See the module documentation for an example. - fn from_bytes(slice: &[u8]) -> &Self; - - /// Gets the underlying byte view of the [`OsStr`] slice. - /// - /// See the module documentation for an example. - #[stable(feature = "rust1", since = "1.0.0")] - fn as_bytes(&self) -> &[u8]; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl OsStrExt for OsStr { - #[inline] - fn from_bytes(slice: &[u8]) -> &OsStr { - unsafe { mem::transmute(slice) } - } - #[inline] - fn as_bytes(&self) -> &[u8] { - &self.as_inner().inner - } -} diff --git a/library/std/src/sys_common/os_str_bytes/tests.rs b/library/std/src/sys_common/os_str_bytes/tests.rs new file mode 100644 index 0000000000..3796737815 --- /dev/null +++ b/library/std/src/sys_common/os_str_bytes/tests.rs @@ -0,0 +1,10 @@ +use super::*; + +#[test] +fn slice_debug_output() { + let input = Slice::from_u8_slice(b"\xF0hello,\tworld"); + let expected = r#""\xF0hello,\tworld""#; + let output = format!("{:?}", input); + + assert_eq!(output, expected); +} diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index fe89b11043..38007d5c41 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -65,16 +65,18 @@ impl CommandEnv { // The following functions build up changes pub fn set(&mut self, key: &OsStr, value: &OsStr) { + let key = EnvKey::from(key); self.maybe_saw_path(&key); - self.vars.insert(key.to_owned().into(), Some(value.to_owned())); + self.vars.insert(key, Some(value.to_owned())); } pub fn remove(&mut self, key: &OsStr) { + let key = EnvKey::from(key); self.maybe_saw_path(&key); if self.clear { - self.vars.remove(key); + self.vars.remove(&key); } else { - self.vars.insert(key.to_owned().into(), None); + self.vars.insert(key, None); } } @@ -87,7 +89,7 @@ impl CommandEnv { self.saw_path || self.clear } - fn maybe_saw_path(&mut self, key: &OsStr) { + fn maybe_saw_path(&mut self, key: &EnvKey) { if !self.saw_path && key == "PATH" { self.saw_path = true; } diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 7d4b0d5283..1bd3cfd220 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -853,10 +853,11 @@ impl<'a> Iterator for EncodeWide<'a> { #[inline] fn size_hint(&self) -> (usize, Option) { let (low, high) = self.code_points.size_hint(); + let ext = (self.extra != 0) as usize; // every code point gets either one u16 or two u16, // so this iterator is between 1 or 2 times as // long as the underlying iterator. - (low, high.and_then(|n| n.checked_mul(2))) + (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext))) } } diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs index 385e01f92f..1bafbaa693 100644 --- a/library/std/src/sys_common/wtf8/tests.rs +++ b/library/std/src/sys_common/wtf8/tests.rs @@ -301,7 +301,7 @@ fn wtf8_slice() { #[test] #[should_panic] fn wtf8_slice_not_code_point_boundary() { - &Wtf8::from_str("aé 💩")[2..4]; + let _ = &Wtf8::from_str("aé 💩")[2..4]; } #[test] @@ -312,7 +312,7 @@ fn wtf8_slice_from() { #[test] #[should_panic] fn wtf8_slice_from_not_code_point_boundary() { - &Wtf8::from_str("aé 💩")[2..]; + let _ = &Wtf8::from_str("aé 💩")[2..]; } #[test] @@ -323,7 +323,7 @@ fn wtf8_slice_to() { #[test] #[should_panic] fn wtf8_slice_to_not_code_point_boundary() { - &Wtf8::from_str("aé 💩")[5..]; + let _ = &Wtf8::from_str("aé 💩")[5..]; } #[test] @@ -395,3 +395,15 @@ fn wtf8_encode_wide() { vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9] ); } + +#[test] +fn wtf8_encode_wide_size_hint() { + let string = Wtf8Buf::from_str("\u{12345}"); + let mut iter = string.encode_wide(); + assert_eq!((1, Some(8)), iter.size_hint()); + iter.next().unwrap(); + assert_eq!((1, Some(1)), iter.size_hint()); + iter.next().unwrap(); + assert_eq!((0, Some(0)), iter.size_hint()); + assert!(iter.next().is_none()); +} diff --git a/library/std/src/thread/available_concurrency.rs b/library/std/src/thread/available_concurrency.rs deleted file mode 100644 index e8cdde8801..0000000000 --- a/library/std/src/thread/available_concurrency.rs +++ /dev/null @@ -1,156 +0,0 @@ -use crate::io; -use crate::num::NonZeroUsize; - -/// Returns the number of hardware threads available to the program. -/// -/// This value should be considered only a hint. -/// -/// # Platform-specific behavior -/// -/// If interpreted as the number of actual hardware threads, it may undercount on -/// Windows systems with more than 64 hardware threads. If interpreted as the -/// available concurrency for that process, it may overcount on Windows systems -/// when limited by a process wide affinity mask or job object limitations, and -/// it may overcount on Linux systems when limited by a process wide affinity -/// mask or affected by cgroups limits. -/// -/// # Errors -/// -/// This function will return an error in the following situations, but is not -/// limited to just these cases: -/// -/// - If the number of hardware threads is not known for the target platform. -/// - The process lacks permissions to view the number of hardware threads -/// available. -/// -/// # Examples -/// -/// ``` -/// # #![allow(dead_code)] -/// #![feature(available_concurrency)] -/// use std::thread; -/// -/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1); -/// ``` -#[unstable(feature = "available_concurrency", issue = "74479")] -pub fn available_concurrency() -> io::Result { - available_concurrency_internal() -} - -cfg_if::cfg_if! { - if #[cfg(windows)] { - #[allow(nonstandard_style)] - fn available_concurrency_internal() -> io::Result { - #[repr(C)] - struct SYSTEM_INFO { - wProcessorArchitecture: u16, - wReserved: u16, - dwPageSize: u32, - lpMinimumApplicationAddress: *mut u8, - lpMaximumApplicationAddress: *mut u8, - dwActiveProcessorMask: *mut u8, - dwNumberOfProcessors: u32, - dwProcessorType: u32, - dwAllocationGranularity: u32, - wProcessorLevel: u16, - wProcessorRevision: u16, - } - extern "system" { - fn GetSystemInfo(info: *mut SYSTEM_INFO) -> i32; - } - let res = unsafe { - let mut sysinfo = crate::mem::zeroed(); - GetSystemInfo(&mut sysinfo); - sysinfo.dwNumberOfProcessors as usize - }; - match res { - 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), - cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }), - } - } - } else if #[cfg(any( - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "solaris", - target_os = "illumos", - ))] { - fn available_concurrency_internal() -> io::Result { - match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { - -1 => Err(io::Error::last_os_error()), - 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), - cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }), - } - } - } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] { - fn available_concurrency_internal() -> io::Result { - use crate::ptr; - - let mut cpus: libc::c_uint = 0; - let mut cpus_size = crate::mem::size_of_val(&cpus); - - unsafe { - cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint; - } - - // Fallback approach in case of errors or no hardware threads. - if cpus < 1 { - let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; - let res = unsafe { - libc::sysctl( - mib.as_mut_ptr(), - 2, - &mut cpus as *mut _ as *mut _, - &mut cpus_size as *mut _ as *mut _, - ptr::null_mut(), - 0, - ) - }; - - // Handle errors if any. - if res == -1 { - return Err(io::Error::last_os_error()); - } else if cpus == 0 { - return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); - } - } - Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) - } - } else if #[cfg(target_os = "openbsd")] { - fn available_concurrency_internal() -> io::Result { - use crate::ptr; - - let mut cpus: libc::c_uint = 0; - let mut cpus_size = crate::mem::size_of_val(&cpus); - let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; - - let res = unsafe { - libc::sysctl( - mib.as_mut_ptr(), - 2, - &mut cpus as *mut _ as *mut _, - &mut cpus_size as *mut _ as *mut _, - ptr::null_mut(), - 0, - ) - }; - - // Handle errors if any. - if res == -1 { - return Err(io::Error::last_os_error()); - } else if cpus == 0 { - return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); - } - - Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) - } - } else { - // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re - fn available_concurrency_internal() -> io::Result { - Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")) - } - } -} diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index e62f4440b3..c53290ec0c 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -324,10 +324,9 @@ macro_rules! __thread_local_inner { /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with). #[stable(feature = "thread_local_try_with", since = "1.26.0")] +#[non_exhaustive] #[derive(Clone, Copy, Eq, PartialEq)] -pub struct AccessError { - _private: (), -} +pub struct AccessError; #[stable(feature = "thread_local_try_with", since = "1.26.0")] impl fmt::Debug for AccessError { @@ -396,7 +395,7 @@ impl LocalKey { F: FnOnce(&T) -> R, { unsafe { - let thread_local = (self.inner)().ok_or(AccessError { _private: () })?; + let thread_local = (self.inner)().ok_or(AccessError)?; Ok(f(thread_local)) } } diff --git a/library/std/src/thread/local/tests.rs b/library/std/src/thread/local/tests.rs index f33d612961..1df1ca758c 100644 --- a/library/std/src/thread/local/tests.rs +++ b/library/std/src/thread/local/tests.rs @@ -297,7 +297,7 @@ fn join_orders_after_tls_destructors() { .unwrap(); loop { - match SYNC_STATE.compare_exchange_weak( + match SYNC_STATE.compare_exchange( THREAD1_WAITING, MAIN_THREAD_RENDEZVOUS, Ordering::SeqCst, diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 30d8c2a1b6..9f7e6b95df 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -155,6 +155,7 @@ use crate::fmt; use crate::io; use crate::mem; use crate::num::NonZeroU64; +use crate::num::NonZeroUsize; use crate::panic; use crate::panicking; use crate::str; @@ -174,15 +175,9 @@ use crate::time::Duration; #[macro_use] mod local; -#[unstable(feature = "available_concurrency", issue = "74479")] -mod available_concurrency; - #[stable(feature = "rust1", since = "1.0.0")] pub use self::local::{AccessError, LocalKey}; -#[unstable(feature = "available_concurrency", issue = "74479")] -pub use available_concurrency::available_concurrency; - // The types used by the thread_local! macro to access TLS keys. Note that there // are two types, the "OS" type and the "fast" type. The OS thread local key // type is accessed via platform-specific API calls and is slow, while the fast @@ -656,22 +651,23 @@ pub fn current() -> Thread { /// Cooperatively gives up a timeslice to the OS scheduler. /// -/// This is used when the programmer knows that the thread will have nothing -/// to do for some time, and thus avoid wasting computing time. -/// -/// For example when polling on a resource, it is common to check that it is -/// available, and if not to yield in order to avoid busy waiting. +/// This calls the underlying OS scheduler's yield primitive, signaling +/// that the calling thread is willing to give up its remaining timeslice +/// so that the OS may schedule other threads on the CPU. /// -/// Thus the pattern of `yield`ing after a failed poll is rather common when -/// implementing low-level shared resources or synchronization primitives. +/// A drawback of yielding in a loop is that if the OS does not have any +/// other ready threads to run on the current CPU, the thread will effectively +/// busy-wait, which wastes CPU time and energy. /// -/// However programmers will usually prefer to use [`channel`]s, [`Condvar`]s, -/// [`Mutex`]es or [`join`] for their synchronization routines, as they avoid -/// thinking about thread scheduling. +/// Therefore, when waiting for events of interest, a programmer's first +/// choice should be to use synchronization devices such as [`channel`]s, +/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are +/// implemented in a blocking manner, giving up the CPU until the event +/// of interest has occurred which avoids repeated yielding. /// -/// Note that [`channel`]s for example are implemented using this primitive. -/// Indeed when you call `send` or `recv`, which are blocking, they will yield -/// if the channel is not available. +/// `yield_now` should thus be used only rarely, mostly in situations where +/// repeated polling is required because there is no other suitable way to +/// learn when an event of interest has occurred. /// /// # Examples /// @@ -1003,11 +999,12 @@ impl ThreadId { static mut COUNTER: u64 = 1; unsafe { - let _guard = GUARD.lock(); + let guard = GUARD.lock(); // If we somehow use up all our bits, panic so that we're not // covering up subtle bugs of IDs being reused. if COUNTER == u64::MAX { + drop(guard); // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire. panic!("failed to generate unique thread ID: bitspace exhausted"); } @@ -1422,3 +1419,39 @@ fn _assert_sync_and_send() { _assert_both::>(); _assert_both::(); } + +/// Returns the number of hardware threads available to the program. +/// +/// This value should be considered only a hint. +/// +/// # Platform-specific behavior +/// +/// If interpreted as the number of actual hardware threads, it may undercount on +/// Windows systems with more than 64 hardware threads. If interpreted as the +/// available concurrency for that process, it may overcount on Windows systems +/// when limited by a process wide affinity mask or job object limitations, and +/// it may overcount on Linux systems when limited by a process wide affinity +/// mask or affected by cgroups limits. +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// - If the number of hardware threads is not known for the target platform. +/// - The process lacks permissions to view the number of hardware threads +/// available. +/// +/// # Examples +/// +/// ``` +/// # #![allow(dead_code)] +/// #![feature(available_concurrency)] +/// use std::thread; +/// +/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1); +/// ``` +#[unstable(feature = "available_concurrency", issue = "74479")] +pub fn available_concurrency() -> io::Result { + imp::available_concurrency() +} diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 899cf6841e..003069b338 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -168,7 +168,7 @@ pub struct Instant(time::Instant); /// /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode -/// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html +/// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html /// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime /// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get /// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime diff --git a/library/stdarch/crates/core_arch/src/x86/bt.rs b/library/stdarch/crates/core_arch/src/x86/bt.rs index 278ddf9543..37429d3db0 100644 --- a/library/stdarch/crates/core_arch/src/x86/bt.rs +++ b/library/stdarch/crates/core_arch/src/x86/bt.rs @@ -20,7 +20,7 @@ macro_rules! bt { /// Returns the bit in position `b` of the memory addressed by `p`. #[inline] #[cfg_attr(test, assert_instr(bt))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 { let r: u8; asm!( @@ -37,7 +37,7 @@ pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 { /// Returns the bit in position `b` of the memory addressed by `p`, then sets the bit to `1`. #[inline] #[cfg_attr(test, assert_instr(bts))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 { let r: u8; asm!( @@ -54,7 +54,7 @@ pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 { /// Returns the bit in position `b` of the memory addressed by `p`, then resets that bit to `0`. #[inline] #[cfg_attr(test, assert_instr(btr))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 { let r: u8; asm!( @@ -71,7 +71,7 @@ pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 { /// Returns the bit in position `b` of the memory addressed by `p`, then inverts that bit. #[inline] #[cfg_attr(test, assert_instr(btc))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittestandcomplement(p: *mut i32, b: i32) -> u8 { let r: u8; asm!( diff --git a/library/stdarch/crates/core_arch/src/x86_64/bt.rs b/library/stdarch/crates/core_arch/src/x86_64/bt.rs index 6e8579fa25..f2aa45d8ea 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/bt.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/bt.rs @@ -20,7 +20,7 @@ macro_rules! bt { /// Returns the bit in position `b` of the memory addressed by `p`. #[inline] #[cfg_attr(test, assert_instr(bt))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 { let r: u8; asm!( @@ -37,7 +37,7 @@ pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 { /// Returns the bit in position `b` of the memory addressed by `p`, then sets the bit to `1`. #[inline] #[cfg_attr(test, assert_instr(bts))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 { let r: u8; asm!( @@ -54,7 +54,7 @@ pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 { /// Returns the bit in position `b` of the memory addressed by `p`, then resets that bit to `0`. #[inline] #[cfg_attr(test, assert_instr(btr))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 { let r: u8; asm!( @@ -71,7 +71,7 @@ pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 { /// Returns the bit in position `b` of the memory addressed by `p`, then inverts that bit. #[inline] #[cfg_attr(test, assert_instr(btc))] -#[unstable(feature = "simd_x86_bittest", issue = "59414")] +#[stable(feature = "simd_x86_bittest", since = "1.55.0")] pub unsafe fn _bittestandcomplement64(p: *mut i64, b: i64) -> u8 { let r: u8; asm!( diff --git a/library/term/Cargo.toml b/library/term/Cargo.toml deleted file mode 100644 index ddf85b5c5b..0000000000 --- a/library/term/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "term" -version = "0.0.0" -edition = "2018" - -[dependencies] -core = { path = "../core" } -std = { path = "../std" } diff --git a/library/term/src/lib.rs b/library/term/src/lib.rs deleted file mode 100644 index 943b276a22..0000000000 --- a/library/term/src/lib.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! Terminal formatting library. -//! -//! This crate provides the `Terminal` trait, which abstracts over an [ANSI -//! Terminal][ansi] to provide color printing, among other things. There are two -//! implementations, the `TerminfoTerminal`, which uses control characters from -//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console -//! API][win]. -//! -//! # Examples -//! -//! ```no_run -//! # #![feature(rustc_private)] -//! extern crate term; -//! use std::io::prelude::*; -//! -//! fn main() { -//! let mut t = term::stdout().unwrap(); -//! -//! t.fg(term::color::GREEN).unwrap(); -//! write!(t, "hello, ").unwrap(); -//! -//! t.fg(term::color::RED).unwrap(); -//! writeln!(t, "world!").unwrap(); -//! -//! assert!(t.reset().unwrap()); -//! } -//! ``` -//! -//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code -//! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications -//! [ti]: https://en.wikipedia.org/wiki/Terminfo - -#![doc(html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] -#![deny(missing_docs)] -#![cfg_attr(windows, feature(libc))] - -use std::io::prelude::*; -use std::io::{self, Stderr, Stdout}; - -pub use terminfo::TerminfoTerminal; -#[cfg(windows)] -pub use win::WinConsole; - -pub mod terminfo; - -#[cfg(windows)] -mod win; - -/// Alias for stdout terminals. -pub type StdoutTerminal = dyn Terminal + Send; -/// Alias for stderr terminals. -pub type StderrTerminal = dyn Terminal + Send; - -#[cfg(not(windows))] -/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be -/// opened. -pub fn stdout() -> Option> { - TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box) -} - -#[cfg(windows)] -/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be -/// opened. -pub fn stdout() -> Option> { - TerminfoTerminal::new(io::stdout()) - .map(|t| Box::new(t) as Box) - .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box)) -} - -#[cfg(not(windows))] -/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be -/// opened. -pub fn stderr() -> Option> { - TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box) -} - -#[cfg(windows)] -/// Returns a Terminal wrapping stderr, or None if a terminal couldn't be -/// opened. -pub fn stderr() -> Option> { - TerminfoTerminal::new(io::stderr()) - .map(|t| Box::new(t) as Box) - .or_else(|| WinConsole::new(io::stderr()).ok().map(|t| Box::new(t) as Box)) -} - -/// Terminal color definitions -#[allow(missing_docs)] -pub mod color { - /// Number for a terminal color - pub type Color = u32; - - pub const BLACK: Color = 0; - pub const RED: Color = 1; - pub const GREEN: Color = 2; - pub const YELLOW: Color = 3; - pub const BLUE: Color = 4; - pub const MAGENTA: Color = 5; - pub const CYAN: Color = 6; - pub const WHITE: Color = 7; - - pub const BRIGHT_BLACK: Color = 8; - pub const BRIGHT_RED: Color = 9; - pub const BRIGHT_GREEN: Color = 10; - pub const BRIGHT_YELLOW: Color = 11; - pub const BRIGHT_BLUE: Color = 12; - pub const BRIGHT_MAGENTA: Color = 13; - pub const BRIGHT_CYAN: Color = 14; - pub const BRIGHT_WHITE: Color = 15; -} - -/// Terminal attributes for use with term.attr(). -/// -/// Most attributes can only be turned on and must be turned off with term.reset(). -/// The ones that can be turned off explicitly take a boolean value. -/// Color is also represented as an attribute for convenience. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum Attr { - /// Bold (or possibly bright) mode - Bold, - /// Dim mode, also called faint or half-bright. Often not supported - Dim, - /// Italics mode. Often not supported - Italic(bool), - /// Underline mode - Underline(bool), - /// Blink mode - Blink, - /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold - Standout(bool), - /// Reverse mode, inverts the foreground and background colors - Reverse, - /// Secure mode, also called invis mode. Hides the printed text - Secure, - /// Convenience attribute to set the foreground color - ForegroundColor(color::Color), - /// Convenience attribute to set the background color - BackgroundColor(color::Color), -} - -/// A terminal with similar capabilities to an ANSI Terminal -/// (foreground/background colors etc). -pub trait Terminal: Write { - /// The terminal's output writer type. - type Output: Write; - - /// Sets the foreground color to the given color. - /// - /// If the color is a bright color, but the terminal only supports 8 colors, - /// the corresponding normal color will be used instead. - /// - /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` - /// if there was an I/O error. - fn fg(&mut self, color: color::Color) -> io::Result; - - /// Sets the background color to the given color. - /// - /// If the color is a bright color, but the terminal only supports 8 colors, - /// the corresponding normal color will be used instead. - /// - /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` - /// if there was an I/O error. - fn bg(&mut self, color: color::Color) -> io::Result; - - /// Sets the given terminal attribute, if supported. Returns `Ok(true)` - /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if - /// there was an I/O error. - fn attr(&mut self, attr: Attr) -> io::Result; - - /// Returns `true` if the given terminal attribute is supported. - fn supports_attr(&self, attr: Attr) -> bool; - - /// Resets all terminal attributes and colors to their defaults. - /// - /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there - /// was an I/O error. - /// - /// *Note: This does not flush.* - /// - /// That means the reset command may get buffered so, if you aren't planning on doing anything - /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after - /// calling reset. - fn reset(&mut self) -> io::Result; - - /// Gets an immutable reference to the stream inside - fn get_ref(&self) -> &Self::Output; - - /// Gets a mutable reference to the stream inside - fn get_mut(&mut self) -> &mut Self::Output; - - /// Returns the contained stream, destroying the `Terminal` - fn into_inner(self) -> Self::Output - where - Self: Sized; -} diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 226557430d..479d86354c 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -10,7 +10,6 @@ crate-type = ["dylib", "rlib"] [dependencies] cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } -term = { path = "../term" } std = { path = "../std" } core = { path = "../core" } libc = { version = "0.2", default-features = false } diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 9cfc7eaf4b..54e30a1fcd 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -13,7 +13,7 @@ use super::{ formatters::{JsonFormatter, JunitFormatter, OutputFormatter, PrettyFormatter, TerseFormatter}, helpers::{concurrency::get_concurrency, metrics::MetricMap}, options::{Options, OutputFormat}, - run_tests, + run_tests, term, test_result::TestResult, time::{TestExecTime, TestSuiteExecTime}, types::{NamePadding, TestDesc, TestDescAndFn}, diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index ec66fc1219..c4b0e1e5c2 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -79,7 +79,7 @@ impl OutputFormatter for JunitFormatter { name=\"{}\" time=\"{}\">", class_name, test_name, - duration.as_secs() + duration.as_secs_f64() ))?; self.write_message("")?; self.write_message("")?; @@ -91,7 +91,7 @@ impl OutputFormatter for JunitFormatter { name=\"{}\" time=\"{}\">", class_name, test_name, - duration.as_secs() + duration.as_secs_f64() ))?; self.write_message(&*format!("", m))?; self.write_message("")?; @@ -103,7 +103,7 @@ impl OutputFormatter for JunitFormatter { name=\"{}\" time=\"{}\">", class_name, test_name, - duration.as_secs() + duration.as_secs_f64() ))?; self.write_message("")?; self.write_message("")?; @@ -123,7 +123,7 @@ impl OutputFormatter for JunitFormatter { name=\"{}\" time=\"{}\"/>", class_name, test_name, - duration.as_secs() + duration.as_secs_f64() ))?; } } diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index e17fc08a9a..9cad71e30b 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -4,6 +4,7 @@ use super::OutputFormatter; use crate::{ bench::fmt_bench_samples, console::{ConsoleTestState, OutputLocation}, + term, test_result::TestResult, time, types::TestDesc, diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index a2c223c494..0c8215c5da 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -4,6 +4,7 @@ use super::OutputFormatter; use crate::{ bench::fmt_bench_samples, console::{ConsoleTestState, OutputLocation}, + term, test_result::TestResult, time, types::NamePadding, diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 3da4d434f4..251f099f28 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -20,7 +20,7 @@ #![crate_name = "test"] #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] -#![cfg_attr(unix, feature(libc))] +#![feature(libc)] #![feature(rustc_private)] #![feature(nll)] #![feature(available_concurrency)] @@ -80,6 +80,7 @@ mod formatters; mod helpers; mod options; pub mod stats; +mod term; mod test_result; mod time; mod types; diff --git a/library/test/src/stats.rs b/library/test/src/stats.rs index 53f3889447..45fae9c76b 100644 --- a/library/test/src/stats.rs +++ b/library/test/src/stats.rs @@ -19,7 +19,7 @@ pub trait Stats { /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric /// Predicates"][paper] /// - /// [paper]: http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps + /// [paper]: https://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps fn sum(&self) -> f64; /// Minimum value of the samples. diff --git a/library/test/src/term.rs b/library/test/src/term.rs new file mode 100644 index 0000000000..b256ab7b8f --- /dev/null +++ b/library/test/src/term.rs @@ -0,0 +1,85 @@ +//! Terminal formatting module. +//! +//! This module provides the `Terminal` trait, which abstracts over an [ANSI +//! Terminal][ansi] to provide color printing, among other things. There are two +//! implementations, the `TerminfoTerminal`, which uses control characters from +//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console +//! API][win]. +//! +//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code +//! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications +//! [ti]: https://en.wikipedia.org/wiki/Terminfo + +#![deny(missing_docs)] + +use std::io::{self, prelude::*}; + +pub(crate) use terminfo::TerminfoTerminal; +#[cfg(windows)] +pub(crate) use win::WinConsole; + +pub(crate) mod terminfo; + +#[cfg(windows)] +mod win; + +/// Alias for stdout terminals. +pub(crate) type StdoutTerminal = dyn Terminal + Send; + +#[cfg(not(windows))] +/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be +/// opened. +pub(crate) fn stdout() -> Option> { + TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box) +} + +#[cfg(windows)] +/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be +/// opened. +pub(crate) fn stdout() -> Option> { + TerminfoTerminal::new(io::stdout()) + .map(|t| Box::new(t) as Box) + .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box)) +} + +/// Terminal color definitions +#[allow(missing_docs)] +#[cfg_attr(not(windows), allow(dead_code))] +pub(crate) mod color { + /// Number for a terminal color + pub(crate) type Color = u32; + + pub(crate) const BLACK: Color = 0; + pub(crate) const RED: Color = 1; + pub(crate) const GREEN: Color = 2; + pub(crate) const YELLOW: Color = 3; + pub(crate) const BLUE: Color = 4; + pub(crate) const MAGENTA: Color = 5; + pub(crate) const CYAN: Color = 6; + pub(crate) const WHITE: Color = 7; +} + +/// A terminal with similar capabilities to an ANSI Terminal +/// (foreground/background colors etc). +pub trait Terminal: Write { + /// Sets the foreground color to the given color. + /// + /// If the color is a bright color, but the terminal only supports 8 colors, + /// the corresponding normal color will be used instead. + /// + /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` + /// if there was an I/O error. + fn fg(&mut self, color: color::Color) -> io::Result; + + /// Resets all terminal attributes and colors to their defaults. + /// + /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there + /// was an I/O error. + /// + /// *Note: This does not flush.* + /// + /// That means the reset command may get buffered so, if you aren't planning on doing anything + /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after + /// calling reset. + fn reset(&mut self) -> io::Result; +} diff --git a/library/term/src/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs similarity index 69% rename from library/term/src/terminfo/mod.rs rename to library/test/src/term/terminfo/mod.rs index fec59aaa0c..f4c5a05d1e 100644 --- a/library/term/src/terminfo/mod.rs +++ b/library/test/src/term/terminfo/mod.rs @@ -8,9 +8,8 @@ use std::fs::File; use std::io::{self, prelude::*, BufReader}; use std::path::Path; -use crate::color; -use crate::Attr; -use crate::Terminal; +use super::color; +use super::Terminal; use parm::{expand, Param, Variables}; use parser::compiled::{msys_terminfo, parse}; @@ -18,20 +17,20 @@ use searcher::get_dbpath_for_term; /// A parsed terminfo database entry. #[derive(Debug)] -pub struct TermInfo { +pub(crate) struct TermInfo { /// Names for the terminal - pub names: Vec, + pub(crate) names: Vec, /// Map of capability name to boolean value - pub bools: HashMap, + pub(crate) bools: HashMap, /// Map of capability name to numeric value - pub numbers: HashMap, + pub(crate) numbers: HashMap, /// Map of capability name to raw (unexpanded) string - pub strings: HashMap>, + pub(crate) strings: HashMap>, } /// A terminfo creation error. #[derive(Debug)] -pub enum Error { +pub(crate) enum Error { /// TermUnset Indicates that the environment doesn't include enough information to find /// the terminfo entry. TermUnset, @@ -64,7 +63,7 @@ impl fmt::Display for Error { impl TermInfo { /// Creates a TermInfo based on current environment. - pub fn from_env() -> Result { + pub(crate) fn from_env() -> Result { let term = match env::var("TERM") { Ok(name) => TermInfo::from_name(&name), Err(..) => return Err(Error::TermUnset), @@ -79,7 +78,7 @@ impl TermInfo { } /// Creates a TermInfo for the named terminal. - pub fn from_name(name: &str) -> Result { + pub(crate) fn from_name(name: &str) -> Result { get_dbpath_for_term(name) .ok_or_else(|| { Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found")) @@ -88,7 +87,7 @@ impl TermInfo { } /// Parse the given TermInfo. - pub fn from_path>(path: P) -> Result { + pub(crate) fn from_path>(path: P) -> Result { Self::_from_path(path.as_ref()) } // Keep the metadata small @@ -99,43 +98,24 @@ impl TermInfo { } } -pub mod searcher; +pub(crate) mod searcher; /// TermInfo format parsing. -pub mod parser { +pub(crate) mod parser { //! ncurses-compatible compiled terminfo format parsing (term(5)) - pub mod compiled; -} -pub mod parm; - -fn cap_for_attr(attr: Attr) -> &'static str { - match attr { - Attr::Bold => "bold", - Attr::Dim => "dim", - Attr::Italic(true) => "sitm", - Attr::Italic(false) => "ritm", - Attr::Underline(true) => "smul", - Attr::Underline(false) => "rmul", - Attr::Blink => "blink", - Attr::Standout(true) => "smso", - Attr::Standout(false) => "rmso", - Attr::Reverse => "rev", - Attr::Secure => "invis", - Attr::ForegroundColor(_) => "setaf", - Attr::BackgroundColor(_) => "setab", - } + pub(crate) mod compiled; } +pub(crate) mod parm; /// A Terminal that knows how many colors it supports, with a reference to its /// parsed Terminfo database record. -pub struct TerminfoTerminal { +pub(crate) struct TerminfoTerminal { num_colors: u32, out: T, ti: TermInfo, } impl Terminal for TerminfoTerminal { - type Output = T; fn fg(&mut self, color: color::Color) -> io::Result { let color = self.dim_if_necessary(color); if self.num_colors > color { @@ -144,32 +124,6 @@ impl Terminal for TerminfoTerminal { Ok(false) } - fn bg(&mut self, color: color::Color) -> io::Result { - let color = self.dim_if_necessary(color); - if self.num_colors > color { - return self.apply_cap("setab", &[Param::Number(color as i32)]); - } - Ok(false) - } - - fn attr(&mut self, attr: Attr) -> io::Result { - match attr { - Attr::ForegroundColor(c) => self.fg(c), - Attr::BackgroundColor(c) => self.bg(c), - _ => self.apply_cap(cap_for_attr(attr), &[]), - } - } - - fn supports_attr(&self, attr: Attr) -> bool { - match attr { - Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0, - _ => { - let cap = cap_for_attr(attr); - self.ti.strings.get(cap).is_some() - } - } - } - fn reset(&mut self) -> io::Result { // are there any terminals that have color/attrs and not sgr0? // Try falling back to sgr, then op @@ -182,26 +136,11 @@ impl Terminal for TerminfoTerminal { }; self.out.write_all(&cmd).and(Ok(true)) } - - fn get_ref(&self) -> &T { - &self.out - } - - fn get_mut(&mut self) -> &mut T { - &mut self.out - } - - fn into_inner(self) -> T - where - Self: Sized, - { - self.out - } } impl TerminfoTerminal { /// Creates a new TerminfoTerminal with the given TermInfo and Write. - pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal { + pub(crate) fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal { let nc = if terminfo.strings.contains_key("setaf") && terminfo.strings.contains_key("setab") { terminfo.numbers.get("colors").map_or(0, |&n| n) @@ -215,7 +154,7 @@ impl TerminfoTerminal { /// Creates a new TerminfoTerminal for the current environment with the given Write. /// /// Returns `None` when the terminfo cannot be found or parsed. - pub fn new(out: T) -> Option> { + pub(crate) fn new(out: T) -> Option> { TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok() } diff --git a/library/term/src/terminfo/parm.rs b/library/test/src/term/terminfo/parm.rs similarity index 92% rename from library/term/src/terminfo/parm.rs rename to library/test/src/term/terminfo/parm.rs index 2e4e917891..0d37eb7359 100644 --- a/library/term/src/terminfo/parm.rs +++ b/library/test/src/term/terminfo/parm.rs @@ -35,13 +35,12 @@ enum FormatState { /// Types of parameters a capability can use #[allow(missing_docs)] #[derive(Clone)] -pub enum Param { - Words(String), +pub(crate) enum Param { Number(i32), } /// Container for static and dynamic variable arrays -pub struct Variables { +pub(crate) struct Variables { /// Static variables A-Z sta_va: [Param; 26], /// Dynamic variables a-z @@ -50,7 +49,7 @@ pub struct Variables { impl Variables { /// Returns a new zero-initialized Variables - pub fn new() -> Variables { + pub(crate) fn new() -> Variables { Variables { sta_va: [ Number(0), @@ -121,7 +120,11 @@ impl Variables { /// /// To be compatible with ncurses, `vars` should be the same between calls to `expand` for /// multiple capabilities for the same terminal. -pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result, String> { +pub(crate) fn expand( + cap: &[u8], + params: &[Param], + vars: &mut Variables, +) -> Result, String> { let mut state = Nothing; // expanded cap will only rarely be larger than the cap itself @@ -168,7 +171,6 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result output.push(128u8), // Don't check bounds. ncurses just casts and truncates. Some(Number(c)) => output.push(c as u8), - Some(_) => return Err("a non-char was used with %c".to_string()), None => return Err("stack is empty".to_string()), } } @@ -178,7 +180,6 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result state = CharConstant, '{' => state = IntConstant(0), 'l' => match stack.pop() { - Some(Words(s)) => stack.push(Number(s.len() as i32)), Some(_) => return Err("a non-str was used with %l".to_string()), None => return Err("stack is empty".to_string()), }, @@ -195,9 +196,6 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result x % y, _ => unreachable!("All cases handled"), })), - (Some(_), Some(_)) => { - return Err(format!("non-numbers on stack with {}", cur)); - } _ => return Err("stack is empty".to_string()), } } @@ -216,9 +214,6 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result { - return Err(format!("non-numbers on stack with {}", cur)); - } _ => return Err("stack is empty".to_string()), }, '!' | '~' => match stack.pop() { @@ -228,7 +223,6 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result !x, _ => unreachable!(), })), - Some(_) => return Err(format!("non-numbers on stack with {}", cur)), None => return Err("stack is empty".to_string()), }, 'i' => match (&mparams[0], &mparams[1]) { @@ -236,7 +230,6 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result return Err("first two params not numbers with %i".to_string()), }, // printf-style support for %doxXs @@ -271,7 +264,6 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result match stack.pop() { Some(Number(0)) => state = SeekIfElse(0), Some(Number(_)) => (), - Some(_) => return Err("non-number on stack with conditional".to_string()), None => return Err("stack is empty".to_string()), }, 'e' => state = SeekIfEnd(0), @@ -480,15 +472,6 @@ impl FormatOp { _ => panic!("bad FormatOp char"), } } - fn to_char(self) -> char { - match self { - FormatOp::Digit => 'd', - FormatOp::Octal => 'o', - FormatOp::LowerHex => 'x', - FormatOp::UpperHex => 'X', - FormatOp::String => 's', - } - } } fn format(val: Param, op: FormatOp, flags: Flags) -> Result, String> { @@ -533,16 +516,6 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result, String> { } .into_bytes() } - Words(s) => match op { - FormatOp::String => { - let mut s = s.into_bytes(); - if flags.precision > 0 && flags.precision < s.len() { - s.truncate(flags.precision); - } - s - } - _ => return Err(format!("non-string on stack with %{}", op.to_char())), - }, }; if flags.width > s.len() { let n = flags.width - s.len(); diff --git a/library/term/src/terminfo/parm/tests.rs b/library/test/src/term/terminfo/parm/tests.rs similarity index 87% rename from library/term/src/terminfo/parm/tests.rs rename to library/test/src/term/terminfo/parm/tests.rs index 1cc0967c8f..256d1aaf44 100644 --- a/library/term/src/terminfo/parm/tests.rs +++ b/library/test/src/term/terminfo/parm/tests.rs @@ -51,7 +51,10 @@ fn test_param_stack_failure_conditions() { for &cap in caps.iter() { let res = get_res("", cap, &[], vars); assert!(res.is_err(), "Op {} succeeded incorrectly with 0 stack entries", cap); - let p = if cap == "%s" || cap == "%l" { Words("foo".to_string()) } else { Number(97) }; + if cap == "%s" || cap == "%l" { + continue; + } + let p = Number(97); let res = get_res("%p1", cap, &[p], vars); assert!(res.is_ok(), "Op {} failed with 1 stack entry: {}", cap, res.unwrap_err()); } @@ -109,23 +112,6 @@ fn test_conditionals() { fn test_format() { let mut varstruct = Variables::new(); let vars = &mut varstruct; - assert_eq!( - expand( - b"%p1%s%p2%2s%p3%2s%p4%.2s", - &[ - Words("foo".to_string()), - Words("foo".to_string()), - Words("f".to_string()), - Words("foo".to_string()) - ], - vars - ), - Ok("foofoo ffo".bytes().collect::>()) - ); - assert_eq!( - expand(b"%p1%:-4.2s", &[Words("foo".to_string())], vars), - Ok("fo ".bytes().collect::>()) - ); assert_eq!( expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars), diff --git a/library/term/src/terminfo/parser/compiled.rs b/library/test/src/term/terminfo/parser/compiled.rs similarity index 96% rename from library/term/src/terminfo/parser/compiled.rs rename to library/test/src/term/terminfo/parser/compiled.rs index fbc5aebdb2..b24f3f8b05 100644 --- a/library/term/src/terminfo/parser/compiled.rs +++ b/library/test/src/term/terminfo/parser/compiled.rs @@ -13,7 +13,7 @@ mod tests; // These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable. #[rustfmt::skip] -pub static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin", +pub(crate) static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin", "no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type", "hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above", "memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok", @@ -26,13 +26,13 @@ pub static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin", "return_does_clr_eol"]; #[rustfmt::skip] -pub static boolnames: &[&str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", +pub(crate) static boolnames: &[&str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; #[rustfmt::skip] -pub static numfnames: &[&str] = &[ "columns", "init_tabs", "lines", +pub(crate) static numfnames: &[&str] = &[ "columns", "init_tabs", "lines", "lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal", "width_status_line", "num_labels", "label_height", "label_width", "max_attributes", "maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity", @@ -43,13 +43,13 @@ pub static numfnames: &[&str] = &[ "columns", "init_tabs", "lines", "new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"]; #[rustfmt::skip] -pub static numnames: &[&str] = &[ "cols", "it", "lines", "lm", "xmc", "pb", +pub(crate) static numnames: &[&str] = &[ "cols", "it", "lines", "lm", "xmc", "pb", "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv", "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs", "btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"]; #[rustfmt::skip] -pub static stringfnames: &[&str] = &[ "back_tab", "bell", "carriage_return", +pub(crate) static stringfnames: &[&str] = &[ "back_tab", "bell", "carriage_return", "change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos", "column_address", "command_character", "cursor_address", "cursor_down", "cursor_home", "cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right", @@ -123,7 +123,7 @@ pub static stringfnames: &[&str] = &[ "back_tab", "bell", "carriage_return", "acs_plus", "memory_lock", "memory_unlock", "box_chars_1"]; #[rustfmt::skip] -pub static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear", +pub(crate) static stringnames: &[&str] = &[ "cbt", "_", "cr", "csr", "tbc", "clear", "_", "_", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1", "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc", "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc", @@ -178,7 +178,7 @@ fn read_byte(r: &mut dyn io::Read) -> io::Result { /// Parse a compiled terminfo entry, using long capability names if `longnames` /// is true -pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result { +pub(crate) fn parse(file: &mut dyn io::Read, longnames: bool) -> Result { macro_rules! t( ($e:expr) => ( match $e { Ok(e) => e, @@ -317,7 +317,7 @@ pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result TermInfo { +pub(crate) fn msys_terminfo() -> TermInfo { let mut strings = HashMap::new(); strings.insert("sgr0".to_string(), b"\x1B[0m".to_vec()); strings.insert("bold".to_string(), b"\x1B[1m".to_vec()); diff --git a/library/term/src/terminfo/parser/compiled/tests.rs b/library/test/src/term/terminfo/parser/compiled/tests.rs similarity index 100% rename from library/term/src/terminfo/parser/compiled/tests.rs rename to library/test/src/term/terminfo/parser/compiled/tests.rs diff --git a/library/term/src/terminfo/searcher.rs b/library/test/src/term/terminfo/searcher.rs similarity index 96% rename from library/term/src/terminfo/searcher.rs rename to library/test/src/term/terminfo/searcher.rs index 5499e240e6..68e181a689 100644 --- a/library/term/src/terminfo/searcher.rs +++ b/library/test/src/term/terminfo/searcher.rs @@ -11,7 +11,7 @@ mod tests; /// Return path to database entry for `term` #[allow(deprecated)] -pub fn get_dbpath_for_term(term: &str) -> Option { +pub(crate) fn get_dbpath_for_term(term: &str) -> Option { let mut dirs_to_search = Vec::new(); let first_char = term.chars().next()?; diff --git a/library/term/src/terminfo/searcher/tests.rs b/library/test/src/term/terminfo/searcher/tests.rs similarity index 100% rename from library/term/src/terminfo/searcher/tests.rs rename to library/test/src/term/terminfo/searcher/tests.rs diff --git a/library/term/src/win.rs b/library/test/src/term/win.rs similarity index 78% rename from library/term/src/win.rs rename to library/test/src/term/win.rs index c24cf9518a..4bdbd6ee75 100644 --- a/library/term/src/win.rs +++ b/library/test/src/term/win.rs @@ -5,12 +5,11 @@ use std::io; use std::io::prelude::*; -use crate::color; -use crate::Attr; -use crate::Terminal; +use super::color; +use super::Terminal; /// A Terminal implementation that uses the Win32 Console API. -pub struct WinConsole { +pub(crate) struct WinConsole { buf: T, def_foreground: color::Color, def_background: color::Color, @@ -115,7 +114,7 @@ impl WinConsole { } /// Returns `None` whenever the terminal cannot be created for some reason. - pub fn new(out: T) -> io::Result> { + pub(crate) fn new(out: T) -> io::Result> { use std::mem::MaybeUninit; let fg; @@ -154,8 +153,6 @@ impl Write for WinConsole { } impl Terminal for WinConsole { - type Output = T; - fn fg(&mut self, color: color::Color) -> io::Result { self.foreground = color; self.apply(); @@ -163,38 +160,6 @@ impl Terminal for WinConsole { Ok(true) } - fn bg(&mut self, color: color::Color) -> io::Result { - self.background = color; - self.apply(); - - Ok(true) - } - - fn attr(&mut self, attr: Attr) -> io::Result { - match attr { - Attr::ForegroundColor(f) => { - self.foreground = f; - self.apply(); - Ok(true) - } - Attr::BackgroundColor(b) => { - self.background = b; - self.apply(); - Ok(true) - } - _ => Ok(false), - } - } - - fn supports_attr(&self, attr: Attr) -> bool { - // it claims support for underscore and reverse video, but I can't get - // it to do anything -cmr - match attr { - Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true, - _ => false, - } - } - fn reset(&mut self) -> io::Result { self.foreground = self.def_foreground; self.background = self.def_background; @@ -202,19 +167,4 @@ impl Terminal for WinConsole { Ok(true) } - - fn get_ref(&self) -> &T { - &self.buf - } - - fn get_mut(&mut self) -> &mut T { - &mut self.buf - } - - fn into_inner(self) -> T - where - Self: Sized, - { - self.buf - } } diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 5a4a540b04..794f727700 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -61,9 +61,7 @@ fn one_ignored_one_unignored_test() -> Vec { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -75,9 +73,7 @@ fn one_ignored_one_unignored_test() -> Vec { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -97,9 +93,7 @@ pub fn do_not_run_ignored_tests() { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -120,9 +114,7 @@ pub fn ignored_tests_result_in_ignored() { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -147,9 +139,7 @@ fn test_should_panic() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -174,9 +164,7 @@ fn test_should_panic_good_message() { ignore: false, should_panic: ShouldPanic::YesWithMessage("error message"), allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -206,9 +194,7 @@ fn test_should_panic_bad_message() { ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -242,9 +228,7 @@ fn test_should_panic_non_string_message_type() { ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -270,9 +254,7 @@ fn test_should_panic_but_succeeds() { ignore: false, should_panic, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -306,9 +288,7 @@ fn report_time_test_template(report_time: bool) -> Option { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -343,9 +323,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type, }, @@ -384,9 +362,7 @@ fn typed_test_desc(test_type: TestType) -> TestDesc { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type, } @@ -499,9 +475,7 @@ pub fn exclude_should_panic_option() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -525,9 +499,7 @@ pub fn exact_filter_match() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -621,9 +593,7 @@ pub fn sort_tests() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }, @@ -702,9 +672,7 @@ pub fn test_bench_no_iter() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; @@ -726,9 +694,7 @@ pub fn test_bench_iter() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; @@ -744,9 +710,7 @@ fn should_sort_failures_before_printing_them() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; @@ -756,9 +720,7 @@ fn should_sort_failures_before_printing_them() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, - #[cfg(not(bootstrap))] compile_fail: false, - #[cfg(not(bootstrap))] no_run: false, test_type: TestType::Unknown, }; diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 63907c71ea..3512a57e8e 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -124,9 +124,7 @@ pub struct TestDesc { pub ignore: bool, pub should_panic: options::ShouldPanic, pub allow_fail: bool, - #[cfg(not(bootstrap))] pub compile_fail: bool, - #[cfg(not(bootstrap))] pub no_run: bool, pub test_type: TestType, } @@ -147,7 +145,6 @@ impl TestDesc { /// Returns None for ignored test or that that are just run, otherwise give a description of the type of test. /// Descriptions include "should panic", "compile fail" and "compile". - #[cfg(not(bootstrap))] pub fn test_mode(&self) -> Option<&'static str> { if self.ignore { return None; @@ -169,11 +166,6 @@ impl TestDesc { } None } - - #[cfg(bootstrap)] - pub fn test_mode(&self) -> Option<&'static str> { - None - } } #[derive(Debug)] diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index c76ba7667d..031d2942c5 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -21,7 +21,7 @@ compiler_builtins = "0.1.0" cfg-if = "0.1.8" [build-dependencies] -cc = "1.0.68" +cc = "1.0.69" [features] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 8445d811e0..64f022b4e8 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -40,7 +40,7 @@ cmake = "0.1.38" filetime = "0.2" num_cpus = "1.0" getopts = "0.2.19" -cc = "1.0.68" +cc = "1.0.69" libc = "0.2" serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" @@ -48,8 +48,9 @@ toml = "0.5" lazy_static = "1.3.0" time = "0.1" ignore = "0.4.10" -opener = "0.4" +opener = "0.5" merge = "0.1.0" +once_cell = "1.7.2" [target.'cfg(windows)'.dependencies.winapi] version = "0.3" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 7c7f162b82..d2cf929aa2 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -77,7 +77,7 @@ def download(path, url, probably_big, verbose): def _download(path, url, probably_big, verbose, exception): if probably_big or verbose: print("downloading {}".format(url)) - # see http://serverfault.com/questions/301128/how-to-download + # see https://serverfault.com/questions/301128/how-to-download if sys.platform == 'win32': run(["PowerShell.exe", "/nologo", "-Command", "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", @@ -138,7 +138,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): shutil.rmtree(os.path.join(dst, fname)) -def run(args, verbose=False, exception=False, **kwargs): +def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): """Run a child program in a new process""" if verbose: print("running: " + ' '.join(args)) @@ -151,7 +151,14 @@ def run(args, verbose=False, exception=False, **kwargs): err = "failed to run: " + ' '.join(args) if verbose or exception: raise RuntimeError(err) - sys.exit(err) + # For most failures, we definitely do want to print this error, or the user will have no + # idea what went wrong. But when we've successfully built bootstrap and it failed, it will + # have already printed an error above, so there's no need to print the exact command we're + # running. + if is_bootstrap: + sys.exit(1) + else: + sys.exit(err) def require(cmd, exit=True): @@ -573,7 +580,13 @@ class RustBuild(object): if ostype != "Linux": return - if not os.path.exists("/etc/NIXOS"): + # Use `/etc/os-release` instead of `/etc/NIXOS`. + # The latter one does not exist on NixOS when using tmpfs as root. + try: + with open("/etc/os-release", "r") as f: + if not any(line.strip() == "ID=nixos" for line in f): + return + except FileNotFoundError: return if os.path.exists("/lib"): return @@ -982,39 +995,40 @@ class RustBuild(object): slow_submodules = self.get_toml('fast-submodules') == "false" start_time = time() if slow_submodules: - print('Unconditionally updating all submodules') + print('Unconditionally updating submodules') else: print('Updating only changed submodules') default_encoding = sys.getdefaultencoding() - submodules = [s.split(' ', 1)[1] for s in subprocess.check_output( - ["git", "config", "--file", - os.path.join(self.rust_root, ".gitmodules"), - "--get-regexp", "path"] - ).decode(default_encoding).splitlines()] + # Only update submodules that are needed to build bootstrap. These are needed because Cargo + # currently requires everything in a workspace to be "locally present" when starting a + # build, and will give a hard error if any Cargo.toml files are missing. + # FIXME: Is there a way to avoid cloning these eagerly? Bootstrap itself doesn't need to + # share a workspace with any tools - maybe it could be excluded from the workspace? + # That will still require cloning the submodules the second you check the standard + # library, though... + # FIXME: Is there a way to avoid hard-coding the submodules required? + # WARNING: keep this in sync with the submodules hard-coded in bootstrap/lib.rs + submodules = [ + "src/tools/rust-installer", + "src/tools/cargo", + "src/tools/rls", + "src/tools/miri", + "library/backtrace", + "library/stdarch" + ] filtered_submodules = [] submodules_names = [] - llvm_checked_out = os.path.exists(os.path.join(self.rust_root, "src/llvm-project/.git")) - external_llvm_provided = self.get_toml('llvm-config') or self.downloading_llvm() - llvm_needed = not self.get_toml('codegen-backends', 'rust') \ - or "llvm" in self.get_toml('codegen-backends', 'rust') for module in submodules: - if module.endswith("llvm-project"): - # Don't sync the llvm-project submodule if an external LLVM was - # provided, if we are downloading LLVM or if the LLVM backend is - # not being built. Also, if the submodule has been initialized - # already, sync it anyways so that it doesn't mess up contributor - # pull requests. - if external_llvm_provided or not llvm_needed: - if self.get_toml('lld') != 'true' and not llvm_checked_out: - continue check = self.check_submodule(module, slow_submodules) filtered_submodules.append((module, check)) submodules_names.append(module) recorded = subprocess.Popen(["git", "ls-tree", "HEAD"] + submodules_names, cwd=self.rust_root, stdout=subprocess.PIPE) recorded = recorded.communicate()[0].decode(default_encoding).strip().splitlines() + # { filename: hash } recorded_submodules = {} for data in recorded: + # [mode, kind, hash, filename] data = data.split() recorded_submodules[data[3]] = data[2] for module in filtered_submodules: @@ -1178,7 +1192,7 @@ def bootstrap(help_triggered): env["BOOTSTRAP_CONFIG"] = toml_path if build.rustc_commit is not None: env["BOOTSTRAP_DOWNLOAD_RUSTC"] = '1' - run(args, env=env, verbose=build.verbose) + run(args, env=env, verbose=build.verbose, is_bootstrap=True) def main(): diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index bc499fdba5..56ecc6e68a 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -29,6 +29,8 @@ use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir}; use crate::{Build, DocTests, GitRepo, Mode}; pub use crate::Compiler; +// FIXME: replace with std::lazy after it gets stabilized and reaches beta +use once_cell::sync::Lazy; pub struct Builder<'a> { pub build: &'a Build, @@ -195,7 +197,7 @@ impl StepDescription { if paths.is_empty() || builder.config.include_default_paths { for (desc, should_run) in v.iter().zip(&should_runs) { - if desc.default && should_run.is_really_default { + if desc.default && should_run.is_really_default() { for pathset in &should_run.paths { desc.maybe_run(builder, pathset); } @@ -228,7 +230,11 @@ impl StepDescription { } } -#[derive(Clone)] +enum ReallyDefault<'a> { + Bool(bool), + Lazy(Lazy bool + 'a>>), +} + pub struct ShouldRun<'a> { pub builder: &'a Builder<'a>, // use a BTreeSet to maintain sort order @@ -236,7 +242,7 @@ pub struct ShouldRun<'a> { // If this is a default rule, this is an additional constraint placed on // its run. Generally something like compiler docs being enabled. - is_really_default: bool, + is_really_default: ReallyDefault<'a>, } impl<'a> ShouldRun<'a> { @@ -244,15 +250,27 @@ impl<'a> ShouldRun<'a> { ShouldRun { builder, paths: BTreeSet::new(), - is_really_default: true, // by default no additional conditions + is_really_default: ReallyDefault::Bool(true), // by default no additional conditions } } pub fn default_condition(mut self, cond: bool) -> Self { - self.is_really_default = cond; + self.is_really_default = ReallyDefault::Bool(cond); + self + } + + pub fn lazy_default_condition(mut self, lazy_cond: Box bool + 'a>) -> Self { + self.is_really_default = ReallyDefault::Lazy(Lazy::new(lazy_cond)); self } + pub fn is_really_default(&self) -> bool { + match &self.is_really_default { + ReallyDefault::Bool(val) => *val, + ReallyDefault::Lazy(lazy) => *lazy.deref(), + } + } + /// Indicates it should run if the command-line selects the given crate or /// any of its (local) dependencies. /// @@ -432,6 +450,7 @@ impl<'a> Builder<'a> { test::RustdocTheme, test::RustdocUi, test::RustdocJson, + test::HtmlCheck, // Run bootstrap close to the end as it's unlikely to fail test::Bootstrap, // Run run-make last, since these won't pass without make on Windows @@ -446,6 +465,7 @@ impl<'a> Builder<'a> { doc::Std, doc::Rustc, doc::Rustdoc, + doc::Rustfmt, doc::ErrorIndex, doc::Nomicon, doc::Reference, diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index 4d7c207e3a..e7fb8c0d4d 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -613,9 +613,14 @@ mod dist { // Note that the stages here are +1 than what they actually are because // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is // not 0. + // + // The stage 0 copy is the one downloaded for bootstrapping. It is + // (currently) needed to run "cargo test" on the linkchecker, and + // should be relatively "free". assert_eq!( first(builder.cache.all::()), &[ + tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } }, tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }, tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } }, ] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 5003d6693f..bc106746e5 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -7,7 +7,7 @@ use crate::config::TargetSelection; use crate::tool::{prepare_tool_cargo, SourceType}; use crate::INTERNER; use crate::{Compiler, Mode, Subcommand}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { @@ -72,6 +72,8 @@ impl Step for Std { } fn run(self, builder: &Builder<'_>) { + builder.update_submodule(&Path::new("library").join("stdarch")); + let target = self.target; let compiler = builder.compiler(builder.top_stage, builder.config.build); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 112a6ea939..78c9a25262 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -2,8 +2,8 @@ //! library. //! //! This module contains some of the real meat in the rustbuild build system -//! which is where Cargo is used to compiler the standard library, libtest, and -//! compiler. This module is also responsible for assembling the sysroot as it +//! which is where Cargo is used to compile the standard library, libtest, and +//! the compiler. This module is also responsible for assembling the sysroot as it //! goes along from the output of the previous stage. use std::borrow::Cow; @@ -79,6 +79,8 @@ impl Step for Std { return; } + builder.update_submodule(&Path::new("library").join("stdarch")); + let mut target_deps = builder.ensure(StartupObjects { compiler, target }); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); @@ -1366,7 +1368,7 @@ pub fn stream_cargo( // Make sure Cargo actually succeeded after we read all of its stdout. let status = t!(child.wait()); - if !status.success() { + if builder.is_verbose() && !status.success() { eprintln!( "command did not execute successfully: {:?}\n\ expected success, got: {}", diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 483816b98d..4b3c25b02c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -13,6 +13,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use crate::cache::{Interned, INTERNER}; +use crate::channel::GitInfo; pub use crate::flags::Subcommand; use crate::flags::{Color, Flags}; use crate::util::exe; @@ -48,7 +49,7 @@ pub struct Config { /// Call Build::ninja() instead of this. pub ninja_in_file: bool, pub verbose: usize, - pub submodules: bool, + pub submodules: Option, pub fast_submodules: bool, pub compiler_docs: bool, pub docs_minification: bool, @@ -552,7 +553,7 @@ impl Config { config.backtrace = true; config.rust_optimize = true; config.rust_optimize_tests = true; - config.submodules = true; + config.submodules = None; config.fast_submodules = true; config.docs = true; config.docs_minification = true; @@ -658,11 +659,11 @@ impl Config { config.npm = build.npm.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); + config.submodules = build.submodules; set(&mut config.low_priority, build.low_priority); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs_minification, build.docs_minification); set(&mut config.docs, build.docs); - set(&mut config.submodules, build.submodules); set(&mut config.fast_submodules, build.fast_submodules); set(&mut config.locked_deps, build.locked_deps); set(&mut config.vendor, build.vendor); @@ -792,8 +793,16 @@ impl Config { // CI-built LLVM can be either dynamic or static. let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm"); - let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt"))); - config.llvm_link_shared = link_type == "dynamic"; + config.llvm_link_shared = if config.dry_run { + // just assume dynamic for now + true + } else { + let link_type = t!( + std::fs::read_to_string(ci_llvm.join("link-type.txt")), + format!("CI llvm missing: {}", ci_llvm.display()) + ); + link_type == "dynamic" + }; } if config.llvm_thin_lto { @@ -1075,6 +1084,10 @@ impl Config { pub fn llvm_enabled(&self) -> bool { self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) } + + pub fn submodules(&self, rust_info: &GitInfo) -> bool { + self.submodules.unwrap_or(rust_info.is_git()) + } } fn set(field: &mut T, val: Option) { diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 999882a1c0..8d9f169e6c 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -160,6 +160,7 @@ o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of tw o("extended", "build.extended", "build an extended rust tool set") v("tools", None, "List of extended tools will be installed") +v("codegen-backends", None, "List of codegen backends to build") v("build", "build.build", "GNUs ./configure syntax LLVM build triple") v("host", None, "GNUs ./configure syntax LLVM host triples") v("target", None, "GNUs ./configure syntax LLVM target triples") @@ -339,6 +340,8 @@ for key in known_args: set('target.{}.llvm-filecheck'.format(build()), value) elif option.name == 'tools': set('build.tools', value.split(',')) + elif option.name == 'codegen-backends': + set('rust.codegen-backends', value.split(',')) elif option.name == 'host': set('build.host', value.split(',')) elif option.name == 'target': diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 16d148db61..c37763243c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -400,12 +400,12 @@ impl Step for Rustc { // Copy over lld if it's there if builder.config.lld_enabled { - let exe = exe("rust-lld", compiler.host); - builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe)); + let rust_lld = exe("rust-lld", compiler.host); + builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld)); // for `-Z gcc-ld=lld` let gcc_lld_dir = dst_dir.join("gcc-ld"); t!(fs::create_dir(&gcc_lld_dir)); - builder.copy(&src_dir.join(&exe), &gcc_lld_dir.join(&exe)); + builder.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host))); } // Copy over llvm-dwp if it's there @@ -1033,13 +1033,7 @@ impl Step for Rls { let rls = builder .ensure(tool::Rls { compiler, target, extra_features: Vec::new() }) .or_else(|| { - // We ignore failure on aarch64 Windows because RLS currently - // fails to build, due to winapi 0.2 not supporting aarch64. - missing_tool( - "RLS", - builder.build.config.missing_tools - || (target.triple.contains("aarch64") && target.triple.contains("windows")), - ); + missing_tool("RLS", builder.build.config.missing_tools); None })?; @@ -1961,8 +1955,16 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir cmd.arg("--libfiles"); builder.verbose(&format!("running {:?}", cmd)); let files = 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(' ') { - builder.install(Path::new(file), dst_libdir, 0o644); + // If we're not using a custom LLVM, make sure we package for the target. + let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) { + target_llvm_out.join(relative_path) + } else { + PathBuf::from(file) + }; + builder.install(&file, dst_libdir, 0o644); } !builder.config.dry_run } else { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index d2fabf9967..9ec5d4d8cc 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -22,8 +22,17 @@ use crate::config::{Config, TargetSelection}; use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; use crate::util::symlink_dir; +macro_rules! submodule_helper { + ($path:expr, submodule) => { + $path + }; + ($path:expr, submodule = $submodule:literal) => { + $submodule + }; +} + macro_rules! book { - ($($name:ident, $path:expr, $book_name:expr;)+) => { + ($($name:ident, $path:expr, $book_name:expr $(, submodule $(= $submodule:literal)? )? ;)+) => { $( #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $name { @@ -46,6 +55,10 @@ macro_rules! book { } fn run(self, builder: &Builder<'_>) { + $( + let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? )); + builder.update_submodule(&path); + )? builder.ensure(RustbookSrc { target: self.target, name: INTERNER.intern_str($book_name), @@ -59,13 +72,16 @@ macro_rules! book { // NOTE: When adding a book here, make sure to ALSO build the book by // adding a build step in `src/bootstrap/builder.rs`! +// NOTE: Make sure to add the corresponding submodule when adding a new book. +// FIXME: Make checking for a submodule automatic somehow (maybe by having a list of all submodules +// and checking against it?). book!( - CargoBook, "src/tools/cargo/src/doc", "cargo"; - EditionGuide, "src/doc/edition-guide", "edition-guide"; - EmbeddedBook, "src/doc/embedded-book", "embedded-book"; - Nomicon, "src/doc/nomicon", "nomicon"; - Reference, "src/doc/reference", "reference"; - RustByExample, "src/doc/rust-by-example", "rust-by-example"; + CargoBook, "src/tools/cargo/src/doc", "cargo", submodule = "src/tools/cargo"; + EditionGuide, "src/doc/edition-guide", "edition-guide", submodule; + EmbeddedBook, "src/doc/embedded-book", "embedded-book", submodule; + Nomicon, "src/doc/nomicon", "nomicon", submodule; + Reference, "src/doc/reference", "reference", submodule; + RustByExample, "src/doc/rust-by-example", "rust-by-example", submodule; RustdocBook, "src/doc/rustdoc", "rustdoc"; ); @@ -197,6 +213,9 @@ impl Step for TheBook { /// * Index page /// * Redirect pages fn run(self, builder: &Builder<'_>) { + let relative_path = Path::new("src").join("doc").join("book"); + builder.update_submodule(&relative_path); + let compiler = self.compiler; let target = self.target; @@ -204,7 +223,7 @@ impl Step for TheBook { builder.ensure(RustbookSrc { target, name: INTERNER.intern_str("book"), - src: INTERNER.intern_path(builder.src.join("src/doc/book")), + src: INTERNER.intern_path(builder.src.join(&relative_path)), }); // building older edition redirects @@ -212,7 +231,7 @@ impl Step for TheBook { builder.ensure(RustbookSrc { target, name: INTERNER.intern_string(format!("book/{}", edition)), - src: INTERNER.intern_path(builder.src.join("src/doc/book").join(edition)), + src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)), }); } @@ -221,7 +240,7 @@ impl Step for TheBook { // build the redirect pages builder.info(&format!("Documenting book redirect pages ({})", target)); - for file in t!(fs::read_dir(builder.src.join("src/doc/book/redirects"))) { + for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) { let file = t!(file); let path = file.path(); let path = path.to_str().unwrap(); @@ -374,9 +393,15 @@ impl Step for Standalone { } if filename == "not_found.md" { - cmd.arg("--markdown-css").arg("https://doc.rust-lang.org/rust.css"); + 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"); } else { - cmd.arg("--markdown-css").arg("rust.css"); + cmd.arg("--markdown-css") + .arg(format!("rustdoc{}.css", &builder.version)) + .arg("--markdown-css") + .arg("rust.css"); } builder.run(&mut cmd); } @@ -501,8 +526,8 @@ impl Step for Std { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustc { - stage: u32, - target: TargetSelection, + pub stage: u32, + pub target: TargetSelection, } impl Step for Rustc { @@ -593,84 +618,103 @@ impl Step for Rustc { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Rustdoc { - stage: u32, - target: TargetSelection, -} - -impl Step for Rustdoc { - type Output = (); - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.krate("rustdoc-tool") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Rustdoc { stage: run.builder.top_stage, target: run.target }); - } - - /// Generates compiler documentation. - /// - /// This will generate all documentation for compiler and dependencies. - /// Compiler documentation is distributed separately, so we make sure - /// we do not merge it with the other documentation from std, test and - /// proc_macros. This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let target = self.target; - builder.info(&format!("Documenting stage{} rustdoc ({})", stage, target)); - - // This is the intended out directory for compiler documentation. - let out = builder.compiler_doc_out(target); - t!(fs::create_dir_all(&out)); +macro_rules! tool_doc { + ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], binary=$bin:expr) => { + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub struct $tool { + stage: u32, + target: TargetSelection, + } - let compiler = builder.compiler(stage, builder.config.build); + impl Step for $tool { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; - if !builder.config.compiler_docs { - builder.info("\tskipping - compiler/librustdoc docs disabled"); - return; - } + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.krate($should_run) + } - // Build rustc docs so that we generate relative links. - builder.ensure(Rustc { stage, target }); + fn make_run(run: RunConfig<'_>) { + run.builder.ensure($tool { stage: run.builder.top_stage, target: run.target }); + } - // Build rustdoc. - builder.ensure(tool::Rustdoc { compiler }); + /// Generates compiler documentation. + /// + /// This will generate all documentation for compiler and dependencies. + /// Compiler documentation is distributed separately, so we make sure + /// we do not merge it with the other documentation from std, test and + /// proc_macros. This is largely just a wrapper around `cargo doc`. + fn run(self, builder: &Builder<'_>) { + let stage = self.stage; + let target = self.target; + builder.info(&format!("Documenting stage{} {} ({})", stage, stringify!($tool).to_lowercase(), target)); - // Symlink compiler docs to the output directory of rustdoc documentation. - let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); - t!(fs::create_dir_all(&out_dir)); - t!(symlink_dir_force(&builder.config, &out, &out_dir)); + // This is the intended out directory for compiler documentation. + let out = builder.compiler_doc_out(target); + t!(fs::create_dir_all(&out)); - // Build cargo command. - let mut cargo = prepare_tool_cargo( - builder, - compiler, - Mode::ToolRustc, - target, - "doc", - "src/tools/rustdoc", - SourceType::InTree, - &[], - ); + let compiler = builder.compiler(stage, builder.config.build); - cargo.arg("-Zskip-rustdoc-fingerprint"); - // Only include compiler crates, no dependencies of those, such as `libc`. - cargo.arg("--no-deps"); - cargo.arg("-p").arg("rustdoc"); - cargo.arg("-p").arg("rustdoc-json-types"); + if !builder.config.compiler_docs { + builder.info("\tskipping - compiler/tool docs disabled"); + return; + } - cargo.rustdocflag("--document-private-items"); - cargo.rustdocflag("--enable-index-page"); - cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("-Zunstable-options"); - builder.run(&mut cargo.into()); + // Build rustc docs so that we generate relative links. + builder.ensure(Rustc { stage, target }); + + // Symlink compiler docs to the output directory of rustdoc documentation. + let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); + t!(fs::create_dir_all(&out_dir)); + t!(symlink_dir_force(&builder.config, &out, &out_dir)); + + // Build cargo command. + let mut cargo = prepare_tool_cargo( + builder, + compiler, + Mode::ToolRustc, + target, + "doc", + $path, + SourceType::InTree, + &[], + ); + + cargo.arg("-Zskip-rustdoc-fingerprint"); + // Only include compiler crates, no dependencies of those, such as `libc`. + cargo.arg("--no-deps"); + $( + cargo.arg("-p").arg($krate); + )+ + + if !$bin { + cargo.rustdocflag("--document-private-items"); + } + cargo.rustdocflag("--enable-index-page"); + cargo.rustdocflag("--show-type-layout"); + cargo.rustdocflag("-Zunstable-options"); + builder.run(&mut cargo.into()); + } + } } } +tool_doc!( + Rustdoc, + "rustdoc-tool", + "src/tools/rustdoc", + ["rustdoc", "rustdoc-json-types"], + binary = false +); +tool_doc!( + Rustfmt, + "rustfmt-nightly", + "src/tools/rustfmt", + ["rustfmt-nightly", "rustfmt-config_proc_macro"], + binary = true +); + #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { pub target: TargetSelection, diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 80a60c79ed..1b7614b298 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -152,7 +152,7 @@ Subcommands: fmt Run rustfmt test, t Build and run some test suites bench Build and run some benchmarks - doc Build documentation + doc, d Build documentation clean Clean out build directories dist Build distribution artifacts install Install distribution artifacts @@ -244,6 +244,7 @@ To learn more about a subcommand, run `./x.py -h`", || (s == "t") || (s == "bench") || (s == "doc") + || (s == "d") || (s == "clean") || (s == "dist") || (s == "install") @@ -312,7 +313,7 @@ To learn more about a subcommand, run `./x.py -h`", "clippy" => { opts.optflag("", "fix", "automatically apply lint suggestions"); } - "doc" => { + "doc" | "d" => { opts.optflag("", "open", "open the docs in a browser"); } "clean" => { @@ -487,7 +488,7 @@ Arguments: ./x.py test --stage 1", ); } - "doc" => { + "doc" | "d" => { subcommand_help.push_str( "\n Arguments: @@ -573,7 +574,7 @@ Arguments: }, }, "bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") }, - "doc" => Subcommand::Doc { paths, open: matches.opt_present("open") }, + "doc" | "d" => Subcommand::Doc { paths, open: matches.opt_present("open") }, "clean" => { if !paths.is_empty() { println!("\nclean does not take a path argument\n"); diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs index 2fe9b06e42..5c0322e18a 100644 --- a/src/bootstrap/job.rs +++ b/src/bootstrap/job.rs @@ -103,12 +103,20 @@ pub unsafe fn setup(build: &mut Build) { }; let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap()); - assert!( - !parent.is_null(), - "PID `{}` doesn't seem to exist: {}", - pid, - io::Error::last_os_error() - ); + + // If we get a null parent pointer here, it is possible that either + // we have got an invalid pid or the parent process has been closed. + // Since the first case rarely happens + // (only when wrongly setting the environmental variable), + // so it might be better to improve the experience of the second case + // when users have interrupted the parent process and we don't finish + // duplicating the handle yet. + // We just need close the job object if that occurs. + if parent.is_null() { + CloseHandle(job); + return; + } + let mut parent_handle = ptr::null_mut(); let r = DuplicateHandle( GetCurrentProcess(), diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 347236c655..245f3eada2 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -477,12 +477,121 @@ impl Build { slice::from_ref(&self.build.triple) } + // modified from `check_submodule` and `update_submodule` in bootstrap.py + /// Given a path to the directory of a submodule, update it. + /// + /// `relative_path` should be relative to the root of the git repository, not an absolute path. + pub(crate) fn update_submodule(&self, relative_path: &Path) { + fn dir_is_empty(dir: &Path) -> bool { + t!(std::fs::read_dir(dir)).next().is_none() + } + + if !self.config.submodules(&self.rust_info) { + return; + } + + let absolute_path = self.config.src.join(relative_path); + + // NOTE: The check for the empty directory is here because when running x.py the first time, + // the submodule won't be checked out. Check it out now so we can build it. + if !channel::GitInfo::new(false, relative_path).is_git() && !dir_is_empty(&absolute_path) { + return; + } + + // check_submodule + if self.config.fast_submodules { + let checked_out_hash = output( + Command::new("git").args(&["rev-parse", "HEAD"]).current_dir(&absolute_path), + ); + // update_submodules + let recorded = output( + Command::new("git") + .args(&["ls-tree", "HEAD"]) + .arg(relative_path) + .current_dir(&self.config.src), + ); + let actual_hash = recorded + .split_whitespace() + .nth(2) + .unwrap_or_else(|| panic!("unexpected output `{}`", recorded)); + + // update_submodule + if actual_hash == checked_out_hash.trim_end() { + // already checked out + return; + } + } + + println!("Updating submodule {}", relative_path.display()); + self.run( + Command::new("git") + .args(&["submodule", "-q", "sync"]) + .arg(relative_path) + .current_dir(&self.config.src), + ); + + // Try passing `--progress` to start, then run git again without if that fails. + let update = |progress: bool| { + let mut git = Command::new("git"); + git.args(&["submodule", "update", "--init", "--recursive"]); + if progress { + git.arg("--progress"); + } + git.arg(relative_path).current_dir(&self.config.src); + git + }; + // NOTE: doesn't use `try_run` because this shouldn't print an error if it fails. + if !update(true).status().map_or(false, |status| status.success()) { + self.run(&mut update(false)); + } + + self.run(Command::new("git").args(&["reset", "-q", "--hard"]).current_dir(&absolute_path)); + self.run(Command::new("git").args(&["clean", "-qdfx"]).current_dir(absolute_path)); + } + + /// If any submodule has been initialized already, sync it unconditionally. + /// This avoids contributors checking in a submodule change by accident. + pub fn maybe_update_submodules(&self) { + // WARNING: keep this in sync with the submodules hard-coded in bootstrap.py + const BOOTSTRAP_SUBMODULES: &[&str] = &[ + "src/tools/rust-installer", + "src/tools/cargo", + "src/tools/rls", + "src/tools/miri", + "library/backtrace", + "library/stdarch", + ]; + // Avoid running git when there isn't a git checkout. + if !self.config.submodules(&self.rust_info) { + return; + } + let output = output( + Command::new("git") + .args(&["config", "--file"]) + .arg(&self.config.src.join(".gitmodules")) + .args(&["--get-regexp", "path"]), + ); + for line in output.lines() { + // Look for `submodule.$name.path = $path` + // Sample output: `submodule.src/rust-installer.path src/tools/rust-installer` + let submodule = Path::new(line.splitn(2, ' ').nth(1).unwrap()); + // avoid updating submodules twice + if !BOOTSTRAP_SUBMODULES.iter().any(|&p| Path::new(p) == submodule) + && channel::GitInfo::new(false, submodule).is_git() + { + self.update_submodule(submodule); + } + } + } + /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { job::setup(self); } + self.maybe_update_submodules(); + if let Subcommand::Format { check, paths } = &self.config.cmd { return format::format(self, *check, &paths); } @@ -857,7 +966,7 @@ impl Build { } // Work around an apparently bad MinGW / GCC optimization, - // See: http://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html + // See: https://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936 if &*target.triple == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 449fdb87b0..1be414b29a 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -128,6 +128,7 @@ impl Step for Llvm { Err(m) => m, }; + builder.update_submodule(&Path::new("src").join("llvm-project")); if builder.config.llvm_link_shared && (target.contains("windows") || target.contains("apple-darwin")) { @@ -139,7 +140,7 @@ impl Step for Llvm { let _time = util::timeit(&builder); t!(fs::create_dir_all(&out_dir)); - // http://llvm.org/docs/CMake.html + // https://llvm.org/docs/CMake.html let mut cfg = cmake::Config::new(builder.src.join(root)); let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { @@ -276,7 +277,7 @@ impl Step for Llvm { } } - // http://llvm.org/docs/HowToCrossCompileLLVM.html + // 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 diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index fe4666effe..31f18d81c7 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -9,7 +9,7 @@ use std::fmt; use std::fs; use std::iter; use std::path::{Path, PathBuf}; -use std::process::Command; +use std::process::{Command, Stdio}; use build_helper::{self, output, t}; @@ -124,8 +124,25 @@ You can skip linkcheck with --exclude src/tools/linkchecker" builder.info(&format!("Linkcheck ({})", host)); + // Test the linkchecker itself. + let bootstrap_host = builder.config.build; + let compiler = builder.compiler(0, bootstrap_host); + let cargo = tool::prepare_tool_cargo( + builder, + compiler, + Mode::ToolBootstrap, + bootstrap_host, + "test", + "src/tools/linkchecker", + SourceType::InTree, + &[], + ); + try_run(builder, &mut cargo.into()); + + // Build all the default documentation. builder.default_doc(&[]); + // Run the linkchecker. let _time = util::timeit(&builder); try_run( builder, @@ -144,6 +161,49 @@ You can skip linkcheck with --exclude src/tools/linkchecker" } } +fn check_if_tidy_is_installed() -> bool { + Command::new("tidy") + .arg("--version") + .stdout(Stdio::null()) + .status() + .map_or(false, |status| status.success()) +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct HtmlCheck { + target: TargetSelection, +} + +impl Step for HtmlCheck { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + let run = run.path("src/tools/html-checker"); + run.lazy_default_condition(Box::new(check_if_tidy_is_installed)) + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(HtmlCheck { target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + if !check_if_tidy_is_installed() { + eprintln!("not running HTML-check tool because `tidy` is missing"); + eprintln!( + "Note that `tidy` is not the in-tree `src/tools/tidy` but needs to be installed" + ); + panic!("Cannot run html-check tests"); + } + // Ensure that a few different kinds of documentation are available. + builder.default_doc(&[]); + builder.ensure(crate::doc::Rustc { target: self.target, stage: builder.top_stage }); + + try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Cargotest { stage: u32, @@ -682,7 +742,7 @@ impl Step for RustdocTheme { let rustdoc = builder.out.join("bootstrap/debug/rustdoc"); let mut cmd = builder.tool_cmd(Tool::RustdocTheme); cmd.arg(rustdoc.to_str().unwrap()) - .arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap()) + .arg(builder.src.join("src/librustdoc/html/static/css/themes").to_str().unwrap()) .env("RUSTC_STAGE", self.compiler.stage.to_string()) .env("RUSTC_SYSROOT", builder.sysroot(self.compiler)) .env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host)) @@ -805,16 +865,16 @@ impl Step for RustdocGUI { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - let run = run.path("src/test/rustdoc-gui"); - run.default_condition( + let run = run.suite_path("src/test/rustdoc-gui"); + run.lazy_default_condition(Box::new(move || { builder.config.nodejs.is_some() && builder .config .npm .as_ref() .map(|p| check_if_browser_ui_test_is_installed(p)) - .unwrap_or(false), - ) + .unwrap_or(false) + })) } fn make_run(run: RunConfig<'_>) { @@ -847,29 +907,46 @@ impl Step for RustdocGUI { // We remove existing folder to be sure there won't be artifacts remaining. let _ = fs::remove_dir_all(&out_dir); - let mut nb_generated = 0; + let src_path = builder.build.src.join("src/test/rustdoc-gui/src"); // We generate docs for the libraries present in the rustdoc-gui's src folder. - let libs_dir = builder.build.src.join("src/test/rustdoc-gui/src"); - for entry in libs_dir.read_dir().expect("read_dir call failed") { - let entry = entry.expect("invalid entry"); - let path = entry.path(); - if path.extension().map(|e| e == "rs").unwrap_or(false) { - let mut command = builder.rustdoc_cmd(self.compiler); - command.arg(path).arg("-o").arg(&out_dir); - builder.run(&mut command); - nb_generated += 1; + for entry in src_path.read_dir().expect("read_dir call failed") { + if let Ok(entry) = entry { + let path = entry.path(); + + if !path.is_dir() { + continue; + } + + let mut cargo = Command::new(&builder.initial_cargo); + cargo + .arg("doc") + .arg("--target-dir") + .arg(&out_dir) + .env("RUSTDOC", builder.rustdoc(self.compiler)) + .env("RUSTC", builder.rustc(self.compiler)) + .current_dir(path); + builder.run(&mut cargo); } } - assert!(nb_generated > 0, "no documentation was generated..."); // We now run GUI tests. let mut command = Command::new(&nodejs); command .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js")) .arg("--doc-folder") - .arg(out_dir) + .arg(out_dir.join("doc")) .arg("--tests-folder") .arg(builder.build.src.join("src/test/rustdoc-gui")); + for path in &builder.paths { + if let Some(name) = path.file_name().and_then(|f| f.to_str()) { + if name.ends_with(".goml") { + command.arg("--file").arg(name); + } + } + } + for test_arg in builder.config.cmd.test_args() { + command.arg(test_arg); + } builder.run(&mut command); } } @@ -1765,7 +1842,10 @@ impl Step for RustcGuide { } fn run(self, builder: &Builder<'_>) { - let src = builder.src.join("src/doc/rustc-dev-guide"); + let relative_path = Path::new("src").join("doc").join("rustc-dev-guide"); + builder.update_submodule(&relative_path); + + let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) { ToolState::TestPass diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9d75ad0918..f5e3f61dcc 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use std::env; use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{exit, Command}; use build_helper::t; @@ -376,6 +376,7 @@ bootstrap_tool!( ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; LintDocs, "src/tools/lint-docs", "lint-docs"; JsonDocCk, "src/tools/jsondocck", "jsondocck"; + HtmlChecker, "src/tools/html-checker", "html-checker"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] @@ -669,7 +670,8 @@ macro_rules! tool_extended { $path:expr, $tool_name:expr, stable = $stable:expr, - $(in_tree = $in_tree:expr,)* + $(in_tree = $in_tree:expr,)? + $(submodule = $submodule:literal,)? $extra_deps:block;)+) => { $( #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -713,6 +715,7 @@ macro_rules! tool_extended { #[allow(unused_mut)] fn run(mut $sel, $builder: &Builder<'_>) -> Option { $extra_deps + $( $builder.update_submodule(&Path::new("src").join("tools").join($submodule)); )? $builder.ensure(ToolBuild { compiler: $sel.compiler, target: $sel.target, @@ -735,6 +738,8 @@ macro_rules! tool_extended { // Note: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` // to make `./x.py build ` work. +// Note: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to +// invoke Cargo to build bootstrap. See the comment there for more details. tool_extended!((self, builder), Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", stable=true, in_tree=true, {}; CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", stable=true, in_tree=true, {}; @@ -751,7 +756,7 @@ tool_extended!((self, builder), }; RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, {}; Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, in_tree=true, {}; - RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, {}; + RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, submodule="rust-analyzer", {}; ); impl<'a> Builder<'a> { diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 80f804174e..b1ec072f3f 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -130,6 +130,7 @@ pub fn make(host: &str) -> PathBuf { } } +#[track_caller] pub fn output(cmd: &mut Command) -> String { let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, diff --git a/src/ci/cpu-usage-over-time.py b/src/ci/cpu-usage-over-time.py index 78ac060368..267c3964d0 100644 --- a/src/ci/cpu-usage-over-time.py +++ b/src/ci/cpu-usage-over-time.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # ignore-tidy-linelength # This is a small script that we use on CI to collect CPU usage statistics of @@ -37,7 +37,10 @@ import datetime import sys import time -if sys.platform == 'linux2': +# Python 3.3 changed the value of `sys.platform` on Linux from "linux2" to just +# "linux". We check here with `.startswith` to keep compatibility with older +# Python versions (especially Python 2.7). +if sys.platform.startswith('linux'): class State: def __init__(self): with open('/proc/stat', 'r') as file: diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile index 8a91859379..e2dbc7cfd7 100644 --- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile @@ -58,7 +58,7 @@ RUN curl https://www.busybox.net/downloads/busybox-1.32.1.tar.bz2 | tar xjf - && # Download the ubuntu rootfs, which we'll use as a chroot for all our tests. WORKDIR /tmp RUN mkdir rootfs/ubuntu -RUN curl http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.1-base-armhf.tar.gz | \ +RUN curl https://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04.1-base-armhf.tar.gz | \ tar xzf - -C rootfs/ubuntu && \ cd rootfs && mkdir proc sys dev etc etc/init.d diff --git a/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh b/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh index 409bca45c9..b305f358c5 100755 --- a/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh +++ b/src/ci/docker/host-x86_64/disabled/dist-x86_64-dragonfly/build-toolchain.sh @@ -39,7 +39,7 @@ rm -rf binutils # Next, download the DragonFly libc and relevant header files -URL=http://mirror-master.dragonflybsd.org/iso-images/dfly-x86_64-5.0.0_REL.iso.bz2 +URL=https://mirror-master.dragonflybsd.org/iso-images/dfly-x86_64-5.0.0_REL.iso.bz2 mkdir dragonfly curl $URL | bzcat | bsdtar xf - -C dragonfly ./usr/include ./usr/lib ./lib diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config index 66709a4004..acdf9a0e04 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config +++ b/src/ci/docker/host-x86_64/dist-arm-linux/arm-linux-gnueabi.config @@ -711,7 +711,7 @@ 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_MIRRORS="https://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" diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config b/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config index a3dcff1c93..69f86663ec 100644 --- a/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config +++ b/src/ci/docker/host-x86_64/dist-armhf-linux/arm-linux-gnueabihf.config @@ -725,7 +725,7 @@ 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_MIRRORS="https://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" diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config b/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config index 81b3d7477e..e3d032fc7e 100644 --- a/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config +++ b/src/ci/docker/host-x86_64/dist-armv7-linux/armv7-linux-gnueabihf.config @@ -671,7 +671,7 @@ CT_MPFR_PATCH_ORDER="global" CT_MPFR_V_3_1=y # CT_MPFR_NO_VERSIONS is not set CT_MPFR_VERSION="3.1.6" -CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)" +CT_MPFR_MIRRORS="https://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" @@ -711,7 +711,7 @@ 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_MIRRORS="https://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" diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile index 247b539652..42fda98bc7 100644 --- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile @@ -69,8 +69,6 @@ COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ RUN ./build-gcc.sh && apt-get remove -y gcc g++ COPY host-x86_64/dist-x86_64-linux/build-python.sh /tmp/ -# Build Python 2.7 needed for Clang 10. -RUN ./build-python.sh 2.7.12 # Build Python 3 needed for LLVM 12. RUN ./build-python.sh 3.9.1 @@ -97,7 +95,7 @@ ENV RUST_CONFIGURE_ARGS \ --build=i686-unknown-linux-gnu \ --set llvm.ninja=false \ --set rust.jemalloc -ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS +ENV SCRIPT python3 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS ENV CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER=clang # This was added when we switched from gcc to clang. It's not clear why this is diff --git a/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config b/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config index ffb2e9195b..45d5ff756c 100644 --- a/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-riscv64-linux/riscv64-unknown-linux-gnu.config @@ -645,7 +645,8 @@ CT_EXPAT_PATCH_ORDER="global" CT_EXPAT_V_2_2=y # CT_EXPAT_NO_VERSIONS is not set CT_EXPAT_VERSION="2.4.1" -CT_EXPAT_MIRRORS="http://downloads.sourceforge.net/project/expat/expat/${CT_EXPAT_VERSION}" +CT_EXPAT_VERSION_TAG="2_4_1" +CT_EXPAT_MIRRORS="https://github.com/libexpat/libexpat/releases/download/R_${CT_EXPAT_VERSION_TAG}" CT_EXPAT_ARCHIVE_FILENAME="@{pkg_name}-@{version}" CT_EXPAT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" CT_EXPAT_ARCHIVE_FORMATS=".tar.bz2" @@ -862,7 +863,7 @@ 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_MIRRORS="https://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" 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 b7f181adf2..e363c4f79f 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -27,7 +27,7 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no g++-8-arm-linux-gnueabi RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 -RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2 main' +RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main' ENV \ AR_x86_64_fuchsia=x86_64-fuchsia-ar \ diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh index f7acedcfb4..eabff87284 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh @@ -7,7 +7,7 @@ target="x86_64-fortanix-unknown-sgx" install_prereq() { curl https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add - - add-apt-repository -y 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' + add-apt-repository -y 'deb https://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' apt-get update apt-get install -y --no-install-recommends \ build-essential \ 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 4dd4378f19..8242e091cd 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 @@ -69,8 +69,6 @@ COPY host-x86_64/dist-x86_64-linux/build-gcc.sh /tmp/ RUN ./build-gcc.sh && apt-get remove -y gcc g++ COPY host-x86_64/dist-x86_64-linux/build-python.sh /tmp/ -# Build Python 2.7 needed for Clang 10. -RUN ./build-python.sh 2.7.12 # Build Python 3 needed for LLVM 12. RUN ./build-python.sh 3.9.1 @@ -102,7 +100,7 @@ ENV RUST_CONFIGURE_ARGS \ --set llvm.thin-lto=true \ --set llvm.ninja=false \ --set rust.jemalloc -ENV SCRIPT ../src/ci/pgo.sh python2.7 ../x.py dist \ +ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ src/tools/build-manifest diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-binutils.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-binutils.sh index ed0b5c85f7..b5378244b7 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-binutils.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-binutils.sh @@ -4,14 +4,16 @@ set -ex source shared.sh -curl https://ftp.gnu.org/gnu/binutils/binutils-2.25.1.tar.bz2 | tar xfj - +VERSION=2.26.1 + +curl https://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.bz2 | tar xfj - mkdir binutils-build cd binutils-build -hide_output ../binutils-2.25.1/configure --prefix=/rustroot -hide_output make -j10 +hide_output ../binutils-$VERSION/configure --prefix=/rustroot +hide_output make -j$(nproc) hide_output make install cd .. rm -rf binutils-build -rm -rf binutils-2.25.1 +rm -rf binutils-$VERSION 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 969443ac09..40a637616d 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -4,7 +4,7 @@ set -ex source shared.sh -LLVM=llvmorg-10.0.0 +LLVM=llvmorg-12.0.1 mkdir llvm-project cd llvm-project @@ -30,7 +30,7 @@ hide_output \ -DLLVM_ENABLE_PROJECTS="clang;lld" \ -DC_INCLUDE_DIRS="$INC" -hide_output make -j10 +hide_output make -j$(nproc) hide_output make install cd ../.. diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh index e17831a1af..2f6b1fa9b8 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-cmake.sh @@ -9,7 +9,7 @@ curl -L https://github.com/Kitware/CMake/releases/download/v$CMAKE/cmake-$CMAKE. mkdir cmake-build cd cmake-build hide_output ../cmake-$CMAKE/configure --prefix=/rustroot -hide_output make -j10 +hide_output make -j$(nproc) hide_output make install cd .. diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh index a60c6be9f3..6efa789756 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh @@ -30,7 +30,7 @@ hide_output ../curl-$VERSION/configure \ --disable-rtsp \ --disable-ldaps \ --disable-ldap -hide_output make -j10 +hide_output make -j$(nproc) hide_output make install cd .. diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh index fcf869b68b..3a03eb2bdc 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh @@ -22,6 +22,7 @@ cd gcc-$GCC # latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server # instead here. # +# FIXME: use HTTPS (see https://github.com/rust-lang/rust/pull/86586#issuecomment-868355356) sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites ./contrib/download_prerequisites @@ -31,7 +32,7 @@ hide_output ../gcc-$GCC/configure \ --prefix=/rustroot \ --enable-languages=c,c++ \ --disable-gnu-unique-object -hide_output make -j10 +hide_output make -j$(nproc) hide_output make install ln -s gcc /rustroot/bin/cc diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh index d8f6bdb51b..34bbe19d2f 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh @@ -14,7 +14,7 @@ curl $URL | tar xzf - cd openssl-$VERSION hide_output ./config --prefix=/rustroot shared -fPIC -hide_output make -j10 +hide_output make -j$(nproc) hide_output make install cd .. rm -rf openssl-$VERSION diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-python.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-python.sh index 970d67b6db..9a203beadd 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-python.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-python.sh @@ -14,7 +14,7 @@ cd python-build # than that fairly normal. CFLAGS='-I /rustroot/include' LDFLAGS='-L /rustroot/lib -L /rustroot/lib64' \ hide_output ../Python-$VERSION/configure --prefix=/rustroot -hide_output make -j10 +hide_output make -j$(nproc) hide_output make install cd .. diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 66afe84be4..eeabee5b4a 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -38,5 +38,5 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ # Runs checks to ensure that there are no ES5 issues in our JS code. - es-check es5 ../src/librustdoc/html/static/*.js && \ - eslint ../src/librustdoc/html/static/*.js + es-check es5 ../src/librustdoc/html/static/js/*.js && \ + eslint ../src/librustdoc/html/static/js/*.js diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile index 7f1a5820e2..ee3cd092f4 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile @@ -17,7 +17,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libgl1-mesa-dev \ llvm-dev \ libfreetype6-dev \ - libexpat1-dev + libexpat1-dev \ + tidy COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index ee7c223ba5..779b301ff6 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -12,7 +12,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ libssl-dev \ sudo \ - xz-utils + xz-utils \ + tidy # Install dependencies for chromium browser RUN apt-get install -y \ diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index e704071e40..128897e580 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -416,6 +416,10 @@ jobs: env: IMAGE: x86_64-gnu RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable + # Only run this job on the nightly channel. Running this on beta + # could cause failures when `dev: 1` in `stage0.txt`, and running + # this on stable is useless. + CI_ONLY_WHEN_CHANNEL: nightly <<: *job-linux-xl - name: x86_64-gnu-aux diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh index c3c717266d..aa009a4eac 100755 --- a/src/ci/pgo.sh +++ b/src/ci/pgo.sh @@ -4,7 +4,7 @@ set -euxo pipefail rm -rf /tmp/rustc-pgo -python2.7 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \ +python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \ --stage 2 library/std --rust-profile-generate=/tmp/rustc-pgo RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ @@ -15,14 +15,16 @@ function pgo_perf_benchmark { local PERF=1e19fc4c6168d2f7596e512f42f358f245d8f09d local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF local name=$1 + local edition=$2 curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs - RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ + RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=$edition \ --crate-type=lib /tmp/$name.rs } -pgo_perf_benchmark externs -pgo_perf_benchmark ctfe-stress-4 +pgo_perf_benchmark externs 2018 +pgo_perf_benchmark ctfe-stress-4 2018 +pgo_perf_benchmark inflate 2015 cp -pri ../src/tools/cargo /tmp/cargo diff --git a/src/ci/scripts/collect-cpu-stats.sh b/src/ci/scripts/collect-cpu-stats.sh index 08065431f9..853b4628fa 100755 --- a/src/ci/scripts/collect-cpu-stats.sh +++ b/src/ci/scripts/collect-cpu-stats.sh @@ -6,4 +6,4 @@ set -euo pipefail IFS=$'\n\t' -python src/ci/cpu-usage-over-time.py &> cpu-usage.csv & +python3 src/ci/cpu-usage-over-time.py &> cpu-usage.csv & diff --git a/src/ci/scripts/should-skip-this.sh b/src/ci/scripts/should-skip-this.sh index fa738fe70c..bb48fcb5a2 100755 --- a/src/ci/scripts/should-skip-this.sh +++ b/src/ci/scripts/should-skip-this.sh @@ -8,31 +8,43 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -if [[ -z "${CI_ONLY_WHEN_SUBMODULES_CHANGED+x}" ]]; then - echo "Executing the job since there is no skip rule in effect" - exit 0 +if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then + git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF" + BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)" + + echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)" + + if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then + # Submodules pseudo-files inside git have the 160000 permissions, so when + # those files are present in the diff a submodule was updated. + echo "Submodules were updated" + elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then + # There is not an easy blanket search for subtrees. For now, manually list + # the subtrees. + echo "Clippy or rustfmt subtrees were updated" + elif ! (git diff --quiet "$BASE_COMMIT" -- \ + src/test/rustdoc-gui \ + src/librustdoc \ + src/tools/rustdoc-gui); then + # There was a change in either rustdoc or in its GUI tests. + echo "Rustdoc was updated" + else + echo "Not executing this job since no submodules nor subtrees were updated" + ciCommandSetEnv SKIP_JOB 1 + exit 0 + fi fi -git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF" -BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)" - -echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)" - -if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then - # Submodules pseudo-files inside git have the 160000 permissions, so when - # those files are present in the diff a submodule was updated. - echo "Executing the job since submodules are updated" -elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then - # There is not an easy blanket search for subtrees. For now, manually list - # the subtrees. - echo "Executing the job since clippy or rustfmt subtree was updated" -elif ! (git diff --quiet "$BASE_COMMIT" -- \ - src/test/rustdoc-gui \ - src/librustdoc \ - src/tools/rustdoc-gui); then - # There was a change in either rustdoc or in its GUI tests. - echo "Executing the job since rustdoc was updated" -else - echo "Not executing this job since no submodules nor subtrees were updated" - ciCommandSetEnv SKIP_JOB 1 +if [[ -n "${CI_ONLY_WHEN_CHANNEL-}" ]]; then + if [[ "${CI_ONLY_WHEN_CHANNEL}" = "$(cat src/ci/channel)" ]]; then + echo "The channel is the expected one" + else + echo "Not executing this job as the channel is not the expected one" + ciCommandSetEnv SKIP_JOB 1 + exit 0 + fi fi + + +echo "Executing the job since there is no skip rule preventing the execution" +exit 0 diff --git a/src/ci/shared.sh b/src/ci/shared.sh index b095afb542..1f218bc834 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -7,7 +7,7 @@ export MIRRORS_BASE="https://ci-mirrors.rust-lang.org/rustc" -# See http://unix.stackexchange.com/questions/82598 +# See https://unix.stackexchange.com/questions/82598 # Duplicated in docker/dist-various-2/shared.sh function retry { echo "Attempting with retry:" "$@" diff --git a/src/doc/book/ferris.js b/src/doc/book/ferris.js index 5e79b3c711..879799c717 100644 --- a/src/doc/book/ferris.js +++ b/src/doc/book/ferris.js @@ -7,10 +7,6 @@ var ferrisTypes = [ attr: 'panics', title: 'This code panics!' }, - { - attr: 'unsafe', - title: 'This code block contains unsafe code.' - }, { attr: 'not_desired_behavior', title: 'This code does not produce the desired behavior.' 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 930a7d9518..172ae61641 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 @@ -1,7 +1,6 @@ [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml index e3091e7da8..242309f93b 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/src/main.rs b/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/src/main.rs index 19a9cc74b6..c31ebd1dfd 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/src/main.rs +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/src/main.rs @@ -16,12 +16,17 @@ fn first_word(s: &str) -> &str { fn main() { let my_string = String::from("hello world"); - // first_word works on slices of `String`s + // `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 is equivalent + // to a slice of the whole `String` + let word = first_word(&my_string); let my_string_literal = "hello world"; - // first_word works on slices of string literals + // `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[..]); // Because string literals *are* string slices already, diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs b/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs index 3b0a7da659..8619449669 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs @@ -5,7 +5,7 @@ fn main() { let r1 = &s; // no problem let r2 = &s; // no problem println!("{} and {}", r1, r2); - // r1 and r2 are no longer used after this point + // variables r1 and r2 will not be used after this point let r3 = &mut s; // no problem println!("{}", r3); diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/src/lib.rs b/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/src/lib.rs index 09c043bad6..bffbe058d2 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/src/lib.rs +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/src/lib.rs @@ -1,3 +1,4 @@ +// ANCHOR: here //! # Art //! //! A library for modeling artistic concepts. @@ -26,7 +27,8 @@ pub mod utils { pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor { // --snip-- // ANCHOR_END: here - SecondaryColor::Orange + unimplemented!(); // ANCHOR: here } } +// ANCHOR_END: here diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml index 0e3940cf1a..03c641f3e4 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "adder" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml index 8260fb541b..ab555f504b 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "add-one" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml index e73f1becaf..cae6ba5d2b 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "adder" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [dependencies] 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 3b0bb1af16..22e2a51240 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 @@ -1,7 +1,6 @@ [package] name = "add-one" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-14/src/main.rs b/src/doc/book/listings/ch19-advanced-features/listing-19-14/src/main.rs index 7dea568d92..9111fbc55c 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-14/src/main.rs +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-14/src/main.rs @@ -1,6 +1,6 @@ use std::ops::Add; -#[derive(Debug, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq)] struct Point { x: i32, y: i32, diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml index 5a93a685c0..4c4e6f898b 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml index 168cbae53c..80cada3ef0 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "hello_macro_derive" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [lib] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml index cc0addaa4a..f150aec0aa 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "pancakes" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [dependencies] diff --git a/src/doc/book/nostarch/chapter02.md b/src/doc/book/nostarch/chapter02.md new file mode 100644 index 0000000000..c3b6584543 --- /dev/null +++ b/src/doc/book/nostarch/chapter02.md @@ -0,0 +1,1008 @@ + +[TOC] + +# Programming a Guessing Game + +Let’s jump into Rust by working through a hands-on project together! This +chapter introduces you to a few common Rust concepts by showing you how to use +them in a real program. You’ll learn about `let`, `match`, methods, associated +functions, using external crates, and more! The following chapters will explore +these ideas in more detail. In this chapter, you’ll practice the fundamentals. + +We’ll implement a classic beginner programming problem: a guessing game. Here’s +how it works: the program will generate a random integer between 1 and 100. It +will then prompt the player to enter a guess. After a guess is entered, the +program will indicate whether the guess is too low or too high. If the guess is +correct, the game will print a congratulatory message and exit. + +## Setting Up a New Project + +To set up a new project, go to the *projects* directory that you created in +Chapter 1 and make a new project using Cargo, like so: + +``` +$ cargo new guessing_game +$ cd guessing_game +``` + +The first command, `cargo new`, takes the name of the project (`guessing_game`) +as the first argument. The second command changes to the new project’s +directory. + +Look at the generated *Cargo.toml* file: + +Filename: Cargo.toml + +``` +[package] +name = "guessing_game" +version = "0.1.0" +edition = "2018" + + +[dependencies] +``` + +As you saw in Chapter 1, `cargo new` generates a “Hello, world!” program for +you. Check out the *src/main.rs* file: + +Filename: src/main.rs + +``` +fn main() { + println!("Hello, world!"); +} +``` + +Now let’s compile this “Hello, world!” program and run it in the same step +using the `cargo run` command: + +``` +$ cargo run + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) + Finished dev [unoptimized + debuginfo] target(s) in 1.50s + Running `target/debug/guessing_game` +Hello, world! +``` + +The `run` command comes in handy when you need to rapidly iterate on a project, +as we’ll do in this game, quickly testing each iteration before moving on to +the next one. + +Reopen the *src/main.rs* file. You’ll be writing all the code in this file. + +## Processing a Guess + +The first part of the guessing game program will ask for user input, process +that input, and check that the input is in the expected form. To start, we’ll +allow the player to input a guess. Enter the code in Listing 2-1 into +*src/main.rs*. + +Filename: src/main.rs + +``` +use std::io; + +fn main() { + println!("Guess the number!"); + + println!("Please input your guess."); + + let mut guess = String::new(); + + io::stdin() + .read_line(&mut guess) + .expect("Failed to read line"); + + println!("You guessed: {}", guess); +} +``` + +Listing 2-1: Code that gets a guess from the user and prints it + +This code contains a lot of information, so let’s go over it line by line. To +obtain user input and then print the result as output, we need to bring the +`io` (input/output) library into scope. The `io` library comes from the +standard library (which is known as `std`): + +``` +use std::io; +``` + +By default, Rust brings only a few types into the scope of every program in the +*prelude*. If a type you want to use isn’t in the prelude, you have to bring +that type into scope explicitly with a `use` statement. Using the `std::io` +library provides you with a number of useful features, including the ability to +accept user input. + +As you saw in Chapter 1, the `main` function is the entry point into the +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. + +As you also learned in Chapter 1, `println!` is a macro that prints a string to +the screen: + +``` + println!("Guess the number!"); + + println!("Please input your guess."); +``` + +This code is printing a prompt stating what the game is and requesting input +from the user. + +### Storing Values with Variables + +Next, we’ll create a place to store the user input, like this: + +``` + let mut guess = String::new(); +``` + +Now the program is getting interesting! There’s a lot going on in this little +line. Notice that this is a `let` statement, which is used to create a +*variable*. Here’s another example: + +``` +let apples = 5; +``` + +This line creates a new variable named `apples` and binds it to the value 5. In +Rust, variables are immutable by default. We’ll be discussing this concept in +detail in the “Variables and Mutability” section in Chapter 3. The following +example shows how to use `mut` before the variable name to make a variable +mutable: + +``` +let apples = 5; // immutable +let mut bananas = 5; // mutable +``` + +> Note: The `//` syntax starts a comment that continues until the end of the +> line. Rust ignores everything in comments, which are discussed in more detail +> in Chapter 3. + +Let’s return to the guessing game program. You now know that `let mut guess` +will introduce a mutable variable named `guess`. On the other side of the equal +sign (`=`) is the value that `guess` is bound to, which is the result of +calling `String::new`, a function that returns a new instance of a `String`. +`String` is a string type provided by the standard library that is a growable, +UTF-8 encoded bit of text. + +The `::` syntax in the `::new` line indicates that `new` is an *associated +function* of the `String` type. An associated function is implemented on a +type, in this case `String`. + +This `new` function creates a new, empty string. You’ll find a `new` function +on many types, because it’s a common name for a function that makes a new value +of some kind. + +To summarize, the `let mut guess = String::new();` line has created a mutable +variable that is currently bound to a new, empty instance of a `String`. Whew! + +Recall that we included the input/output functionality from the standard +library with `use std::io;` on the first line of the program. Now we’ll call +the `stdin` function from the `io` module: + +``` + io::stdin() + .read_line(&mut guess) +``` + +If we hadn’t put the `use std::io` line at the beginning of the program, we +could have written this function call as `std::io::stdin`. The `stdin` function +returns an instance of `std::io::Stdin`, which is a type that represents a +handle to the standard input for your terminal. + +The next part of the code, `.read_line(&mut guess)`, calls the `read_line` +method on the standard input handle to get input from the user. We’re also +passing one argument to `read_line`: `&mut guess`. + +The job of `read_line` is to take whatever the user types into standard input +and append that into a string (without overwriting its contents), so it takes +that string as an argument. The string argument needs to be mutable so the +method can change the string’s content by adding the user input. + +The `&` indicates that this argument is a *reference*, which gives you a way to +let multiple parts of your code access one piece of data without needing to +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 +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 + +We’re still working on this line of code. Although we’re now discussing a third +line of text, it’s still part of a single logical line of code. The next part +is this method: + +``` + .expect("Failed to read line"); +``` + +When you call a method with the `.method_name()` syntax, it’s often wise to +introduce a newline and other whitespace to help break up long lines. We could +have written this code as: + +``` +io::stdin().read_line(&mut guess).expect("Failed to read line"); +``` + +However, one long line is difficult to read, so it’s best to divide it. Now +let’s discuss what this line does. + +As mentioned earlier, `read_line` puts what the user types into the string +we’re passing it, but it also returns a value—in this case, an `io::Result`. +Rust has a number of types named `Result` in its standard library: a generic +`Result` as well as specific versions for submodules, such as `io::Result`. + +The `Result` types are *enumerations*, often referred to as *enums*. An +enumeration is a type that can have a fixed set of values, and those values are +called the enum’s *variants*. Chapter 6 will cover enums in more detail. + +For `Result`, the variants are `Ok` or `Err`. The `Ok` variant indicates the +operation was successful, and inside `Ok` is the successfully generated value. +The `Err` variant means the operation failed, and `Err` contains information +about how or why the operation failed. + +The purpose of these `Result` types is to encode error-handling information. +Values of the `Result` type, like values of any type, have methods defined on +them. An instance of `io::Result` has an `expect` method that you can call. If +this instance of `io::Result` is an `Err` value, `expect` will cause the +program to crash and display the message that you passed as an argument to +`expect`. If the `read_line` method returns an `Err`, it would likely be the +result of an error coming from the underlying operating system. If this +instance of `io::Result` is an `Ok` value, `expect` will take the return value +that `Ok` is holding and return just that value to you so you can use it. In +this case, that value is the number of bytes in what the user entered into +standard input. + +If you don’t call `expect`, the program will compile, but you’ll get a warning: + +``` +$ cargo build + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) +warning: unused `Result` that must be used + --> src/main.rs:10:5 + | +10 | io::stdin().read_line(&mut guess); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: this `Result` may be an `Err` variant, which should be handled + +warning: 1 warning emitted + + Finished dev [unoptimized + debuginfo] target(s) in 0.59s +``` + +Rust warns that you haven’t used the `Result` value returned from `read_line`, +indicating that the program hasn’t handled a possible error. + +The right way to suppress the warning is to actually write error handling, but +because you just want to crash this program when a problem occurs, you can use +`expect`. You’ll learn about recovering from errors in Chapter 9. + +### Printing Values with `println!` Placeholders + +Aside from the closing curly bracket, there’s only one more line to discuss in +the code added so far, which is the following: + +``` + println!("You guessed: {}", guess); +``` + +This line prints the string we saved the user’s input in. The set of curly +brackets, `{}`, is a placeholder: think of `{}` as little crab pincers that +hold a value in place. You can print more than one value using curly brackets: +the first set of curly brackets holds the first value listed after the format +string, the second set holds the second value, and so on. Printing multiple +values in one call to `println!` would look like this: + +``` +let x = 5; +let y = 10; + +println!("x = {} and y = {}", x, y); +``` + +This code would print `x = 5 and y = 10`. + +### Testing the First Part + +Let’s test the first part of the guessing game. Run it using `cargo run`: + +``` +$ cargo run + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) + Finished dev [unoptimized + debuginfo] target(s) in 6.44s + Running `target/debug/guessing_game` +Guess the number! +Please input your guess. +6 +You guessed: 6 +``` + +At this point, the first part of the game is done: we’re getting input from the +keyboard and then printing it. + +## Generating a Secret Number + +Next, we need to generate a secret number that the user will try to guess. The +secret number should be different every time so the game is fun to play more +than once. Let’s use a random number between 1 and 100 so the game isn’t too +difficult. Rust doesn’t yet include random number functionality in its standard +library. However, the Rust team does provide a `rand` crate at +*https://crates.io/crates/rand*. + +### Using a Crate to Get More Functionality + +Remember that a crate is a collection of Rust source code files. The project +we’ve been building is a *binary crate*, which is an executable. The `rand` +crate is a *library crate*, which contains code intended to be used in other +programs. + +Cargo’s coordination of external crates is where Cargo really shines. Before we +can write code that uses `rand`, we need to modify the *Cargo.toml* file to +include the `rand` crate as a dependency. Open that file now and add the +following line to the bottom beneath the `[dependencies]` section header that +Cargo created for you. Be sure to specify `rand` exactly as we have here, or +the code examples in this tutorial may not work. + +Filename: Cargo.toml + +``` +rand = "0.8.3" +``` + +In the *Cargo.toml* file, everything that follows a header is part of a section +that continues until another section starts. The `[dependencies]` section is +where you tell Cargo which external crates your project depends on and which +versions of those crates you require. In this case, we’ll specify the `rand` +crate with the semantic version specifier `0.8.3`. Cargo understands Semantic +Versioning (sometimes called *SemVer*), which is a standard for writing version +numbers. The number `0.8.3` is actually shorthand for `^0.8.3`, which means any +version that is at least `0.8.3` but below `0.9.0`. Cargo considers these +versions to have public APIs compatible with version `0.8.3`, and this +specification ensures you'll get the latest patch release that will still +compile with the code in this chapter. Any version `0.9.0` or greater is not +guaranteed to have the same API as what the following examples use. + +Now, without changing any of the code, let’s build the project, as shown in +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 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 +``` + +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. + +Now that we have an external dependency, Cargo fetches the latest versions of +everything from the *registry*, which is a copy of data from Crates.io at +*https://crates.io/*. Crates.io is where people in the Rust ecosystem post +their open source Rust projects for others to use. + +After updating the registry, Cargo checks the `[dependencies]` section and +downloads any crates you don’t have yet. In this case, although we only listed +`rand` as a dependency, Cargo also grabbed other crates that `rand` depends on +to work. After downloading the crates, Rust compiles them and then compiles the +project with the dependencies available. + +If you immediately run `cargo build` again without making any changes, you +won’t get any output aside from the `Finished` line. Cargo knows it has already +downloaded and compiled the dependencies, and you haven’t changed anything +about them in your *Cargo.toml* file. Cargo also knows that you haven’t changed +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: + +``` +$ cargo build + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) + Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs +``` + +These lines show Cargo only updates the build with your tiny change to the +*src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can +reuse what it has already downloaded and compiled for those. It just rebuilds +your part of the code. + +#### Ensuring Reproducible Builds with the *Cargo.lock* File + +Cargo has a mechanism that ensures you can rebuild the same artifact every time +you or anyone else builds your code: Cargo will use only the versions of the +dependencies you specified until you indicate otherwise. For example, what +happens if next week version 0.8.4 of the `rand` crate comes out, and that +version contains an important bug fix, but it also contains a regression that +will break your code? + +The answer to this problem is the *Cargo.lock* file, which was created the +first time you ran `cargo build` and is now in your *guessing_game* directory. +When you build a project for the first time, Cargo figures out all the +versions of the dependencies that fit the criteria and then writes them to +the *Cargo.lock* file. When you build your project in the future, Cargo will +see that the *Cargo.lock* file exists and 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. + +#### Updating a Crate to Get a New Version + +When you *do* want to update a crate, Cargo provides another command, `update`, +which will ignore the *Cargo.lock* file and figure out all the latest versions +that fit your specifications in *Cargo.toml*. If that works, Cargo will write +those versions to the *Cargo.lock* file. + +But by default, Cargo will only look for versions greater than `0.8.3` and less +than `0.9.0`. If the `rand` crate has released two new versions, `0.8.4` and +`0.9.0`, you would see the following if you ran `cargo update`: + +``` +$ cargo update + Updating crates.io index + Updating rand v0.8.3 -> v0.8.4 +``` + +At this point, you would also notice a change in your *Cargo.lock* file noting +that the version of the `rand` crate you are now using is `0.8.4`. + +If you wanted to use `rand` version `0.9.0` or any version in the `0.9.x` +series, you’d have to update the *Cargo.toml* file to look like this instead: + +``` +[dependencies] +rand = "0.9.0" +``` + +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 +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. + +### Generating a Random Number + +Now that you’ve added the `rand` crate to *Cargo.toml*, let’s start using +`rand`. The next step is to update *src/main.rs*, as shown in Listing 2-3. + +Filename: src/main.rs + +``` +use std::io; +use rand::Rng; + +fn main() { + println!("Guess the number!"); + + let secret_number = rand::thread_rng().gen_range(1..101); + + println!("The secret number is: {}", secret_number); + + println!("Please input your guess."); + + let mut guess = String::new(); + + io::stdin() + .read_line(&mut guess) + .expect("Failed to read line"); + + println!("You guessed: {}", guess); +} +``` + +Listing 2-3: Adding code to generate a random number + +First, we add a `use` line: `use rand::Rng`. The `Rng` trait defines +methods that random number generators implement, and this trait must be in +scope for us to use those methods. Chapter 10 will cover traits in detail. + +Next, we’re adding two lines in the middle. The `rand::thread_rng` function +will give us the particular random number generator that we’re going to use: +one that is local to the current thread of execution and seeded by the +operating system. Then we call the `gen_range` method on the random number +generator. This method is defined by the `Rng` trait that we brought into scope +with the `use rand::Rng` statement. The `gen_range` method takes a range +expression as an argument and generates a random number in the range. The kind +of range expression we’re using here takes the form `start..end`. It’s +inclusive on the lower bound but exclusive on the upper bound, so we need to +specify `1..101` to request a number between 1 and 100. Alternatively, we could +pass the range `1..=100`, which is equivalent. + +> Note: You won’t just know which traits to use and which methods and functions +> to call from a crate. Instructions for using a crate are in each crate’s +> documentation. Another neat feature of Cargo is that you can run the `cargo +> doc --open` command, which will build documentation provided by all of your +> dependencies locally and open it in your browser. If you’re interested in +> other functionality in the `rand` crate, for example, run `cargo doc --open` +> and click `rand` in the sidebar on the left. + +The second line that we added to the middle of the code prints the secret +number. This is useful while we’re developing the program to be able to test +it, but we’ll delete it from the final version. It’s not much of a game if the +program prints the answer as soon as it starts! + +Try running the program a few times: + +``` +$ cargo run + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) + Finished dev [unoptimized + debuginfo] target(s) in 2.53s + Running `target/debug/guessing_game` +Guess the number! +The secret number is: 7 +Please input your guess. +4 +You guessed: 4 + +$ cargo run + Finished dev [unoptimized + debuginfo] target(s) in 0.02s + Running `target/debug/guessing_game` +Guess the number! +The secret number is: 83 +Please input your guess. +5 +You guessed: 5 +``` + +You should get different random numbers, and they should all be numbers between +1 and 100. Great job! + +## 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. + +Filename: src/main.rs + +``` +use rand::Rng; +use std::cmp::Ordering; +use std::io; + +fn main() { + // --snip-- + + println!("You guessed: {}", guess); + + match guess.cmp(&secret_number) { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), + } +} +``` + +Listing 2-4: Handling the possible return values of +comparing two numbers + +The first new bit here is another `use` statement, bringing a type called +`std::cmp::Ordering` into scope from the standard library. Like `Result`, +`Ordering` is another enum, but the variants for `Ordering` are `Less`, +`Greater`, and `Equal`. These are the three outcomes that are possible when you +compare two values. + +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 +`Ordering` enum we brought into scope with the `use` statement. We use a +`match` expression to decide what to do next based on which variant of +`Ordering` was returned from the call to `cmp` with the values in `guess` and +`secret_number`. + +A `match` expression is made up of *arms*. An arm consists of a *pattern* and +the code that should be run if the value given to the beginning of the `match` +expression fits that arm’s pattern. Rust takes the value given to `match` and +looks through each arm’s pattern in turn. The `match` construct and patterns +are powerful features in Rust that let you express a variety of situations your +code might encounter and make sure that you handle them all. These features +will be covered in detail in Chapter 6 and Chapter 18, respectively. + +Let’s walk through an example of what would happen with the `match` expression +used here. Say that the user has guessed 50 and the randomly generated secret +number this time is 38. When the code compares 50 to 38, the `cmp` method will +return `Ordering::Greater`, because 50 is greater than 38. The `match` +expression gets the `Ordering::Greater` value and starts checking each arm’s +pattern. It looks at the first arm’s pattern, `Ordering::Less`, and sees that +the value `Ordering::Greater` does not match `Ordering::Less`, so it ignores +the code in that arm and moves to the next arm. The next arm’s pattern, +`Ordering::Greater`, *does* match `Ordering::Greater`! The associated code in +that arm will execute and print `Too big!` to the screen. The `match` +expression ends because it has no need to look at the last arm in this scenario. + +However, the code in Listing 2-4 won’t compile yet. Let’s try it: + +``` +$ cargo build + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) +error[E0308]: mismatched types + --> src/main.rs:22:21 + | +22 | match guess.cmp(&secret_number) { + | ^^^^^^^^^^^^^^ expected struct `String`, found integer + | + = note: expected reference `&String` + found reference `&{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. +error: could not compile `guessing_game` + +To learn more, run the command again with --verbose. +``` + +The core of the error states that there are *mismatched types*. Rust has a +strong, static type system. However, it also has type inference. When we wrote +`let mut guess = String::new()`, Rust was able to infer that `guess` should be +a `String` and didn’t make us write the type. The `secret_number`, on the other +hand, is a number type. A few number types can have a value between 1 and 100: +`i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a 64-bit +number; as well as others. Rust defaults to an `i32`, which is the type of +`secret_number` unless you add type information elsewhere that would cause Rust +to infer a different numerical type. The reason for the error is that Rust +cannot compare a string and a number type. + +Ultimately, we want to convert the `String` the program reads as input into a +real number type so we can compare it numerically to the secret number. We can +do that by adding another line to the `main` function body: + +Filename: src/main.rs + +``` + // --snip-- + + let mut guess = String::new(); + + io::stdin() + .read_line(&mut guess) + .expect("Failed to read line"); + + let guess: u32 = guess.trim().parse().expect("Please type a number!"); + + println!("You guessed: {}", guess); + + match guess.cmp(&secret_number) { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), + } +``` + +The line is: + +``` +let guess: u32 = guess.trim().parse().expect("Please type a number!"); +``` + +We create a variable named `guess`. But wait, doesn’t the program already have +a variable named `guess`? It does, but Rust allows us to *shadow* the previous +value of `guess` with a new one. This feature is often used in situations in +which you want to convert a value from one type to another type. Shadowing lets +us reuse the `guess` variable name rather than forcing us to create two unique +variables, such as `guess_str` and `guess` for example. (Chapter 3 covers +shadowing in more detail.) + +We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the +expression refers to the original `guess` that was a `String` with the input in +it. The `trim` method on a `String` instance will eliminate any whitespace at +the beginning and end. Although `u32` can contain only numerical characters, +the user must press enter to satisfy +`read_line`. When the user presses enter, a +newline character is added to the string. For example, if the user types 5 and presses enter, +`guess` looks like this: `5\n`. The `\n` represents “newline,” the result of +pressing enter (On Windows, pressing 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 parses a string into some kind of number. Because +this method can parse a variety of number types, 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! + +The call to `parse` could easily cause an error. 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. + +Let’s run the program now! + +``` +$ cargo run + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) + Finished dev [unoptimized + debuginfo] target(s) in 0.43s + Running `target/debug/guessing_game` +Guess the number! +The secret number is: 58 +Please input your guess. + 76 +You guessed: 76 +Too big! +``` + +Nice! Even though spaces were added before the guess, the program still figured +out that the user guessed 76. Run the program a few times to verify the +different behavior with different kinds of input: guess the number correctly, +guess a number that is too high, and guess a number that is too low. + +We have most of the game working now, but the user can make only one guess. +Let’s change that by adding a loop! + +## Allowing Multiple Guesses with Looping + +The `loop` keyword creates an infinite loop. We’ll add that now to give users +more chances at guessing the number: + +Filename: src/main.rs + +``` + // --snip-- + + println!("The secret number is: {}", secret_number); + + loop { + println!("Please input your guess."); + + // --snip-- + + match guess.cmp(&secret_number) { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => println!("You win!"), + } + } +} +``` + +As you can see, we’ve moved everything into a loop from the guess input prompt +onward. Be sure to indent the lines inside the loop another four spaces each +and run the program again. Notice that there is a new problem because the +program is doing exactly what we told it to do: ask for another guess forever! +It doesn’t seem like the user can quit! + +The user could always interrupt the program by using the keyboard shortcut +ctrl-c. But there’s another way to escape this +insatiable monster, as mentioned in the `parse` discussion in “Comparing the +Guess to the Secret Number”: if the user enters a non-number answer, the +program will crash. The user can take advantage of that in order to quit, as +shown here: + +``` +$ cargo run + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) + Finished dev [unoptimized + debuginfo] target(s) in 1.50s + Running `target/debug/guessing_game` +Guess the number! +The secret number is: 59 +Please input your guess. +45 +You guessed: 45 +Too small! +Please input your guess. +60 +You guessed: 60 +Too big! +Please input your guess. +59 +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 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +Typing `quit` actually quits the game, but so will any other non-number input. +However, this is suboptimal to say the least. We want the game to automatically +stop when the correct number is guessed. + +### Quitting After a Correct Guess + +Let’s program the game to quit when the user wins by adding a `break` statement: + +Filename: src/main.rs + +``` + // --snip-- + + match guess.cmp(&secret_number) { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => { + println!("You win!"); + break; + } + } + } +} +``` + +Adding the `break` line after `You win!` makes the program exit the loop when +the user guesses the secret number correctly. Exiting the loop also means +exiting the program, because the loop is the last part of `main`. + +### Handling Invalid Input + +To further refine the game’s behavior, rather than crashing the program when +the user inputs a non-number, let’s make the game ignore a non-number so the +user can continue guessing. We can do that by altering the line where `guess` +is converted from a `String` to a `u32`, as shown in Listing 2-5. + +Filename: src/main.rs + +``` + // --snip-- + + io::stdin() + .read_line(&mut guess) + .expect("Failed to read line"); + + let guess: u32 = match guess.trim().parse() { + Ok(num) => num, + Err(_) => continue, + }; + + println!("You guessed: {}", guess); + + // --snip-- +``` + +Listing 2-5: Ignoring a non-number guess and asking for another guess instead +of crashing the program + +Switching from an `expect` call to a `match` expression is one way of moving +from crashing on an error to handling the error. Remember that `parse` returns +a `Result` type and `Result` is an enum that has the variants `Ok` or `Err`. +We’re using a `match` expression here, as we did with the `Ordering` result of +the `cmp` method. + +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 +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. + +If `parse` is *not* able to turn the string into a number, it will return an +`Err` value that contains more information about the error. The `Err` value +does not match the `Ok(num)` pattern in the first `match` arm, but it does +match the `Err(_)` pattern in the second arm. The underscore, `_`, is a +catchall value; in this example, we’re saying we want to match all `Err` +values, no matter what information they have inside them. So the program will +execute the second arm’s code, `continue`, which tells the program to go to the +next iteration of the `loop` and ask for another guess. So, effectively, the +program ignores all errors that `parse` might encounter! + +Now everything in the program should work as expected. Let’s try it: + +``` +$ cargo run + Compiling guessing_game v0.1.0 (file:///projects/guessing_game) + Finished dev [unoptimized + debuginfo] target(s) in 4.45s + Running `target/debug/guessing_game` +Guess the number! +The secret number is: 61 +Please input your guess. +10 +You guessed: 10 +Too small! +Please input your guess. +99 +You guessed: 99 +Too big! +Please input your guess. +foo +Please input your guess. +61 +You guessed: 61 +You win! +``` + +Awesome! With one tiny final tweak, we will finish the guessing game. Recall +that the program is still printing the secret number. That worked well for +testing, but it ruins the game. Let’s delete the `println!` that outputs the +secret number. Listing 2-6 shows the final code. + +Filename: src/main.rs + +``` +use rand::Rng; +use std::cmp::Ordering; +use std::io; + +fn main() { + println!("Guess the number!"); + + let secret_number = rand::thread_rng().gen_range(1..101); + + loop { + println!("Please input your guess."); + + let mut guess = String::new(); + + io::stdin() + .read_line(&mut guess) + .expect("Failed to read line"); + + let guess: u32 = match guess.trim().parse() { + Ok(num) => num, + Err(_) => continue, + }; + + println!("You guessed: {}", guess); + + match guess.cmp(&secret_number) { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => { + println!("You win!"); + break; + } + } + } +} +``` + +Listing 2-6: Complete guessing game code + +## Summary + +At this point, you’ve successfully built the guessing game. Congratulations! + +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 +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/src/appendix-02-operators.md b/src/doc/book/src/appendix-02-operators.md index 965b2371f5..925862916e 100644 --- a/src/doc/book/src/appendix-02-operators.md +++ b/src/doc/book/src/appendix-02-operators.md @@ -27,7 +27,7 @@ overload that operator is listed. | `&&` | `expr && expr` | Short-circuiting logical AND | | | `*` | `expr * expr` | Arithmetic multiplication | `Mul` | | `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulAssign` | -| `*` | `*expr` | Dereference | | +| `*` | `*expr` | Dereference | `Deref` | | `*` | `*const type`, `*mut type` | Raw pointer | | | `+` | `trait + trait`, `'a + trait` | Compound type constraint | | | `+` | `expr + expr` | Arithmetic addition | `Add` | @@ -38,11 +38,11 @@ overload that operator is listed. | `-=` | `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 | | -| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | | +| `..` | `..`, `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` | In a pattern: inclusive range pattern | | +| `...` | `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 | | diff --git a/src/doc/book/src/appendix-06-translation.md b/src/doc/book/src/appendix-06-translation.md index cbd39743c9..d95ea675e0 100644 --- a/src/doc/book/src/appendix-06-translation.md +++ b/src/doc/book/src/appendix-06-translation.md @@ -8,6 +8,7 @@ For resources in languages other than English. Most are still in progress; see - [Português](https://github.com/rust-br/rust-book-pt-br) (BR) - [Português](https://github.com/nunojesus/rust-book-pt-pt) (PT) - [简体中文](https://github.com/KaiserY/trpl-zh-cn) +- [正體中文](https://github.com/rust-tw/book-tw) - [Українська](https://github.com/pavloslav/rust-book-uk-ua) - [Español](https://github.com/thecodix/book), [alternate](https://github.com/ManRR/rust-book-es) - [Italiano](https://github.com/AgeOfWar/rust-book-it) @@ -25,3 +26,5 @@ For resources in languages other than English. Most are still in progress; see - [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) diff --git a/src/doc/book/src/ch00-00-introduction.md b/src/doc/book/src/ch00-00-introduction.md index c3d7c4a6e5..2a1b7745c0 100644 --- a/src/doc/book/src/ch00-00-introduction.md +++ b/src/doc/book/src/ch00-00-introduction.md @@ -173,12 +173,11 @@ 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. Ferris will also help you distinguish code that isn’t meant to work: -| Ferris | Meaning | -|------------------------------------------------------------------------|--------------------------------------------------| -| | This code does not compile! | -| | This code panics! | -| | This code block contains unsafe code. | -| | This code does not produce the desired behavior. | +| Ferris | Meaning | +|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| +| Ferris with a question mark | This code does not compile! | +| Ferris throwing up their hands | This code panics! | +| Ferris with one claw up, shrugging | This code does not produce the desired behavior. | In most situations, we’ll lead you to the correct version of any code that doesn’t compile. diff --git a/src/doc/book/src/ch01-01-installation.md b/src/doc/book/src/ch01-01-installation.md index f343d50094..96e45aebd0 100644 --- a/src/doc/book/src/ch01-01-installation.md +++ b/src/doc/book/src/ch01-01-installation.md @@ -39,13 +39,21 @@ for your password. If the install is successful, the following line will appear: Rust is installed now. Great! ``` -Additionally, you’ll need a linker of some kind. It’s likely one is already -installed, but when you try to compile a Rust program and get errors indicating -that a linker could not execute, that means a linker isn’t installed on your -system and you’ll need to install one manually. C compilers usually come with -the correct linker. Check your platform’s documentation for how to install a C -compiler. Also, some common Rust packages depend on C code and will need a C -compiler. Therefore, it might be worth installing one now. +You will also need a linker, which is a program that Rust uses to join its +compiled outputs into one file. It is likely you already have one. If you get +linker errors, you should install a C compiler, which will typically include a +linker. A C compiler is also useful because some common Rust packages depend on +C code and will need a C compiler. + +On macOS, you can get a C compiler by running: + +```console +$ xcode-select --install +``` + +Linux users should generally install GCC or Clang, according to their +distribution's documentation. For example, if you use Ubuntu, you can install +the `build-essential` package. ### Installing `rustup` on Windows diff --git a/src/doc/book/src/ch01-02-hello-world.md b/src/doc/book/src/ch01-02-hello-world.md index 69f59dfc98..98ba880715 100644 --- a/src/doc/book/src/ch01-02-hello-world.md +++ b/src/doc/book/src/ch01-02-hello-world.md @@ -125,7 +125,8 @@ First, Rust style is to indent with four spaces, not a tab. Second, `println!` calls a Rust macro. If it called a function instead, it would be entered as `println` (without the `!`). We’ll discuss Rust macros in more detail in Chapter 19. For now, you just need to know that using a `!` -means that you’re calling a macro instead of a normal function. +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 to `println!`, and the string is printed to the screen. diff --git a/src/doc/book/src/ch01-03-hello-cargo.md b/src/doc/book/src/ch01-03-hello-cargo.md index 0f11be8ade..2c018a04da 100644 --- a/src/doc/book/src/ch01-03-hello-cargo.md +++ b/src/doc/book/src/ch01-03-hello-cargo.md @@ -3,7 +3,8 @@ Cargo is Rust’s build system and package manager. Most Rustaceans use this tool to manage their Rust projects because Cargo handles a lot of tasks for you, such as building your code, downloading the libraries your code depends on, and -building those libraries. (We call libraries your code needs *dependencies*.) +building those libraries. (We call the libraries that your code needs +*dependencies*.) The simplest Rust programs, like the one we’ve written so far, don’t have any dependencies. So if we had built the “Hello, world!” project with Cargo, it @@ -63,7 +64,6 @@ code in Listing 1-2. [package] name = "hello_cargo" version = "0.1.0" -authors = ["Your Name "] edition = "2018" [dependencies] @@ -79,11 +79,9 @@ The first line, `[package]`, is a section heading that indicates that the following statements are configuring a package. As we add more information to this file, we’ll add other sections. -The next four lines set the configuration information Cargo needs to compile -your program: the name, the version, who wrote it, and the edition of Rust to -use. Cargo gets your name and email information from your environment, so if -that information is not correct, fix the information now and then save the -file. We’ll talk about the `edition` key in Appendix E. +The next three lines set the configuration information Cargo needs to compile +your program: the name, the version, and the edition of Rust to use. We’ll talk +about the `edition` key in [Appendix E][appendix-e]. The last line, `[dependencies]`, is the start of a section for you to list any of your project’s dependencies. In Rust, packages of code are referred to as @@ -249,3 +247,4 @@ 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 +[appendix-e]: appendix-05-editions.html 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 ba494eb944..761dc218a9 100644 --- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md +++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md @@ -34,9 +34,6 @@ Look at the generated *Cargo.toml* file: {{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml}} ``` -If the author information that Cargo obtained from your environment is not -correct, fix that in the file and save it again. - As you saw in Chapter 1, `cargo new` generates a “Hello, world!” program for you. Check out the *src/main.rs* file: @@ -125,19 +122,18 @@ line. Notice that this is a `let` statement, which is used to create a *variable*. Here’s another example: ```rust,ignore -let foo = bar; +let apples = 5; ``` -This line creates a new variable named `foo` and binds it to the value of the -`bar` variable. In Rust, variables are immutable by default. We’ll be -discussing this concept in detail in the [“Variables and -Mutability”][variables-and-mutability] section in Chapter 3. -The following example shows how to use `mut` before the variable name to make -a variable mutable: +This line creates a new variable named `apples` and binds it to the value 5. In +Rust, variables are immutable by default. We’ll be discussing this concept in +detail in the [“Variables and Mutability”][variables-and-mutability] section in Chapter 3. The following example shows how to use `mut` before +the variable name to make a variable mutable: ```rust,ignore -let foo = 5; // immutable -let mut bar = 5; // mutable +let apples = 5; // immutable +let mut bananas = 5; // mutable ``` > Note: The `//` syntax starts a comment that continues until the end of the @@ -154,9 +150,8 @@ library that is a growable, UTF-8 encoded bit of text. [string]: ../std/string/struct.String.html The `::` syntax in the `::new` line indicates that `new` is an *associated -function* of the `String` type. An associated function is implemented on a type, -in this case `String`, rather than on a particular instance of a `String`. Some -languages call this a *static method*. +function* of the `String` type. An associated function is implemented on a +type, in this case `String`. This `new` function creates a new, empty string. You’ll find a `new` function on many types, because it’s a common name for a function that makes a new value @@ -212,9 +207,9 @@ is this method: {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:expect}} ``` -When you call a method with the `.foo()` syntax, it’s often wise to introduce a -newline and other whitespace to help break up long lines. We could have -written this code as: +When you call a method with the `.method_name()` syntax, it’s often wise to +introduce a newline and other whitespace to help break up long lines. We could +have written this code as: ```rust,ignore io::stdin().read_line(&mut guess).expect("Failed to read line"); @@ -332,17 +327,17 @@ library. However, the Rust team does provide a [`rand` crate][randcrate]. ### Using a Crate to Get More Functionality -Remember that a crate is a collection of Rust source code files. -The project we’ve been building is a *binary crate*, which is an executable. -The `rand` crate is a *library crate*, which contains code intended to be -used in other programs. +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. -Cargo’s use of external crates is where it really shines. Before we can write -code that uses `rand`, we need to modify the *Cargo.toml* file to include the -`rand` crate as a dependency. Open that file now and add the following line to -the bottom beneath the `[dependencies]` section header that Cargo created for -you. Be sure to specify `rand` exactly as we have here, or the code examples in -this tutorial may not work. +Cargo’s coordination of external crates is where Cargo really shines. Before we +can write code that uses `rand`, we need to modify the *Cargo.toml* file to +include the `rand` crate as a dependency. Open that file now and add the +following line to the bottom beneath the `[dependencies]` section header that +Cargo created for you. Be sure to specify `rand` exactly as we have here, or +the code examples in this tutorial may not work. 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: Filename: src/main.rs @@ -303,3 +307,4 @@ 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`. [strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings +[deref-coercions]: ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods diff --git a/src/doc/book/src/ch06-01-defining-an-enum.md b/src/doc/book/src/ch06-01-defining-an-enum.md index be794ce5b5..24b2130ba3 100644 --- a/src/doc/book/src/ch06-01-defining-an-enum.md +++ b/src/doc/book/src/ch06-01-defining-an-enum.md @@ -141,7 +141,7 @@ different amounts and types of values

(&mut self, predicate: P) -> Option where @@ -384,30 +346,10 @@ where { fuse!(self.iter.rfind(predicate)) } - - #[inline] - default fn len(&self) -> usize - where - I: ExactSizeIterator, - { - match self.iter { - Some(ref iter) => iter.len(), - None => 0, - } - } - - #[inline] - default fn is_empty(&self) -> bool - where - I: ExactSizeIterator, - { - match self.iter { - Some(ref iter) => iter.is_empty(), - None => true, - } - } } +/// Specialized `Fuse` impl which doesn't bother clearing `iter` when exhausted. +/// However, we must still be prepared for the possibility that it was already cleared! #[doc(hidden)] impl FuseImpl for Fuse where @@ -415,45 +357,25 @@ where { #[inline] fn next(&mut self) -> Option<::Item> { - unchecked!(self).next() + spec!(self.iter.next()) } #[inline] fn nth(&mut self, n: usize) -> Option { - unchecked!(self).nth(n) - } - - #[inline] - fn last(self) -> Option { - unchecked!(self).last() + spec!(self.iter.nth(n)) } #[inline] - fn count(self) -> usize { - unchecked!(self).count() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - unchecked!(self).size_hint() - } - - #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R + fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - unchecked!(self).try_fold(init, fold) - } - - #[inline] - fn fold(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - unchecked!(self).fold(init, fold) + if let Some(ref mut iter) = self.iter { + acc = iter.try_fold(acc, fold)?; + } + try { acc } } #[inline] @@ -461,7 +383,7 @@ where where P: FnMut(&Self::Item) -> bool, { - unchecked!(self).find(predicate) + spec!(self.iter.find(predicate)) } #[inline] @@ -469,7 +391,7 @@ where where I: DoubleEndedIterator, { - unchecked!(self).next_back() + spec!(self.iter.next_back()) } #[inline] @@ -477,27 +399,21 @@ where where I: DoubleEndedIterator, { - unchecked!(self).nth_back(n) + spec!(self.iter.nth_back(n)) } #[inline] - fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, I: DoubleEndedIterator, { - unchecked!(self).try_rfold(init, fold) - } - - #[inline] - fn rfold(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - I: DoubleEndedIterator, - { - unchecked!(self).rfold(init, fold) + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + } + try { acc } } #[inline] @@ -506,43 +422,6 @@ where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { - unchecked!(self).rfind(predicate) - } - - #[inline] - fn len(&self) -> usize - where - I: ExactSizeIterator, - { - unchecked!(self).len() - } - - #[inline] - fn is_empty(&self) -> bool - where - I: ExactSizeIterator, - { - unchecked!(self).is_empty() + spec!(self.iter.rfind(predicate)) } } - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Fuse -where - I: SourceIter, -{ - type Source = S; - - #[inline] - unsafe fn as_inner(&mut self) -> &mut S { - match self.iter { - // SAFETY: unsafe function forwarding to unsafe function with the same requirements - Some(ref mut iter) => unsafe { SourceIter::as_inner(iter) }, - // SAFETY: the specialized iterator never sets `None` - None => unsafe { intrinsics::unreachable() }, - } - } -} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Fuse {} diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 0bf9f4b032..dc86eccfcb 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -122,6 +122,7 @@ where self.iter.fold(init, map_fold(self.f, g)) } + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B where Self: TrustedRandomAccess, diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 9fdd4fca04..a3fbf4d9c3 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -54,7 +54,7 @@ pub use self::zip::TrustedRandomAccess; #[unstable(feature = "iter_zip", issue = "83574")] pub use self::zip::zip; -/// This trait provides transitive access to source-stage in an interator-adapter pipeline +/// This trait provides transitive access to source-stage in an iterator-adapter pipeline /// under the conditions that /// * the iterator source `S` itself implements `SourceIter` /// * there is a delegating implementation of this trait for each adapter in the pipeline between diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 69bd2996ef..91fa1a9ad3 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -130,7 +130,6 @@ where } #[inline] - #[cfg(not(bootstrap))] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, @@ -150,28 +149,6 @@ where } } - #[inline] - #[cfg(bootstrap)] - fn try_rfold(&mut self, init: B, mut f: F) -> R - where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try, - { - let _use_the_import: ControlFlow<()>; - match self.peeked.take() { - Some(None) => try { init }, - Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() { - Ok(acc) => f(acc, v), - Err(e) => { - self.peeked = Some(Some(v)); - R::from_error(e) - } - }, - None => self.iter.try_rfold(init, f), - } - } - #[inline] fn rfold(self, init: Acc, mut fold: Fold) -> Acc where diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index c95324c80b..3d0401cbeb 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -88,6 +88,7 @@ where } #[inline] + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item where Self: TrustedRandomAccess, @@ -226,6 +227,8 @@ where fn next(&mut self) -> Option<(A::Item, B::Item)> { if self.index < self.len { let i = self.index; + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess self.index += 1; // SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()` unsafe { @@ -233,6 +236,7 @@ where } } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len { let i = self.index; + // as above, increment before executing code that may panic self.index += 1; self.len += 1; // match the base implementation's potential side effects @@ -258,6 +262,8 @@ where let end = self.index + delta; while self.index < end { let i = self.index; + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess self.index += 1; if A::MAY_HAVE_SIDE_EFFECT { // SAFETY: the usage of `cmp::min` to calculate `delta` @@ -294,9 +300,12 @@ where let sz_a = self.a.size(); if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len { for _ in 0..sz_a - self.len { + // since next_back() may panic we increment the counters beforehand + // to keep Zip's state in sync with the underlying iterator source + self.a_len -= 1; self.a.next_back(); } - self.a_len = self.len; + debug_assert_eq!(self.a_len, self.len); } let sz_b = self.b.size(); if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len { @@ -307,6 +316,8 @@ where } } if self.index < self.len { + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess self.len -= 1; self.a_len -= 1; let i = self.len; diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index de5d77e96e..b9387ef49e 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -30,7 +30,7 @@ pub trait Step: Clone + PartialOrd + Sized { /// For any `a`, `b`, and `n`: /// /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward_checked(&a, n) == Some(b)` - /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&a, n) == Some(a)` + /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&b, n) == Some(a)` /// * `steps_between(&a, &b) == Some(n)` only if `a <= b` /// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b` /// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`; @@ -667,6 +667,7 @@ impl Iterator for ops::Range { } #[inline] + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item where Self: TrustedRandomAccess, diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index a9478041c6..733142ed01 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -51,6 +51,7 @@ use crate::iter::{FusedIterator, TrustedLen}; /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "iter_repeat")] pub fn repeat(elt: T) -> Repeat { Repeat { element: elt } } diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 0a4210a78e..c2e837df5f 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -3,12 +3,11 @@ use crate::num::Wrapping; /// Trait to represent types that can be created by summing up an iterator. /// -/// This trait is used to implement the [`sum()`] method on iterators. Types which -/// implement the trait can be generated by the [`sum()`] method. Like -/// [`FromIterator`] this trait should rarely be called directly and instead -/// interacted with through [`Iterator::sum()`]. +/// This trait is used to implement [`Iterator::sum()`]. Types which implement +/// this trait can be generated by using the [`sum()`] method on an iterator. +/// Like [`FromIterator`], this trait should rarely be called directly. /// -/// [`sum()`]: Sum::sum +/// [`sum()`]: Iterator::sum /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Sum: Sized { @@ -21,12 +20,11 @@ pub trait Sum: Sized { /// Trait to represent types that can be created by multiplying elements of an /// iterator. /// -/// This trait is used to implement the [`product()`] method on iterators. Types -/// which implement the trait can be generated by the [`product()`] method. Like -/// [`FromIterator`] this trait should rarely be called directly and instead -/// interacted with through [`Iterator::product()`]. +/// This trait is used to implement [`Iterator::product()`]. Types which implement +/// this trait can be generated by using the [`product()`] method on an iterator. +/// Like [`FromIterator`], this trait should rarely be called directly. /// -/// [`product()`]: Product::product +/// [`product()`]: Iterator::product /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Product: Sized { diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index e2a407509b..7f87ead6fe 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -89,6 +89,7 @@ over elements of type `{A}`", label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" )] +#[rustc_diagnostic_item = "FromIterator"] pub trait FromIterator: Sized { /// Creates a value from an iterator. /// @@ -238,6 +239,7 @@ impl IntoIterator for I { type Item = I::Item; type IntoIter = I; + #[inline] fn into_iter(self) -> I { self } diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index c302502b3b..9a9cf20077 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -36,6 +36,7 @@ use crate::ops::{ControlFlow, Try}; /// assert_eq!(None, iter.next_back()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")] pub trait DoubleEndedIterator: Iterator { /// Removes and returns an element from the end of the iterator. /// @@ -248,6 +249,11 @@ pub trait DoubleEndedIterator: Iterator { /// Folding is useful whenever you have a collection of something, and want /// to produce a single value from it. /// + /// Note: `rfold()` combines elements in a *right-associative* fashion. For associative + /// operators like `+`, the order the elements are combined in is not important, but for non-associative + /// operators like `-` the order will affect the final result. + /// For a *left-associative* version of `rfold()`, see [`Iterator::fold()`]. + /// /// # Examples /// /// Basic usage: @@ -262,7 +268,8 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(sum, 6); /// ``` /// - /// This example builds a string, starting with an initial value + /// This example demonstrates the right-associative nature of `rfold()`: + /// it builds a string, starting with an initial value /// and continuing with each element from the back until the front: /// /// ``` @@ -276,6 +283,7 @@ pub trait DoubleEndedIterator: Iterator { /// /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))"); /// ``` + #[doc(alias = "foldr")] #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] fn rfold(mut self, init: B, mut f: F) -> B diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index 167db3359f..a476799b70 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -97,7 +97,6 @@ pub trait ExactSizeIterator: Iterator { /// /// assert_eq!(5, five.len()); /// ``` - #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn len(&self) -> usize { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 11dea400a4..16efd2f0ea 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -333,21 +333,22 @@ pub trait Iterator { /// regardless of the step given. /// /// Note 2: The time at which ignored elements are pulled is not fixed. - /// `StepBy` behaves like the sequence `next(), nth(step-1), nth(step-1), …`, - /// but is also free to behave like the sequence - /// `advance_n_and_return_first(step), advance_n_and_return_first(step), …` + /// `StepBy` behaves like the sequence `self.next()`, `self.nth(step-1)`, + /// `self.nth(step-1)`, …, but is also free to behave like the sequence + /// `advance_n_and_return_first(&mut self, step)`, + /// `advance_n_and_return_first(&mut self, step)`, … /// Which way is used may change for some iterators for performance reasons. /// The second way will advance the iterator earlier and may consume more items. /// /// `advance_n_and_return_first` is the equivalent of: /// ``` - /// fn advance_n_and_return_first(iter: &mut I, total_step: usize) -> Option + /// fn advance_n_and_return_first(iter: &mut I, n: usize) -> Option /// where /// I: Iterator, /// { /// let next = iter.next(); - /// if total_step > 1 { - /// iter.nth(total_step-2); + /// if n > 1 { + /// iter.nth(n - 2); /// } /// next /// } @@ -1959,6 +1960,31 @@ pub trait Iterator { /// assert_eq!(it.len(), 2); /// assert_eq!(it.next(), Some(&40)); /// ``` + /// + /// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`] + /// type allows a similar idea: + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// let triangular = (1..30).try_fold(0_i8, |prev, x| { + /// if let Some(next) = prev.checked_add(x) { + /// ControlFlow::Continue(next) + /// } else { + /// ControlFlow::Break(prev) + /// } + /// }); + /// assert_eq!(triangular, ControlFlow::Break(120)); + /// + /// let triangular = (1..30).try_fold(0_u64, |prev, x| { + /// if let Some(next) = prev.checked_add(x) { + /// ControlFlow::Continue(next) + /// } else { + /// ControlFlow::Break(prev) + /// } + /// }); + /// assert_eq!(triangular, ControlFlow::Continue(435)); + /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_fold(&mut self, init: B, mut f: F) -> R @@ -2001,6 +2027,22 @@ pub trait Iterator { /// // It short-circuited, so the remaining items are still in the iterator: /// assert_eq!(it.next(), Some("stale_bread.json")); /// ``` + /// + /// The [`crate::ops::ControlFlow`] type can be used with this method for the + /// situations in which you'd use `break` and `continue` in a normal loop: + /// + /// ``` + /// use std::ops::ControlFlow; + /// + /// let r = (2..100).try_for_each(|x| { + /// if 323 % x == 0 { + /// return ControlFlow::Break(x) + /// } + /// + /// ControlFlow::Continue(()) + /// }); + /// assert_eq!(r, ControlFlow::Break(17)); + /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_for_each(&mut self, f: F) -> R @@ -2042,6 +2084,11 @@ pub trait Iterator { /// Note: [`reduce()`] can be used to use the first element as the initial /// value, if the accumulator type and item type is the same. /// + /// Note: `fold()` combines elements in a *left-associative* fashion. For associative + /// operators like `+`, the order the elements are combined in is not important, but for non-associative + /// operators like `-` the order will affect the final result. + /// For a *right-associative* version of `fold()`, see [`DoubleEndedIterator::rfold()`]. + /// /// # Note to Implementors /// /// Several of the other (forward) methods have default implementations in @@ -2075,6 +2122,21 @@ pub trait Iterator { /// /// And so, our final result, `6`. /// + /// This example demonstrates the left-associative nature of `fold()`: + /// it builds a string, starting with an initial value + /// and continuing with each element from the front until the back: + /// + /// ``` + /// let numbers = [1, 2, 3, 4, 5]; + /// + /// let zero = "0".to_string(); + /// + /// let result = numbers.iter().fold(zero, |acc, &x| { + /// format!("({} + {})", acc, x) + /// }); + /// + /// assert_eq!(result, "(((((0 + 1) + 2) + 3) + 4) + 5)"); + /// ``` /// It's common for people who haven't used iterators a lot to /// use a `for` loop with a list of things to build up a result. Those /// can be turned into `fold()`s: @@ -2099,7 +2161,7 @@ pub trait Iterator { /// ``` /// /// [`reduce()`]: Iterator::reduce - #[doc(alias = "inject")] + #[doc(alias = "inject", alias = "foldl")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn fold(mut self, init: B, mut f: F) -> B @@ -2193,7 +2255,6 @@ pub trait Iterator { /// // we can still use `iter`, as there are more elements. /// assert_eq!(iter.next(), Some(&3)); /// ``` - #[doc(alias = "every")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn all(&mut self, f: F) -> bool @@ -2378,7 +2439,6 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] - #[cfg(not(bootstrap))] fn try_find(&mut self, f: F) -> Result, E> where Self: Sized, @@ -2405,32 +2465,6 @@ pub trait Iterator { self.try_fold((), check(f)).break_value().transpose() } - /// We're bootstrapping. - #[inline] - #[unstable(feature = "try_find", reason = "new API", issue = "63178")] - #[cfg(bootstrap)] - fn try_find(&mut self, f: F) -> Result, R::Error> - where - Self: Sized, - F: FnMut(&Self::Item) -> R, - R: Try, - { - #[inline] - fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> - where - F: FnMut(&T) -> R, - R: Try, - { - move |(), x| match f(&x).into_result() { - Ok(false) => ControlFlow::CONTINUE, - Ok(true) => ControlFlow::Break(Ok(x)), - Err(x) => ControlFlow::Break(Err(x)), - } - } - - self.try_fold((), check(f)).break_value().transpose() - } - /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0bb0f8768a..6d87a7ab05 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -49,6 +49,10 @@ // // This cfg won't affect doc tests. #![cfg(not(test))] +// To run libcore tests without x.py without ending up with two copies of libcore, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] #![stable(feature = "core", since = "1.6.0")] #![doc( html_playground_url = "https://play.rust-lang.org/", @@ -87,7 +91,6 @@ #![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] #![feature(const_fn_trait_bound)] -#![cfg_attr(bootstrap, feature(const_fn))] #![feature(const_option)] #![feature(const_precise_live_drops)] #![feature(const_ptr_offset)] @@ -112,7 +115,6 @@ #![feature(doc_cfg)] #![feature(doc_notable_trait)] #![feature(duration_consts_2)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(extern_types)] #![feature(fundamental)] #![feature(intra_doc_pointers)] @@ -165,10 +167,9 @@ #![feature(slice_ptr_get)] #![feature(no_niche)] // rust-lang/rust#68303 #![feature(no_coverage)] // rust-lang/rust#84605 -#![feature(int_error_matching)] -#![cfg_attr(bootstrap, feature(target_feature_11))] #![deny(unsafe_op_in_unsafe_fn)] -#![deny(or_patterns_back_compat)] +#![cfg_attr(bootstrap, deny(or_patterns_back_compat))] +#![cfg_attr(not(bootstrap), deny(rust_2021_incompatible_or_patterns))] // allow using `core::` in intra-doc links #[allow(unused_extern_crates)] @@ -269,7 +270,6 @@ pub mod option; pub mod panic; pub mod panicking; pub mod pin; -pub mod raw; pub mod result; #[unstable(feature = "async_stream", issue = "79024")] pub mod stream; @@ -320,5 +320,35 @@ pub mod primitive; #[unstable(feature = "stdsimd", issue = "48556")] mod core_arch; +#[doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")] #[stable(feature = "simd_arch", since = "1.27.0")] -pub use core_arch::arch; +pub mod arch { + #[stable(feature = "simd_arch", since = "1.27.0")] + pub use crate::core_arch::arch::*; + + /// Inline assembly. + /// + /// Read the [unstable book] for the usage. + /// + /// [unstable book]: ../../unstable-book/library-features/asm.html + #[unstable( + feature = "asm", + issue = "72016", + reason = "inline assembly is not stable enough for use and is subject to change" + )] + #[rustc_builtin_macro] + pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ + } + + /// Module-level inline assembly. + #[unstable( + feature = "global_asm", + issue = "35119", + reason = "`global_asm!` is not stable enough for use and is subject to change" + )] + #[rustc_builtin_macro] + pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ + } +} diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 1a3c088e92..3ca8f27c79 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1,6 +1,7 @@ #[doc = include_str!("panic.md")] #[macro_export] -#[rustc_builtin_macro = "core_panic"] +#[cfg_attr(bootstrap, rustc_builtin_macro = "core_panic")] +#[cfg_attr(not(bootstrap), rustc_builtin_macro(core_panic))] #[allow_internal_unstable(edition_panic)] #[stable(feature = "core", since = "1.6.0")] #[rustc_diagnostic_item = "core_panic_macro"] @@ -1311,27 +1312,6 @@ pub(crate) mod builtin { ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }}; } - /// Inline assembly. - /// - /// Read the [unstable book] for the usage. - /// - /// [unstable book]: ../unstable-book/library-features/asm.html - #[unstable( - feature = "asm", - issue = "72016", - reason = "inline assembly is not stable enough for use and is subject to change" - )] - #[rustc_builtin_macro] - #[macro_export] - macro_rules! asm { - ("assembly template", - $(operands,)* - $(options($(option),*))? - ) => { - /* compiler built-in */ - }; - } - /// LLVM-style inline assembly. /// /// Read the [unstable book] for the usage. @@ -1354,23 +1334,6 @@ pub(crate) mod builtin { }; } - /// Module-level inline assembly. - #[unstable( - feature = "global_asm", - issue = "35119", - reason = "`global_asm!` is not stable enough for use and is subject to change" - )] - #[rustc_builtin_macro] - #[macro_export] - macro_rules! global_asm { - ("assembly template", - $(operands,)* - $(options($(option),*))? - ) => { - /* compiler built-in */ - }; - } - /// Prints passed tokens into the standard output. #[unstable( feature = "log_syntax", diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 2b24045504..fb957348be 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -31,7 +31,6 @@ use crate::hash::Hasher; /// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")] -#[cfg_attr(not(bootstrap), lang = "send")] #[rustc_on_unimplemented( message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely" diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 10219201a4..5122421ea8 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -79,7 +79,7 @@ use crate::ptr; /// // a `MaybeUninit` may be invalid, and hence this is not UB: /// let mut x = MaybeUninit::<&i32>::uninit(); /// // Set it to a valid value. -/// unsafe { x.as_mut_ptr().write(&0); } +/// x.write(&0); /// // Extract the initialized data -- this is only allowed *after* properly /// // initializing `x`! /// let x = unsafe { x.assume_init() }; @@ -135,7 +135,7 @@ use crate::ptr; /// // this loop, we have a memory leak, but there is no memory safety /// // issue. /// for elem in &mut data[..] { -/// *elem = MaybeUninit::new(vec![42]); +/// elem.write(vec![42]); /// } /// /// // Everything is initialized. Transmute the array to the @@ -161,7 +161,7 @@ use crate::ptr; /// let mut data_len: usize = 0; /// /// for elem in &mut data[0..500] { -/// *elem = MaybeUninit::new(String::from("hello")); +/// elem.write(String::from("hello")); /// data_len += 1; /// } /// @@ -402,12 +402,90 @@ impl MaybeUninit { u } - /// Sets the value of the `MaybeUninit`. This overwrites any previous value - /// without dropping it, so be careful not to use this twice unless you want to - /// skip running the destructor. For your convenience, this also returns a mutable - /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit_extra", issue = "63567")] - #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")] + /// Sets the value of the `MaybeUninit`. + /// + /// This overwrites any previous value without dropping it, so be careful + /// not to use this twice unless you want to skip running the destructor. + /// For your convenience, this also returns a mutable reference to the + /// (now safely initialized) contents of `self`. + /// + /// As the content is stored inside a `MaybeUninit`, the destructor is not + /// run for the inner data if the MaybeUninit leaves scope without a call to + /// [`assume_init`], [`assume_init_drop`], or similar. Code that receives + /// the mutable reference returned by this function needs to keep this in + /// mind. The safety model of Rust regards leaks as safe, but they are + /// usually still undesirable. This being said, the mutable reference + /// behaves like any other mutable reference would, so assigning a new value + /// to it will drop the old content. + /// + /// [`assume_init`]: Self::assume_init + /// [`assume_init_drop`]: Self::assume_init_drop + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// + /// { + /// let hello = x.write((&b"Hello, world!").to_vec()); + /// // Setting hello does not leak prior allocations, but drops them + /// *hello = (&b"Hello").to_vec(); + /// hello[0] = 'h' as u8; + /// } + /// // x is initialized now: + /// let s = unsafe { x.assume_init() }; + /// assert_eq!(b"hello", s.as_slice()); + /// ``` + /// + /// This usage of the method causes a leak: + /// + /// ```rust + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// + /// x.write("Hello".to_string()); + /// // This leaks the contained string: + /// x.write("hello".to_string()); + /// // x is initialized now: + /// let s = unsafe { x.assume_init() }; + /// ``` + /// + /// This method can be used to avoid unsafe in some cases. The example below + /// shows a part of an implementation of a fixed sized arena that lends out + /// pinned references. + /// With `write`, we can avoid the need to write through a raw pointer: + /// + /// ```rust + /// #![feature(maybe_uninit_extra)] + /// use core::pin::Pin; + /// use core::mem::MaybeUninit; + /// + /// struct PinArena { + /// memory: Box<[MaybeUninit]>, + /// len: usize, + /// } + /// + /// impl PinArena { + /// pub fn capacity(&self) -> usize { + /// self.memory.len() + /// } + /// pub fn push(&mut self, val: T) -> Pin<&mut T> { + /// if self.len >= self.capacity() { + /// panic!("Attempted to push to a full pin arena!"); + /// } + /// let ref_ = self.memory[self.len].write(val); + /// self.len += 1; + /// unsafe { Pin::new_unchecked(ref_) } + /// } + /// } + /// ``` + #[stable(feature = "maybe_uninit_write", since = "1.55.0")] + #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")] #[inline(always)] pub const fn write(&mut self, val: T) -> &mut T { *self = MaybeUninit::new(val); @@ -428,7 +506,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); } + /// x.write(vec![0, 1, 2]); /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. /// let x_vec = unsafe { &*x.as_ptr() }; /// assert_eq!(x_vec.len(), 3); @@ -465,7 +543,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); } + /// x.write(vec![0, 1, 2]); /// // Create a reference into the `MaybeUninit>`. /// // This is okay because we initialized it. /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; @@ -524,7 +602,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::::uninit(); - /// unsafe { x.as_mut_ptr().write(true); } + /// x.write(true); /// let x_init = unsafe { x.assume_init() }; /// assert_eq!(x_init, true); /// ``` @@ -564,9 +642,11 @@ impl MaybeUninit { /// behavior. The [type-level documentation][inv] contains more information about /// this initialization invariant. /// - /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit`. 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 + /// Moreover, similar to the [`ptr::read`] function, this function creates a + /// bitwise copy of the contents, regardless whether the contained type + /// 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. /// /// [inv]: #initialization-invariant @@ -622,7 +702,8 @@ impl MaybeUninit { /// Drops the contained value in place. /// - /// If you have ownership of the `MaybeUninit`, you can use [`assume_init`] instead. + /// If you have ownership of the `MaybeUninit`, you can also use + /// [`assume_init`] as an alternative. /// /// # Safety /// @@ -632,11 +713,12 @@ impl MaybeUninit { /// /// On top of that, all additional invariants of the type `T` must be /// satisfied, as the `Drop` implementation of `T` (or its members) may - /// rely on this. For example, a `1`-initialized [`Vec`] is considered - /// initialized (under the current implementation; this does not constitute - /// a stable guarantee) because the only requirement the compiler knows - /// about it is that the data pointer must be non-null. Dropping such a - /// `Vec` however will cause undefined behaviour. + /// rely on this. For example, setting a [`Vec`] to an invalid but + /// non-null address makes it initialized (under the current implementation; + /// this does not constitute a stable guarantee), because the only + /// requirement the compiler knows about it is that the data pointer must be + /// non-null. Dropping such a `Vec` however will cause undefined + /// behaviour. /// /// [`assume_init`]: MaybeUninit::assume_init /// [`Vec`]: ../../std/vec/struct.Vec.html @@ -665,12 +747,11 @@ impl MaybeUninit { /// ### Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit_ref)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); /// // Initialize `x`: - /// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); } + /// x.write(vec![1, 2, 3]); /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to /// // create a shared reference to it: /// let x: &Vec = unsafe { @@ -683,7 +764,6 @@ impl MaybeUninit { /// ### *Incorrect* usages of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::>::uninit(); @@ -692,7 +772,6 @@ impl MaybeUninit { /// ``` /// /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] /// use std::{cell::Cell, mem::MaybeUninit}; /// /// let b = MaybeUninit::>::uninit(); @@ -703,7 +782,7 @@ impl MaybeUninit { /// // Reference to an uninitialized `Cell`: UB! /// } /// ``` - #[unstable(feature = "maybe_uninit_ref", issue = "63568")] + #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] #[inline(always)] pub const unsafe fn assume_init_ref(&self) -> &T { @@ -733,7 +812,6 @@ impl MaybeUninit { /// ### Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit_ref)] /// use std::mem::MaybeUninit; /// /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] } @@ -769,7 +847,6 @@ impl MaybeUninit { /// You cannot use `.assume_init_mut()` to initialize a value: /// /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] /// use std::mem::MaybeUninit; /// /// let mut b = MaybeUninit::::uninit(); @@ -785,7 +862,6 @@ impl MaybeUninit { /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] /// use std::{io, mem::MaybeUninit}; /// /// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]> @@ -802,7 +878,6 @@ impl MaybeUninit { /// Nor can you use direct field access to do field-by-field gradual initialization: /// /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] /// use std::{mem::MaybeUninit, ptr}; /// /// struct Foo { @@ -823,10 +898,7 @@ impl MaybeUninit { /// foo.assume_init() /// }; /// ``` - // FIXME(#76092): We currently rely on the above being incorrect, i.e., we have references - // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make - // a final decision about the rules before stabilization. - #[unstable(feature = "maybe_uninit_ref", issue = "63568")] + #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] #[inline(always)] pub const unsafe fn assume_init_mut(&mut self) -> &mut T { @@ -853,9 +925,9 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut array: [MaybeUninit; 3] = MaybeUninit::uninit_array(); - /// array[0] = MaybeUninit::new(0); - /// array[1] = MaybeUninit::new(1); - /// array[2] = MaybeUninit::new(2); + /// array[0].write(0); + /// array[1].write(1); + /// array[2].write(2); /// /// // SAFETY: Now safe as we initialised all elements /// let array = unsafe { @@ -936,7 +1008,7 @@ impl MaybeUninit { this.as_mut_ptr() as *mut T } - /// Copies the elements from `src` to `this`, returning a mutable reference to the now initalized contents of `this`. + /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. /// /// If `T` does not implement `Copy`, use [`write_slice_cloned`] /// @@ -989,12 +1061,12 @@ impl MaybeUninit { this.copy_from_slice(uninit_src); - // SAFETY: Valid elements have just been copied into `this` so it is initalized + // SAFETY: Valid elements have just been copied into `this` so it is initialized unsafe { MaybeUninit::slice_assume_init_mut(this) } } - /// Clones the elements from `src` to `this`, returning a mutable reference to the now initalized contents of `this`. - /// Any already initalized elements will not be dropped. + /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`. + /// Any already initialized elements will not be dropped. /// /// If `T` implements `Copy`, use [`write_slice`] /// @@ -1080,7 +1152,7 @@ impl MaybeUninit { super::forget(guard); - // SAFETY: Valid elements have just been written into `this` so it is initalized + // SAFETY: Valid elements have just been written into `this` so it is initialized unsafe { MaybeUninit::slice_assume_init_mut(this) } } } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index c6750c52d1..2c75de39ff 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -140,6 +140,7 @@ pub use crate::intrinsics::transmute; #[inline] #[rustc_const_stable(feature = "const_forget", since = "1.46.0")] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_forget")] pub const fn forget(t: T) { let _ = ManuallyDrop::new(t); } @@ -298,6 +299,7 @@ pub fn forget_unsized(t: T) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_size_of", since = "1.24.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of")] pub const fn size_of() -> usize { intrinsics::size_of::() } @@ -324,6 +326,7 @@ pub const fn size_of() -> usize { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] pub const fn size_of_val(val: &T) -> usize { // SAFETY: `val` is a reference, so it's a valid raw pointer unsafe { intrinsics::size_of_val(val) } @@ -682,7 +685,8 @@ pub unsafe fn uninitialized() -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub fn swap(x: &mut T, y: &mut T) { +#[rustc_const_unstable(feature = "const_swap", issue = "83163")] +pub const fn swap(x: &mut T, y: &mut T) { // SAFETY: the raw pointers have been created from safe mutable references satisfying all the // constraints on `ptr::swap_nonoverlapping_one` unsafe { @@ -812,7 +816,9 @@ pub fn take(dest: &mut T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] -pub fn replace(dest: &mut T, src: T) -> T { +#[rustc_const_unstable(feature = "const_replace", issue = "83164")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] +pub const fn replace(dest: &mut T, src: T) -> T { // SAFETY: We read from `dest` but directly write `src` into it afterwards, // such that the old value is not duplicated. Nothing is dropped and // nothing here can panic. @@ -886,6 +892,7 @@ pub fn replace(dest: &mut T, src: T) -> T { /// [`RefCell`]: crate::cell::RefCell #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_drop")] pub fn drop(_x: T) {} /// Interprets `src` as having type `&U`, and then reads `src` without moving @@ -1013,6 +1020,7 @@ impl fmt::Debug for Discriminant { /// ``` #[stable(feature = "discriminant_value", since = "1.21.0")] #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] +#[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")] pub const fn discriminant(v: &T) -> Discriminant { Discriminant(intrinsics::discriminant_value(v)) } diff --git a/library/core/src/num/dec2flt/algorithm.rs b/library/core/src/num/dec2flt/algorithm.rs deleted file mode 100644 index 313b6870ac..0000000000 --- a/library/core/src/num/dec2flt/algorithm.rs +++ /dev/null @@ -1,429 +0,0 @@ -//! The various algorithms from the paper. - -use crate::cmp::min; -use crate::cmp::Ordering::{Equal, Greater, Less}; -use crate::num::dec2flt::num::{self, Big}; -use crate::num::dec2flt::rawfp::{self, fp_to_float, next_float, prev_float, RawFloat, Unpacked}; -use crate::num::dec2flt::table; -use crate::num::diy_float::Fp; - -/// Number of significand bits in Fp -const P: u32 = 64; - -// We simply store the best approximation for *all* exponents, so the variable "h" and the -// associated conditions can be omitted. This trades performance for a couple kilobytes of space. - -fn power_of_ten(e: i16) -> Fp { - assert!(e >= table::MIN_E); - let i = e - table::MIN_E; - let sig = table::POWERS.0[i as usize]; - let exp = table::POWERS.1[i as usize]; - Fp { f: sig, e: exp } -} - -// In most architectures, floating point operations have an explicit bit size, therefore the -// precision of the computation is determined on a per-operation basis. -#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] -mod fpu_precision { - pub fn set_precision() {} -} - -// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available. -// The x87 FPU operates with 80 bits of precision by default, which means that operations will -// round to 80 bits causing double rounding to happen when values are eventually represented as -// 32/64 bit float values. To overcome this, the FPU control word can be set so that the -// computations are performed in the desired precision. -#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] -mod fpu_precision { - use crate::mem::size_of; - - /// A structure used to preserve the original value of the FPU control word, so that it can be - /// restored when the structure is dropped. - /// - /// The x87 FPU is a 16-bits register whose fields are as follows: - /// - /// | 12-15 | 10-11 | 8-9 | 6-7 | 5 | 4 | 3 | 2 | 1 | 0 | - /// |------:|------:|----:|----:|---:|---:|---:|---:|---:|---:| - /// | | RC | PC | | PM | UM | OM | ZM | DM | IM | - /// - /// The documentation for all of the fields is available in the IA-32 Architectures Software - /// Developer's Manual (Volume 1). - /// - /// The only field which is relevant for the following code is PC, Precision Control. This - /// field determines the precision of the operations performed by the FPU. It can be set to: - /// - 0b00, single precision i.e., 32-bits - /// - 0b10, double precision i.e., 64-bits - /// - 0b11, double extended precision i.e., 80-bits (default state) - /// The 0b01 value is reserved and should not be used. - pub struct FPUControlWord(u16); - - fn set_cw(cw: u16) { - // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with - // any `u16` - unsafe { - asm!( - "fldcw word ptr [{}]", - in(reg) &cw, - options(nostack), - ) - } - } - - /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`. - pub fn set_precision() -> FPUControlWord { - let mut cw = 0_u16; - - // Compute the value for the Precision Control field that is appropriate for `T`. - let cw_precision = match size_of::() { - 4 => 0x0000, // 32 bits - 8 => 0x0200, // 64 bits - _ => 0x0300, // default, 80 bits - }; - - // Get the original value of the control word to restore it later, when the - // `FPUControlWord` structure is dropped - // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with - // any `u16` - unsafe { - asm!( - "fnstcw word ptr [{}]", - in(reg) &mut cw, - options(nostack), - ) - } - - // Set the control word to the desired precision. This is achieved by masking away the old - // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above. - set_cw((cw & 0xFCFF) | cw_precision); - - FPUControlWord(cw) - } - - impl Drop for FPUControlWord { - fn drop(&mut self) { - set_cw(self.0) - } - } -} - -/// The fast path of Bellerophon using machine-sized integers and floats. -/// -/// This is extracted into a separate function so that it can be attempted before constructing -/// a bignum. -pub fn fast_path(integral: &[u8], fractional: &[u8], e: i64) -> Option { - let num_digits = integral.len() + fractional.len(); - // log_10(f64::MAX_SIG) ~ 15.95. We compare the exact value to MAX_SIG near the end, - // this is just a quick, cheap rejection (and also frees the rest of the code from - // worrying about underflow). - if num_digits > 16 { - return None; - } - if e.abs() >= T::CEIL_LOG5_OF_MAX_SIG as i64 { - return None; - } - let f = num::from_str_unchecked(integral.iter().chain(fractional.iter())); - if f > T::MAX_SIG { - return None; - } - - // The fast path crucially depends on arithmetic being rounded to the correct number of bits - // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision - // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit. - // The `set_precision` function takes care of setting the precision on architectures which - // require setting it by changing the global state (like the control word of the x87 FPU). - let _cw = fpu_precision::set_precision::(); - - // The case e < 0 cannot be folded into the other branch. Negative powers result in - // a repeating fractional part in binary, which are rounded, which causes real - // (and occasionally quite significant!) errors in the final result. - if e >= 0 { - Some(T::from_int(f) * T::short_fast_pow10(e as usize)) - } else { - Some(T::from_int(f) / T::short_fast_pow10(e.abs() as usize)) - } -} - -/// Algorithm Bellerophon is trivial code justified by non-trivial numeric analysis. -/// -/// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation -/// of `10^e` (in the same floating point format). This is often enough to get the correct result. -/// However, when the result is close to halfway between two adjacent (ordinary) floats, the -/// compound rounding error from multiplying two approximation means the result may be off by a -/// few bits. When this happens, the iterative Algorithm R fixes things up. -/// -/// The hand-wavy "close to halfway" is made precise by the numeric analysis in the paper. -/// In the words of Clinger: -/// -/// > Slop, expressed in units of the least significant bit, is an inclusive bound for the error -/// > accumulated during the floating point calculation of the approximation to f * 10^e. (Slop is -/// > not a bound for the true error, but bounds the difference between the approximation z and -/// > the best possible approximation that uses p bits of significand.) -pub fn bellerophon(f: &Big, e: i16) -> T { - let slop = if f <= &Big::from_u64(T::MAX_SIG) { - // The cases abs(e) < log5(2^N) are in fast_path() - if e >= 0 { 0 } else { 3 } - } else { - if e >= 0 { 1 } else { 4 } - }; - let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize(); - let exp_p_n = 1 << (P - T::SIG_BITS as u32); - let lowbits: i64 = (z.f % exp_p_n) as i64; - // Is the slop large enough to make a difference when - // rounding to n bits? - if (lowbits - exp_p_n as i64 / 2).abs() <= slop { - algorithm_r(f, e, fp_to_float(z)) - } else { - fp_to_float(z) - } -} - -/// An iterative algorithm that improves a floating point approximation of `f * 10^e`. -/// -/// Each iteration gets one unit in the last place closer, which of course takes terribly long to -/// converge if `z0` is even mildly off. Luckily, when used as fallback for Bellerophon, the -/// starting approximation is off by at most one ULP. -fn algorithm_r(f: &Big, e: i16, z0: T) -> T { - let mut z = z0; - loop { - let raw = z.unpack(); - let (m, k) = (raw.sig, raw.k); - let mut x = f.clone(); - let mut y = Big::from_u64(m); - - // Find positive integers `x`, `y` such that `x / y` is exactly `(f * 10^e) / (m * 2^k)`. - // This not only avoids dealing with the signs of `e` and `k`, we also eliminate the - // power of two common to `10^e` and `2^k` to make the numbers smaller. - make_ratio(&mut x, &mut y, e, k); - - let m_digits = [(m & 0xFF_FF_FF_FF) as u32, (m >> 32) as u32]; - // This is written a bit awkwardly because our bignums don't support - // negative numbers, so we use the absolute value + sign information. - // The multiplication with m_digits can't overflow. If `x` or `y` are large enough that - // we need to worry about overflow, then they are also large enough that `make_ratio` has - // reduced the fraction by a factor of 2^64 or more. - let (d2, d_negative) = if x >= y { - // Don't need x any more, save a clone(). - x.sub(&y).mul_pow2(1).mul_digits(&m_digits); - (x, false) - } else { - // Still need y - make a copy. - let mut y = y.clone(); - y.sub(&x).mul_pow2(1).mul_digits(&m_digits); - (y, true) - }; - - if d2 < y { - let mut d2_double = d2; - d2_double.mul_pow2(1); - if m == T::MIN_SIG && d_negative && d2_double > y { - z = prev_float(z); - } else { - return z; - } - } else if d2 == y { - if m % 2 == 0 { - if m == T::MIN_SIG && d_negative { - z = prev_float(z); - } else { - return z; - } - } else if d_negative { - z = prev_float(z); - } else { - z = next_float(z); - } - } else if d_negative { - z = prev_float(z); - } else { - z = next_float(z); - } - } -} - -/// Given `x = f` and `y = m` where `f` represent input decimal digits as usual and `m` is the -/// significand of a floating point approximation, make the ratio `x / y` equal to -/// `(f * 10^e) / (m * 2^k)`, possibly reduced by a power of two both have in common. -fn make_ratio(x: &mut Big, y: &mut Big, e: i16, k: i16) { - let (e_abs, k_abs) = (e.abs() as usize, k.abs() as usize); - if e >= 0 { - if k >= 0 { - // x = f * 10^e, y = m * 2^k, except that we reduce the fraction by some power of two. - let common = min(e_abs, k_abs); - x.mul_pow5(e_abs).mul_pow2(e_abs - common); - y.mul_pow2(k_abs - common); - } else { - // x = f * 10^e * 2^abs(k), y = m - // This can't overflow because it requires positive `e` and negative `k`, which can - // only happen for values extremely close to 1, which means that `e` and `k` will be - // comparatively tiny. - x.mul_pow5(e_abs).mul_pow2(e_abs + k_abs); - } - } else { - if k >= 0 { - // x = f, y = m * 10^abs(e) * 2^k - // This can't overflow either, see above. - y.mul_pow5(e_abs).mul_pow2(k_abs + e_abs); - } else { - // x = f * 2^abs(k), y = m * 10^abs(e), again reducing by a common power of two. - let common = min(e_abs, k_abs); - x.mul_pow2(k_abs - common); - y.mul_pow5(e_abs).mul_pow2(e_abs - common); - } - } -} - -/// Conceptually, Algorithm M is the simplest way to convert a decimal to a float. -/// -/// We form a ratio that is equal to `f * 10^e`, then throwing in powers of two until it gives -/// a valid float significand. The binary exponent `k` is the number of times we multiplied -/// numerator or denominator by two, i.e., at all times `f * 10^e` equals `(u / v) * 2^k`. -/// When we have found out significand, we only need to round by inspecting the remainder of the -/// division, which is done in helper functions further below. -/// -/// This algorithm is super slow, even with the optimization described in `quick_start()`. -/// However, it's the simplest of the algorithms to adapt for overflow, underflow, and subnormal -/// results. This implementation takes over when Bellerophon and Algorithm R are overwhelmed. -/// Detecting underflow and overflow is easy: The ratio still isn't an in-range significand, -/// yet the minimum/maximum exponent has been reached. In the case of overflow, we simply return -/// infinity. -/// -/// Handling underflow and subnormals is trickier. One big problem is that, with the minimum -/// exponent, the ratio might still be too large for a significand. See underflow() for details. -pub fn algorithm_m(f: &Big, e: i16) -> T { - let mut u; - let mut v; - let e_abs = e.abs() as usize; - let mut k = 0; - if e < 0 { - u = f.clone(); - v = Big::from_small(1); - v.mul_pow5(e_abs).mul_pow2(e_abs); - } else { - // FIXME possible optimization: generalize big_to_fp so that we can do the equivalent of - // fp_to_float(big_to_fp(u)) here, only without the double rounding. - u = f.clone(); - u.mul_pow5(e_abs).mul_pow2(e_abs); - v = Big::from_small(1); - } - quick_start::(&mut u, &mut v, &mut k); - let mut rem = Big::from_small(0); - let mut x = Big::from_small(0); - let min_sig = Big::from_u64(T::MIN_SIG); - let max_sig = Big::from_u64(T::MAX_SIG); - loop { - u.div_rem(&v, &mut x, &mut rem); - if k == T::MIN_EXP_INT { - // We have to stop at the minimum exponent, if we wait until `k < T::MIN_EXP_INT`, - // then we'd be off by a factor of two. Unfortunately this means we have to special- - // case normal numbers with the minimum exponent. - // FIXME find a more elegant formulation, but run the `tiny-pow10` test to make sure - // that it's actually correct! - if x >= min_sig && x <= max_sig { - break; - } - return underflow(x, v, rem); - } - if k > T::MAX_EXP_INT { - return T::INFINITY; - } - if x < min_sig { - u.mul_pow2(1); - k -= 1; - } else if x > max_sig { - v.mul_pow2(1); - k += 1; - } else { - break; - } - } - let q = num::to_u64(&x); - let z = rawfp::encode_normal(Unpacked::new(q, k)); - round_by_remainder(v, rem, q, z) -} - -/// Skips over most Algorithm M iterations by checking the bit length. -fn quick_start(u: &mut Big, v: &mut Big, k: &mut i16) { - // The bit length is an estimate of the base two logarithm, and log(u / v) = log(u) - log(v). - // The estimate is off by at most 1, but always an under-estimate, so the error on log(u) - // and log(v) are of the same sign and cancel out (if both are large). Therefore the error - // for log(u / v) is at most one as well. - // The target ratio is one where u/v is in an in-range significand. Thus our termination - // condition is log2(u / v) being the significand bits, plus/minus one. - // FIXME Looking at the second bit could improve the estimate and avoid some more divisions. - let target_ratio = T::SIG_BITS as i16; - let log2_u = u.bit_length() as i16; - let log2_v = v.bit_length() as i16; - let mut u_shift: i16 = 0; - let mut v_shift: i16 = 0; - assert!(*k == 0); - loop { - if *k == T::MIN_EXP_INT { - // Underflow or subnormal. Leave it to the main function. - break; - } - if *k == T::MAX_EXP_INT { - // Overflow. Leave it to the main function. - break; - } - let log2_ratio = (log2_u + u_shift) - (log2_v + v_shift); - if log2_ratio < target_ratio - 1 { - u_shift += 1; - *k -= 1; - } else if log2_ratio > target_ratio + 1 { - v_shift += 1; - *k += 1; - } else { - break; - } - } - u.mul_pow2(u_shift as usize); - v.mul_pow2(v_shift as usize); -} - -fn underflow(x: Big, v: Big, rem: Big) -> T { - if x < Big::from_u64(T::MIN_SIG) { - let q = num::to_u64(&x); - let z = rawfp::encode_subnormal(q); - return round_by_remainder(v, rem, q, z); - } - // Ratio isn't an in-range significand with the minimum exponent, so we need to round off - // excess bits and adjust the exponent accordingly. The real value now looks like this: - // - // x lsb - // /--------------\/ - // 1010101010101010.10101010101010 * 2^k - // \-----/\-------/ \------------/ - // q trunc. (represented by rem) - // - // Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding - // on their own. When they are equal and the remainder is non-zero, the value still - // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder - // is zero, we have a half-to-even situation. - let bits = x.bit_length(); - let lsb = bits - T::SIG_BITS as usize; - let q = num::get_bits(&x, lsb, bits); - let k = T::MIN_EXP_INT + lsb as i16; - let z = rawfp::encode_normal(Unpacked::new(q, k)); - let q_even = q % 2 == 0; - match num::compare_with_half_ulp(&x, lsb) { - Greater => next_float(z), - Less => z, - Equal if rem.is_zero() && q_even => z, - Equal => next_float(z), - } -} - -/// Ordinary round-to-even, obfuscated by having to round based on the remainder of a division. -fn round_by_remainder(v: Big, r: Big, q: u64, z: T) -> T { - let mut v_minus_r = v; - v_minus_r.sub(&r); - if r < v_minus_r { - z - } else if r > v_minus_r { - next_float(z) - } else if q % 2 == 0 { - z - } else { - next_float(z) - } -} diff --git a/library/core/src/num/dec2flt/common.rs b/library/core/src/num/dec2flt/common.rs new file mode 100644 index 0000000000..247123737d --- /dev/null +++ b/library/core/src/num/dec2flt/common.rs @@ -0,0 +1,198 @@ +//! Common utilities, for internal use only. + +use crate::ptr; + +/// Helper methods to process immutable bytes. +pub(crate) trait ByteSlice: AsRef<[u8]> { + unsafe fn first_unchecked(&self) -> u8 { + debug_assert!(!self.is_empty()); + // SAFETY: safe as long as self is not empty + unsafe { *self.as_ref().get_unchecked(0) } + } + + /// Get if the slice contains no elements. + fn is_empty(&self) -> bool { + self.as_ref().is_empty() + } + + /// Check if the slice at least `n` length. + fn check_len(&self, n: usize) -> bool { + n <= self.as_ref().len() + } + + /// Check if the first character in the slice is equal to c. + fn first_is(&self, c: u8) -> bool { + self.as_ref().first() == Some(&c) + } + + /// Check if the first character in the slice is equal to c1 or c2. + fn first_is2(&self, c1: u8, c2: u8) -> bool { + if let Some(&c) = self.as_ref().first() { c == c1 || c == c2 } else { false } + } + + /// Bounds-checked test if the first character in the slice is a digit. + fn first_isdigit(&self) -> bool { + if let Some(&c) = self.as_ref().first() { c.is_ascii_digit() } else { false } + } + + /// Check if self starts with u with a case-insensitive comparison. + fn eq_ignore_case(&self, u: &[u8]) -> bool { + debug_assert!(self.as_ref().len() >= u.len()); + let iter = self.as_ref().iter().zip(u.iter()); + let d = iter.fold(0, |i, (&x, &y)| i | (x ^ y)); + d == 0 || d == 32 + } + + /// Get the remaining slice after the first N elements. + fn advance(&self, n: usize) -> &[u8] { + &self.as_ref()[n..] + } + + /// Get the slice after skipping all leading characters equal c. + fn skip_chars(&self, c: u8) -> &[u8] { + let mut s = self.as_ref(); + while s.first_is(c) { + s = s.advance(1); + } + s + } + + /// Get the slice after skipping all leading characters equal c1 or c2. + fn skip_chars2(&self, c1: u8, c2: u8) -> &[u8] { + let mut s = self.as_ref(); + while s.first_is2(c1, c2) { + s = s.advance(1); + } + s + } + + /// Read 8 bytes as a 64-bit integer in little-endian order. + unsafe fn read_u64_unchecked(&self) -> u64 { + debug_assert!(self.check_len(8)); + let src = self.as_ref().as_ptr() as *const u64; + // SAFETY: safe as long as self is at least 8 bytes + u64::from_le(unsafe { ptr::read_unaligned(src) }) + } + + /// Try to read the next 8 bytes from the slice. + fn read_u64(&self) -> Option { + if self.check_len(8) { + // SAFETY: self must be at least 8 bytes. + Some(unsafe { self.read_u64_unchecked() }) + } else { + None + } + } + + /// Calculate the offset of slice from another. + fn offset_from(&self, other: &Self) -> isize { + other.as_ref().len() as isize - self.as_ref().len() as isize + } +} + +impl ByteSlice for [u8] {} + +/// Helper methods to process mutable bytes. +pub(crate) trait ByteSliceMut: AsMut<[u8]> { + /// Write a 64-bit integer as 8 bytes in little-endian order. + unsafe fn write_u64_unchecked(&mut self, value: u64) { + debug_assert!(self.as_mut().len() >= 8); + let dst = self.as_mut().as_mut_ptr() as *mut u64; + // NOTE: we must use `write_unaligned`, since dst is not + // guaranteed to be properly aligned. Miri will warn us + // if we use `write` instead of `write_unaligned`, as expected. + // SAFETY: safe as long as self is at least 8 bytes + unsafe { + ptr::write_unaligned(dst, u64::to_le(value)); + } + } +} + +impl ByteSliceMut for [u8] {} + +/// Bytes wrapper with specialized methods for ASCII characters. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct AsciiStr<'a> { + slc: &'a [u8], +} + +impl<'a> AsciiStr<'a> { + pub fn new(slc: &'a [u8]) -> Self { + Self { slc } + } + + /// Advance the view by n, advancing it in-place to (n..). + pub unsafe fn step_by(&mut self, n: usize) -> &mut Self { + // SAFETY: safe as long n is less than the buffer length + self.slc = unsafe { self.slc.get_unchecked(n..) }; + self + } + + /// Advance the view by n, advancing it in-place to (1..). + pub unsafe fn step(&mut self) -> &mut Self { + // SAFETY: safe as long as self is not empty + unsafe { self.step_by(1) } + } + + /// Iteratively parse and consume digits from bytes. + pub fn parse_digits(&mut self, mut func: impl FnMut(u8)) { + while let Some(&c) = self.as_ref().first() { + let c = c.wrapping_sub(b'0'); + if c < 10 { + func(c); + // SAFETY: self cannot be empty + unsafe { + self.step(); + } + } else { + break; + } + } + } +} + +impl<'a> AsRef<[u8]> for AsciiStr<'a> { + #[inline] + fn as_ref(&self) -> &[u8] { + self.slc + } +} + +impl<'a> ByteSlice for AsciiStr<'a> {} + +/// Determine if 8 bytes are all decimal digits. +/// This does not care about the order in which the bytes were loaded. +pub(crate) fn is_8digits(v: u64) -> bool { + let a = v.wrapping_add(0x4646_4646_4646_4646); + let b = v.wrapping_sub(0x3030_3030_3030_3030); + (a | b) & 0x8080_8080_8080_8080 == 0 +} + +/// Iteratively parse and consume digits from bytes. +pub(crate) fn parse_digits(s: &mut &[u8], mut f: impl FnMut(u8)) { + while let Some(&c) = s.get(0) { + let c = c.wrapping_sub(b'0'); + if c < 10 { + f(c); + *s = s.advance(1); + } else { + break; + } + } +} + +/// A custom 64-bit floating point type, representing `f * 2^e`. +/// e is biased, so it be directly shifted into the exponent bits. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] +pub struct BiasedFp { + /// The significant digits. + pub f: u64, + /// The biased, binary exponent. + pub e: i32, +} + +impl BiasedFp { + pub const fn zero_pow2(e: i32) -> Self { + Self { f: 0, e } + } +} diff --git a/library/core/src/num/dec2flt/decimal.rs b/library/core/src/num/dec2flt/decimal.rs new file mode 100644 index 0000000000..f8edc3625e --- /dev/null +++ b/library/core/src/num/dec2flt/decimal.rs @@ -0,0 +1,351 @@ +//! Arbitrary-precision decimal class for fallback algorithms. +//! +//! This is only used if the fast-path (native floats) and +//! the Eisel-Lemire algorithm are unable to unambiguously +//! determine the float. +//! +//! The technique used is "Simple Decimal Conversion", developed +//! by Nigel Tao and Ken Thompson. A detailed description of the +//! algorithm can be found in "ParseNumberF64 by Simple Decimal Conversion", +//! available online: . + +use crate::num::dec2flt::common::{is_8digits, parse_digits, ByteSlice, ByteSliceMut}; + +#[derive(Clone)] +pub struct Decimal { + /// The number of significant digits in the decimal. + pub num_digits: usize, + /// The offset of the decimal point in the significant digits. + pub decimal_point: i32, + /// If the number of significant digits stored in the decimal is truncated. + pub truncated: bool, + /// Buffer of the raw digits, in the range [0, 9]. + pub digits: [u8; Self::MAX_DIGITS], +} + +impl Default for Decimal { + fn default() -> Self { + Self { num_digits: 0, decimal_point: 0, truncated: false, digits: [0; Self::MAX_DIGITS] } + } +} + +impl Decimal { + /// The maximum number of digits required to unambiguously round a float. + /// + /// For a double-precision IEEE-754 float, this required 767 digits, + /// so we store the max digits + 1. + /// + /// We can exactly represent a float in radix `b` from radix 2 if + /// `b` is divisible by 2. This function calculates the exact number of + /// digits required to exactly represent that float. + /// + /// According to the "Handbook of Floating Point Arithmetic", + /// for IEEE754, with emin being the min exponent, p2 being the + /// precision, and b being the radix, the number of digits follows as: + /// + /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋` + /// + /// For f32, this follows as: + /// emin = -126 + /// p2 = 24 + /// + /// For f64, this follows as: + /// emin = -1022 + /// p2 = 53 + /// + /// In Python: + /// `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))` + pub const MAX_DIGITS: usize = 768; + /// The max digits that can be exactly represented in a 64-bit integer. + pub const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19; + pub const DECIMAL_POINT_RANGE: i32 = 2047; + + /// Append a digit to the buffer. + pub fn try_add_digit(&mut self, digit: u8) { + if self.num_digits < Self::MAX_DIGITS { + self.digits[self.num_digits] = digit; + } + self.num_digits += 1; + } + + /// Trim trailing zeros from the buffer. + pub fn trim(&mut self) { + // All of the following calls to `Decimal::trim` can't panic because: + // + // 1. `parse_decimal` sets `num_digits` to a max of `Decimal::MAX_DIGITS`. + // 2. `right_shift` sets `num_digits` to `write_index`, which is bounded by `num_digits`. + // 3. `left_shift` `num_digits` to a max of `Decimal::MAX_DIGITS`. + // + // Trim is only called in `right_shift` and `left_shift`. + debug_assert!(self.num_digits <= Self::MAX_DIGITS); + while self.num_digits != 0 && self.digits[self.num_digits - 1] == 0 { + self.num_digits -= 1; + } + } + + pub fn round(&self) -> u64 { + if self.num_digits == 0 || self.decimal_point < 0 { + return 0; + } else if self.decimal_point > 18 { + return 0xFFFF_FFFF_FFFF_FFFF_u64; + } + let dp = self.decimal_point as usize; + let mut n = 0_u64; + for i in 0..dp { + n *= 10; + if i < self.num_digits { + n += self.digits[i] as u64; + } + } + let mut round_up = false; + if dp < self.num_digits { + round_up = self.digits[dp] >= 5; + if self.digits[dp] == 5 && dp + 1 == self.num_digits { + round_up = self.truncated || ((dp != 0) && (1 & self.digits[dp - 1] != 0)) + } + } + if round_up { + n += 1; + } + n + } + + /// Computes decimal * 2^shift. + pub fn left_shift(&mut self, shift: usize) { + if self.num_digits == 0 { + return; + } + let num_new_digits = number_of_digits_decimal_left_shift(self, shift); + let mut read_index = self.num_digits; + let mut write_index = self.num_digits + num_new_digits; + let mut n = 0_u64; + while read_index != 0 { + read_index -= 1; + write_index -= 1; + n += (self.digits[read_index] as u64) << shift; + let quotient = n / 10; + let remainder = n - (10 * quotient); + if write_index < Self::MAX_DIGITS { + self.digits[write_index] = remainder as u8; + } else if remainder > 0 { + self.truncated = true; + } + n = quotient; + } + while n > 0 { + write_index -= 1; + let quotient = n / 10; + let remainder = n - (10 * quotient); + if write_index < Self::MAX_DIGITS { + self.digits[write_index] = remainder as u8; + } else if remainder > 0 { + self.truncated = true; + } + n = quotient; + } + self.num_digits += num_new_digits; + if self.num_digits > Self::MAX_DIGITS { + self.num_digits = Self::MAX_DIGITS; + } + self.decimal_point += num_new_digits as i32; + self.trim(); + } + + /// Computes decimal * 2^-shift. + pub fn right_shift(&mut self, shift: usize) { + let mut read_index = 0; + let mut write_index = 0; + let mut n = 0_u64; + while (n >> shift) == 0 { + if read_index < self.num_digits { + n = (10 * n) + self.digits[read_index] as u64; + read_index += 1; + } else if n == 0 { + return; + } else { + while (n >> shift) == 0 { + n *= 10; + read_index += 1; + } + break; + } + } + self.decimal_point -= read_index as i32 - 1; + if self.decimal_point < -Self::DECIMAL_POINT_RANGE { + // `self = Self::Default()`, but without the overhead of clearing `digits`. + self.num_digits = 0; + self.decimal_point = 0; + self.truncated = false; + return; + } + let mask = (1_u64 << shift) - 1; + while read_index < self.num_digits { + let new_digit = (n >> shift) as u8; + n = (10 * (n & mask)) + self.digits[read_index] as u64; + read_index += 1; + self.digits[write_index] = new_digit; + write_index += 1; + } + while n > 0 { + let new_digit = (n >> shift) as u8; + n = 10 * (n & mask); + if write_index < Self::MAX_DIGITS { + self.digits[write_index] = new_digit; + write_index += 1; + } else if new_digit > 0 { + self.truncated = true; + } + } + self.num_digits = write_index; + self.trim(); + } +} + +/// Parse a big integer representation of the float as a decimal. +pub fn parse_decimal(mut s: &[u8]) -> Decimal { + let mut d = Decimal::default(); + let start = s; + s = s.skip_chars(b'0'); + parse_digits(&mut s, |digit| d.try_add_digit(digit)); + if s.first_is(b'.') { + s = s.advance(1); + let first = s; + // Skip leading zeros. + if d.num_digits == 0 { + s = s.skip_chars(b'0'); + } + while s.len() >= 8 && d.num_digits + 8 < Decimal::MAX_DIGITS { + // SAFETY: s is at least 8 bytes. + let v = unsafe { s.read_u64_unchecked() }; + if !is_8digits(v) { + break; + } + // SAFETY: d.num_digits + 8 is less than d.digits.len() + unsafe { + d.digits[d.num_digits..].write_u64_unchecked(v - 0x3030_3030_3030_3030); + } + d.num_digits += 8; + s = s.advance(8); + } + parse_digits(&mut s, |digit| d.try_add_digit(digit)); + d.decimal_point = s.len() as i32 - first.len() as i32; + } + if d.num_digits != 0 { + // Ignore the trailing zeros if there are any + let mut n_trailing_zeros = 0; + for &c in start[..(start.len() - s.len())].iter().rev() { + if c == b'0' { + n_trailing_zeros += 1; + } else if c != b'.' { + break; + } + } + d.decimal_point += n_trailing_zeros as i32; + d.num_digits -= n_trailing_zeros; + d.decimal_point += d.num_digits as i32; + if d.num_digits > Decimal::MAX_DIGITS { + d.truncated = true; + d.num_digits = Decimal::MAX_DIGITS; + } + } + if s.first_is2(b'e', b'E') { + s = s.advance(1); + let mut neg_exp = false; + if s.first_is(b'-') { + neg_exp = true; + s = s.advance(1); + } else if s.first_is(b'+') { + s = s.advance(1); + } + let mut exp_num = 0_i32; + parse_digits(&mut s, |digit| { + if exp_num < 0x10000 { + exp_num = 10 * exp_num + digit as i32; + } + }); + d.decimal_point += if neg_exp { -exp_num } else { exp_num }; + } + for i in d.num_digits..Decimal::MAX_DIGITS_WITHOUT_OVERFLOW { + d.digits[i] = 0; + } + d +} + +fn number_of_digits_decimal_left_shift(d: &Decimal, mut shift: usize) -> usize { + #[rustfmt::skip] + const TABLE: [u16; 65] = [ + 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, 0x181D, 0x2024, + 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, 0x3073, 0x3080, 0x388E, 0x389C, + 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, + 0x5180, 0x5998, 0x59B0, 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, + 0x72AA, 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, 0x8C02, + 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, 0x051C, 0x051C, + ]; + #[rustfmt::skip] + const TABLE_POW5: [u8; 0x051C] = [ + 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, 0, 6, 2, 5, 1, + 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, + 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, + 5, 1, 5, 2, 5, 8, 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6, + 9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1, + 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9, + 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6, 0, 4, 6, + 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, + 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, + 3, 8, 2, 8, 1, 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6, + 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, 7, 4, 6, 1, 5, + 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, + 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, + 3, 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4, + 6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, + 1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0, + 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, 0, 3, 1, 2, 5, 3, + 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, + 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, + 7, 0, 1, 7, 7, 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5, + 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, 7, 3, 6, 7, 5, + 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, + 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8, + 8, 6, 0, 8, 0, 8, 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0, + 9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0, + 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1, + 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7, 5, 7, 8, 1, 2, + 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, + 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, + 6, 6, 8, 9, 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3, + 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, 5, 0, 0, 6, 2, + 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, + 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1, + 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8, + 2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, + 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1, + 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1, 3, 8, 7, 7, 7, 8, + 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, + 6, 2, 5, 6, 9, 3, 8, 8, 9, 3, 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, + 5, 5, 6, 7, 6, 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1, + 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, 7, 3, 4, 7, 2, + 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, + 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2, + 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5, + ]; + + shift &= 63; + let x_a = TABLE[shift]; + let x_b = TABLE[shift + 1]; + let num_new_digits = (x_a >> 11) as _; + let pow5_a = (0x7FF & x_a) as usize; + let pow5_b = (0x7FF & x_b) as usize; + let pow5 = &TABLE_POW5[pow5_a..]; + for (i, &p5) in pow5.iter().enumerate().take(pow5_b - pow5_a) { + if i >= d.num_digits { + return num_new_digits - 1; + } else if d.digits[i] == p5 { + continue; + } else if d.digits[i] < p5 { + return num_new_digits - 1; + } else { + return num_new_digits; + } + } + num_new_digits +} diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs new file mode 100644 index 0000000000..5921c5ed47 --- /dev/null +++ b/library/core/src/num/dec2flt/float.rs @@ -0,0 +1,207 @@ +//! Helper trait for generic float types. + +use crate::fmt::{Debug, LowerExp}; +use crate::num::FpCategory; +use crate::ops::{Add, Div, Mul, Neg}; + +/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`. +/// +/// See the parent module's doc comment for why this is necessary. +/// +/// Should **never ever** be implemented for other types or be used outside the dec2flt module. +#[doc(hidden)] +pub trait RawFloat: + Sized + + Div + + Neg + + Mul + + Add + + LowerExp + + PartialEq + + PartialOrd + + Default + + Clone + + Copy + + Debug +{ + const INFINITY: Self; + const NEG_INFINITY: Self; + const NAN: Self; + const NEG_NAN: Self; + + /// The number of bits in the significand, *excluding* the hidden bit. + const MANTISSA_EXPLICIT_BITS: usize; + + // Round-to-even only happens for negative values of q + // when q ≥ −4 in the 64-bit case and when q ≥ −17 in + // the 32-bitcase. + // + // When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we + // have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have + // 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10. + // + // When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64 + // so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case) + // or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64 + // (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11 + // or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase). + // + // Thus we have that we only need to round ties to even when + // we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10] + // (in the 32-bit case). In both cases,the power of five(5^|q|) + // fits in a 64-bit word. + const MIN_EXPONENT_ROUND_TO_EVEN: i32; + const MAX_EXPONENT_ROUND_TO_EVEN: i32; + + // Minimum exponent that for a fast path case, or `-⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋` + const MIN_EXPONENT_FAST_PATH: i64; + + // Maximum exponent that for a fast path case, or `⌊(MANTISSA_EXPLICIT_BITS+1)/log2(5)⌋` + const MAX_EXPONENT_FAST_PATH: i64; + + // Maximum exponent that can be represented for a disguised-fast path case. + // This is `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋` + const MAX_EXPONENT_DISGUISED_FAST_PATH: i64; + + // Minimum exponent value `-(1 << (EXP_BITS - 1)) + 1`. + const MINIMUM_EXPONENT: i32; + + // Largest exponent value `(1 << EXP_BITS) - 1`. + const INFINITE_POWER: i32; + + // Index (in bits) of the sign. + const SIGN_INDEX: usize; + + // Smallest decimal exponent for a non-zero value. + const SMALLEST_POWER_OF_TEN: i32; + + // Largest decimal exponent for a non-infinite value. + const LARGEST_POWER_OF_TEN: i32; + + // Maximum mantissa for the fast-path (`1 << 53` for f64). + const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_EXPLICIT_BITS; + + /// Convert integer into float through an as cast. + /// This is only called in the fast-path algorithm, and therefore + /// will not lose precision, since the value will always have + /// only if the value is <= Self::MAX_MANTISSA_FAST_PATH. + fn from_u64(v: u64) -> Self; + + /// Performs a raw transmutation from an integer. + fn from_u64_bits(v: u64) -> Self; + + /// Get a small power-of-ten for fast-path multiplication. + fn pow10_fast_path(exponent: usize) -> Self; + + /// Returns the category that this number falls into. + fn classify(self) -> FpCategory; + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(self) -> (u64, i16, i8); +} + +impl RawFloat for f32 { + const INFINITY: Self = f32::INFINITY; + const NEG_INFINITY: Self = f32::NEG_INFINITY; + const NAN: Self = f32::NAN; + const NEG_NAN: Self = -f32::NAN; + + const MANTISSA_EXPLICIT_BITS: usize = 23; + const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17; + const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10; + const MIN_EXPONENT_FAST_PATH: i64 = -10; // assuming FLT_EVAL_METHOD = 0 + const MAX_EXPONENT_FAST_PATH: i64 = 10; + const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 17; + const MINIMUM_EXPONENT: i32 = -127; + const INFINITE_POWER: i32 = 0xFF; + const SIGN_INDEX: usize = 31; + const SMALLEST_POWER_OF_TEN: i32 = -65; + const LARGEST_POWER_OF_TEN: i32 = 38; + + fn from_u64(v: u64) -> Self { + debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); + v as _ + } + + fn from_u64_bits(v: u64) -> Self { + f32::from_bits((v & 0xFFFFFFFF) as u32) + } + + fn pow10_fast_path(exponent: usize) -> Self { + #[allow(clippy::use_self)] + const TABLE: [f32; 16] = + [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.]; + TABLE[exponent & 15] + } + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(self) -> (u64, i16, i8) { + let bits = self.to_bits(); + let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 23) & 0xff) as i16; + let mantissa = + if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 }; + // Exponent bias + mantissa shift + exponent -= 127 + 23; + (mantissa as u64, exponent, sign) + } + + fn classify(self) -> FpCategory { + self.classify() + } +} + +impl RawFloat for f64 { + const INFINITY: Self = f64::INFINITY; + const NEG_INFINITY: Self = f64::NEG_INFINITY; + const NAN: Self = f64::NAN; + const NEG_NAN: Self = -f64::NAN; + + const MANTISSA_EXPLICIT_BITS: usize = 52; + const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4; + const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23; + const MIN_EXPONENT_FAST_PATH: i64 = -22; // assuming FLT_EVAL_METHOD = 0 + const MAX_EXPONENT_FAST_PATH: i64 = 22; + const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 37; + const MINIMUM_EXPONENT: i32 = -1023; + const INFINITE_POWER: i32 = 0x7FF; + const SIGN_INDEX: usize = 63; + const SMALLEST_POWER_OF_TEN: i32 = -342; + const LARGEST_POWER_OF_TEN: i32 = 308; + + fn from_u64(v: u64) -> Self { + debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH); + v as _ + } + + fn from_u64_bits(v: u64) -> Self { + f64::from_bits(v) + } + + fn pow10_fast_path(exponent: usize) -> Self { + const TABLE: [f64; 32] = [ + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, + 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0., + ]; + TABLE[exponent & 31] + } + + /// Returns the mantissa, exponent and sign as integers. + fn integer_decode(self) -> (u64, i16, i8) { + let bits = self.to_bits(); + let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; + let mantissa = if exponent == 0 { + (bits & 0xfffffffffffff) << 1 + } else { + (bits & 0xfffffffffffff) | 0x10000000000000 + }; + // Exponent bias + mantissa shift + exponent -= 1023 + 52; + (mantissa, exponent, sign) + } + + fn classify(self) -> FpCategory { + self.classify() + } +} diff --git a/library/core/src/num/dec2flt/fpu.rs b/library/core/src/num/dec2flt/fpu.rs new file mode 100644 index 0000000000..24492d9a1d --- /dev/null +++ b/library/core/src/num/dec2flt/fpu.rs @@ -0,0 +1,89 @@ +//! Platform-specific, assembly instructions to avoid +//! intermediate rounding on architectures with FPUs. + +pub use fpu_precision::set_precision; + +// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available. +// The x87 FPU operates with 80 bits of precision by default, which means that operations will +// round to 80 bits causing double rounding to happen when values are eventually represented as +// 32/64 bit float values. To overcome this, the FPU control word can be set so that the +// computations are performed in the desired precision. +#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] +mod fpu_precision { + use core::mem::size_of; + + /// A structure used to preserve the original value of the FPU control word, so that it can be + /// restored when the structure is dropped. + /// + /// The x87 FPU is a 16-bits register whose fields are as follows: + /// + /// | 12-15 | 10-11 | 8-9 | 6-7 | 5 | 4 | 3 | 2 | 1 | 0 | + /// |------:|------:|----:|----:|---:|---:|---:|---:|---:|---:| + /// | | RC | PC | | PM | UM | OM | ZM | DM | IM | + /// + /// The documentation for all of the fields is available in the IA-32 Architectures Software + /// Developer's Manual (Volume 1). + /// + /// The only field which is relevant for the following code is PC, Precision Control. This + /// field determines the precision of the operations performed by the FPU. It can be set to: + /// - 0b00, single precision i.e., 32-bits + /// - 0b10, double precision i.e., 64-bits + /// - 0b11, double extended precision i.e., 80-bits (default state) + /// The 0b01 value is reserved and should not be used. + pub struct FPUControlWord(u16); + + fn set_cw(cw: u16) { + // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with + // any `u16` + unsafe { + asm!( + "fldcw word ptr [{}]", + in(reg) &cw, + options(nostack), + ) + } + } + + /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`. + pub fn set_precision() -> FPUControlWord { + let mut cw = 0_u16; + + // Compute the value for the Precision Control field that is appropriate for `T`. + let cw_precision = match size_of::() { + 4 => 0x0000, // 32 bits + 8 => 0x0200, // 64 bits + _ => 0x0300, // default, 80 bits + }; + + // Get the original value of the control word to restore it later, when the + // `FPUControlWord` structure is dropped + // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with + // any `u16` + unsafe { + asm!( + "fnstcw word ptr [{}]", + in(reg) &mut cw, + options(nostack), + ) + } + + // Set the control word to the desired precision. This is achieved by masking away the old + // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above. + set_cw((cw & 0xFCFF) | cw_precision); + + FPUControlWord(cw) + } + + impl Drop for FPUControlWord { + fn drop(&mut self) { + set_cw(self.0) + } + } +} + +// In most architectures, floating point operations have an explicit bit size, therefore the +// precision of the computation is determined on a per-operation basis. +#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] +mod fpu_precision { + pub fn set_precision() {} +} diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs new file mode 100644 index 0000000000..9b7efc3d55 --- /dev/null +++ b/library/core/src/num/dec2flt/lemire.rs @@ -0,0 +1,166 @@ +//! Implementation of the Eisel-Lemire algorithm. + +use crate::num::dec2flt::common::BiasedFp; +use crate::num::dec2flt::float::RawFloat; +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. +/// +/// Fast conversion of a the significant digits and decimal exponent +/// a float to a extended representation with a binary float. This +/// algorithm will accurately parse the vast majority of cases, +/// and uses a 128-bit representation (with a fallback 192-bit +/// representation). +/// +/// This algorithm scales the exponent by the decimal exponent +/// using pre-computed powers-of-5, and calculates if the +/// representation can be unambiguously rounded to the nearest +/// machine float. Near-halfway cases are not handled here, +/// and are represented by a negative, biased binary exponent. +/// +/// The algorithm is described in detail in "Daniel Lemire, Number Parsing +/// at a Gigabyte per Second" in section 5, "Fast Algorithm", and +/// section 6, "Exact Numbers And Ties", available online: +/// . +pub fn compute_float(q: i64, mut w: u64) -> BiasedFp { + let fp_zero = BiasedFp::zero_pow2(0); + let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER); + let fp_error = BiasedFp::zero_pow2(-1); + + // Short-circuit if the value can only be a literal 0 or infinity. + if w == 0 || q < F::SMALLEST_POWER_OF_TEN as i64 { + return fp_zero; + } else if q > F::LARGEST_POWER_OF_TEN as i64 { + return fp_inf; + } + // Normalize our significant digits, so the most-significant bit is set. + let lz = w.leading_zeros(); + w <<= lz; + let (lo, hi) = compute_product_approx(q, w, F::MANTISSA_EXPLICIT_BITS + 3); + if lo == 0xFFFF_FFFF_FFFF_FFFF { + // If we have failed to approximate w x 5^-q with our 128-bit value. + // Since the addition of 1 could lead to an overflow which could then + // round up over the half-way point, this can lead to improper rounding + // of a float. + // + // However, this can only occur if q ∈ [-27, 55]. The upper bound of q + // is 55 because 5^55 < 2^128, however, this can only happen if 5^q > 2^64, + // since otherwise the product can be represented in 64-bits, producing + // an exact result. For negative exponents, rounding-to-even can + // only occur if 5^-q < 2^64. + // + // For detailed explanations of rounding for negative exponents, see + // . For detailed + // explanations of rounding for positive exponents, see + // . + let inside_safe_exponent = (q >= -27) && (q <= 55); + if !inside_safe_exponent { + return fp_error; + } + } + let upperbit = (hi >> 63) as i32; + let mut mantissa = hi >> (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3); + let mut power2 = power(q as i32) + upperbit - lz as i32 - F::MINIMUM_EXPONENT; + if power2 <= 0 { + if -power2 + 1 >= 64 { + // Have more than 64 bits below the minimum exponent, must be 0. + return fp_zero; + } + // Have a subnormal value. + mantissa >>= -power2 + 1; + mantissa += mantissa & 1; + mantissa >>= 1; + power2 = (mantissa >= (1_u64 << F::MANTISSA_EXPLICIT_BITS)) as i32; + 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 + // need to round down. + // + // This will only occur if: + // 1. The lower 64 bits of the 128-bit representation is 0. + // IE, 5^q fits in single 64-bit word. + // 2. The least-significant bit prior to truncated mantissa is odd. + // 3. All the bits truncated when shifting to mantissa bits + 1 are 0. + // + // Or, we may fall between two floats: we are exactly halfway. + if lo <= 1 + && q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64 + && q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64 + && mantissa & 3 == 1 + && (mantissa << (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3)) == hi + { + // Zero the lowest bit, so we don't round up. + mantissa &= !1_u64; + } + // Round-to-even, then shift the significant digits into place. + mantissa += mantissa & 1; + mantissa >>= 1; + if mantissa >= (2_u64 << F::MANTISSA_EXPLICIT_BITS) { + // Rounding up overflowed, so the carry bit is set. Set the + // mantissa to 1 (only the implicit, hidden bit is set) and + // increase the exponent. + mantissa = 1_u64 << F::MANTISSA_EXPLICIT_BITS; + power2 += 1; + } + // Zero out the hidden bit. + mantissa &= !(1_u64 << F::MANTISSA_EXPLICIT_BITS); + if power2 >= F::INFINITE_POWER { + // Exponent is above largest normal value, must be infinite. + return fp_inf; + } + BiasedFp { f: mantissa, e: power2 } +} + +/// Calculate a base 2 exponent from a decimal exponent. +/// This uses a pre-computed integer approximation for +/// log2(10), where 217706 / 2^16 is accurate for the +/// entire range of non-finite decimal exponents. +fn power(q: i32) -> i32 { + (q.wrapping_mul(152_170 + 65536) >> 16) + 63 +} + +fn full_multiplication(a: u64, b: u64) -> (u64, u64) { + let r = (a as u128) * (b as u128); + (r as u64, (r >> 64) as u64) +} + +// This will compute or rather approximate w * 5**q and return a pair of 64-bit words +// approximating the result, with the "high" part corresponding to the most significant +// bits and the low part corresponding to the least significant bits. +fn compute_product_approx(q: i64, w: u64, precision: usize) -> (u64, u64) { + debug_assert!(q >= SMALLEST_POWER_OF_FIVE as i64); + debug_assert!(q <= LARGEST_POWER_OF_FIVE as i64); + debug_assert!(precision <= 64); + + let mask = if precision < 64 { + 0xFFFF_FFFF_FFFF_FFFF_u64 >> precision + } else { + 0xFFFF_FFFF_FFFF_FFFF_u64 + }; + + // 5^q < 2^64, then the multiplication always provides an exact value. + // That means whenever we need to round ties to even, we always have + // an exact value. + let index = (q - SMALLEST_POWER_OF_FIVE as i64) as usize; + let (lo5, hi5) = POWER_OF_FIVE_128[index]; + // Only need one multiplication as long as there is 1 zero but + // in the explicit mantissa bits, +1 for the hidden bit, +1 to + // determine the rounding direction, +1 for if the computed + // product has a leading zero. + let (mut first_lo, mut first_hi) = full_multiplication(w, lo5); + if first_hi & mask == mask { + // Need to do a second multiplication to get better precision + // for the lower product. This will always be exact + // where q is < 55, since 5^55 < 2^128. If this wraps, + // then we need to need to round up the hi product. + let (_, second_hi) = full_multiplication(w, hi5); + first_lo = first_lo.wrapping_add(second_hi); + if second_hi > first_lo { + first_hi += 1; + } + } + (first_lo, first_hi) +} diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index f008a64ffe..c78492f5ae 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -27,20 +27,12 @@ //! //! We then try a long chain of progressively more general and expensive special cases using //! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then -//! a type with 64 bit significand, `Fp`). When all these fail, we bite the bullet and resort to a -//! simple but very slow algorithm that involved computing `f * 10^e` fully and doing an iterative -//! search for the best approximation. -//! -//! Primarily, this module and its children implement the algorithms described in: -//! "How to Read Floating Point Numbers Accurately" by William D. Clinger, -//! available online: -//! -//! In addition, there are numerous helper functions that are used in the paper but not available -//! in Rust (or at least in core). Our version is additionally complicated by the need to handle -//! overflow and underflow and the desire to handle subnormal numbers. Bellerophon and -//! Algorithm R have trouble with overflow, subnormals, and underflow. We conservatively switch to -//! Algorithm M (with the modifications described in section 8 of the paper) well before the -//! inputs get into the critical region. +//! a type with 64 bit significand). The extended-precision algorithm +//! uses the Eisel-Lemire algorithm, which uses a 128-bit (or 192-bit) +//! representation that can accurately and quickly compute the vast majority +//! of floats. When all these fail, we bite the bullet and resort to using +//! a large-decimal representation, shifting the digits into range, calculating +//! the upper significant bits and exactly round to the nearest representation. //! //! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions //! are parametrized. One might think that it's enough to parse to `f64` and cast the result to @@ -54,10 +46,9 @@ //! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision //! and round *exactly once, at the end*, by considering all truncated bits at once. //! -//! FIXME: Although some code duplication is necessary, perhaps parts of the code could be shuffled -//! around such that less code is duplicated. Large parts of the algorithms are independent of the -//! float type to output, or only needs access to a few constants, which could be passed in as -//! parameters. +//! Primarily, this module and its children implement the algorithms described in: +//! "Number Parsing at a Gigabyte per Second", available online: +//! . //! //! # Other //! @@ -87,16 +78,22 @@ use crate::fmt; use crate::str::FromStr; -use self::num::digits_to_big; -use self::parse::{parse_decimal, Decimal, ParseResult, Sign}; -use self::rawfp::RawFloat; +use self::common::{BiasedFp, ByteSlice}; +use self::float::RawFloat; +use self::lemire::compute_float; +use self::parse::{parse_inf_nan, parse_number}; +use self::slow::parse_long_mantissa; -mod algorithm; -mod num; +mod common; +mod decimal; +mod fpu; +mod slow; mod table; -// These two have their own tests. +// float is used in flt2dec, and all are used in unit tests. +pub mod float; +pub mod lemire; +pub mod number; pub mod parse; -pub mod rawfp; macro_rules! from_str_float_impl { ($t:ty) => { @@ -136,13 +133,6 @@ macro_rules! from_str_float_impl { /// /// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation /// - /// # Known bugs - /// - /// In some situations, some strings that should create a valid float - /// instead return an error. See [issue #31407] for details. - /// - /// [issue #31407]: https://github.com/rust-lang/rust/issues/31407 - /// /// # Arguments /// /// * src - A string @@ -211,148 +201,70 @@ impl fmt::Display for ParseFloatError { } } -fn pfe_empty() -> ParseFloatError { +pub(super) fn pfe_empty() -> ParseFloatError { ParseFloatError { kind: FloatErrorKind::Empty } } -fn pfe_invalid() -> ParseFloatError { +// Used in unit tests, keep public. +// This is much better than making FloatErrorKind and ParseFloatError::kind public. +pub fn pfe_invalid() -> ParseFloatError { ParseFloatError { kind: FloatErrorKind::Invalid } } -/// Splits a decimal string into sign and the rest, without inspecting or validating the rest. -fn extract_sign(s: &str) -> (Sign, &str) { - match s.as_bytes()[0] { - b'+' => (Sign::Positive, &s[1..]), - b'-' => (Sign::Negative, &s[1..]), - // If the string is invalid, we never use the sign, so we don't need to validate here. - _ => (Sign::Positive, s), - } +/// Converts a `BiasedFp` to the closest machine float type. +fn biased_fp_to_float(x: BiasedFp) -> T { + let mut word = x.f; + word |= (x.e as u64) << T::MANTISSA_EXPLICIT_BITS; + T::from_u64_bits(word) } /// Converts a decimal string into a floating point number. -fn dec2flt(s: &str) -> Result { - if s.is_empty() { +pub fn dec2flt(s: &str) -> Result { + let mut s = s.as_bytes(); + let c = if let Some(&c) = s.first() { + c + } else { return Err(pfe_empty()); + }; + let negative = c == b'-'; + if c == b'-' || c == b'+' { + s = s.advance(1); + } + if s.is_empty() { + return Err(pfe_invalid()); } - let (sign, s) = extract_sign(s); - let flt = match parse_decimal(s) { - ParseResult::Valid(decimal) => convert(decimal)?, - ParseResult::ShortcutToInf => T::INFINITY, - ParseResult::ShortcutToZero => T::ZERO, - ParseResult::Invalid => { - if s.eq_ignore_ascii_case("nan") { - T::NAN - } else if s.eq_ignore_ascii_case("inf") || s.eq_ignore_ascii_case("infinity") { - T::INFINITY + + let num = match parse_number(s, negative) { + Some(r) => r, + None => { + if let Some(value) = parse_inf_nan(s, negative) { + return Ok(value); } else { return Err(pfe_invalid()); } } }; - - match sign { - Sign::Positive => Ok(flt), - Sign::Negative => Ok(-flt), + if let Some(value) = num.try_fast_path::() { + return Ok(value); } -} - -/// The main workhorse for the decimal-to-float conversion: Orchestrate all the preprocessing -/// and figure out which algorithm should do the actual conversion. -fn convert(mut decimal: Decimal<'_>) -> Result { - simplify(&mut decimal); - if let Some(x) = trivial_cases(&decimal) { - return Ok(x); - } - // Remove/shift out the decimal point. - let e = decimal.exp - decimal.fractional.len() as i64; - if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) { - return Ok(x); - } - // Big32x40 is limited to 1280 bits, which translates to about 385 decimal digits. - // If we exceed this, we'll crash, so we error out before getting too close (within 10^10). - let upper_bound = bound_intermediate_digits(&decimal, e); - if upper_bound > 375 { - return Err(pfe_invalid()); - } - let f = digits_to_big(decimal.integral, decimal.fractional); - - // Now the exponent certainly fits in 16 bit, which is used throughout the main algorithms. - let e = e as i16; - // FIXME These bounds are rather conservative. A more careful analysis of the failure modes - // of Bellerophon could allow using it in more cases for a massive speed up. - let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E; - let value_in_range = upper_bound <= T::MAX_NORMAL_DIGITS as u64; - if exponent_in_range && value_in_range { - Ok(algorithm::bellerophon(&f, e)) - } else { - Ok(algorithm::algorithm_m(&f, e)) - } -} -// As written, this optimizes badly (see #27130, though it refers to an old version of the code). -// `inline(always)` is a workaround for that. There are only two call sites overall and it doesn't -// make code size worse. - -/// Strip zeros where possible, even when this requires changing the exponent -#[inline(always)] -fn simplify(decimal: &mut Decimal<'_>) { - let is_zero = &|&&d: &&u8| -> bool { d == b'0' }; - // Trimming these zeros does not change anything but may enable the fast path (< 15 digits). - let leading_zeros = decimal.integral.iter().take_while(is_zero).count(); - decimal.integral = &decimal.integral[leading_zeros..]; - let trailing_zeros = decimal.fractional.iter().rev().take_while(is_zero).count(); - let end = decimal.fractional.len() - trailing_zeros; - decimal.fractional = &decimal.fractional[..end]; - // Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent accordingly. - // This may not always be a win (possibly pushes some numbers out of the fast path), but it - // simplifies other parts significantly (notably, approximating the magnitude of the value). - if decimal.integral.is_empty() { - let leading_zeros = decimal.fractional.iter().take_while(is_zero).count(); - decimal.fractional = &decimal.fractional[leading_zeros..]; - decimal.exp -= leading_zeros as i64; - } else if decimal.fractional.is_empty() { - let trailing_zeros = decimal.integral.iter().rev().take_while(is_zero).count(); - let end = decimal.integral.len() - trailing_zeros; - decimal.integral = &decimal.integral[..end]; - decimal.exp += trailing_zeros as i64; + // If significant digits were truncated, then we can have rounding error + // only if `mantissa + 1` produces a different result. We also avoid + // redundantly using the Eisel-Lemire algorithm if it was unable to + // correctly round on the first pass. + let mut fp = compute_float::(num.exponent, num.mantissa); + if num.many_digits && fp.e >= 0 && fp != compute_float::(num.exponent, num.mantissa + 1) { + fp.e = -1; } -} - -/// Returns a quick-an-dirty upper bound on the size (log10) of the largest value that Algorithm R -/// and Algorithm M will compute while working on the given decimal. -fn bound_intermediate_digits(decimal: &Decimal<'_>, e: i64) -> u64 { - // We don't need to worry too much about overflow here thanks to trivial_cases() and the - // parser, which filter out the most extreme inputs for us. - let f_len: u64 = decimal.integral.len() as u64 + decimal.fractional.len() as u64; - if e >= 0 { - // In the case e >= 0, both algorithms compute about `f * 10^e`. Algorithm R proceeds to - // do some complicated calculations with this but we can ignore that for the upper bound - // because it also reduces the fraction beforehand, so we have plenty of buffer there. - f_len + (e as u64) - } else { - // If e < 0, Algorithm R does roughly the same thing, but Algorithm M differs: - // It tries to find a positive number k such that `f << k / 10^e` is an in-range - // significand. This will result in about `2^53 * f * 10^e` < `10^17 * f * 10^e`. - // One input that triggers this is 0.33...33 (375 x 3). - f_len + e.unsigned_abs() + 17 + // Unable to correctly round the float using the Eisel-Lemire algorithm. + // Fallback to a slower, but always correct algorithm. + if fp.e < 0 { + fp = parse_long_mantissa::(s); } -} -/// Detects obvious overflows and underflows without even looking at the decimal digits. -fn trivial_cases(decimal: &Decimal<'_>) -> Option { - // There were zeros but they were stripped by simplify() - if decimal.integral.is_empty() && decimal.fractional.is_empty() { - return Some(T::ZERO); - } - // This is a crude approximation of ceil(log10(the real value)). We don't need to worry too - // much about overflow here because the input length is tiny (at least compared to 2^64) and - // the parser already handles exponents whose absolute value is greater than 10^18 - // (which is still 10^19 short of 2^64). - let max_place = decimal.exp + decimal.integral.len() as i64; - if max_place > T::INF_CUTOFF { - return Some(T::INFINITY); - } else if max_place < T::ZERO_CUTOFF { - return Some(T::ZERO); + let mut float = biased_fp_to_float::(fp); + if num.negative { + float = -float; } - None + Ok(float) } diff --git a/library/core/src/num/dec2flt/num.rs b/library/core/src/num/dec2flt/num.rs deleted file mode 100644 index 208783dd32..0000000000 --- a/library/core/src/num/dec2flt/num.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Utility functions for bignums that don't make too much sense to turn into methods. - -// FIXME This module's name is a bit unfortunate, since other modules also import `core::num`. - -use crate::cmp::Ordering::{self, Equal, Greater, Less}; - -pub use crate::num::bignum::Big32x40 as Big; - -/// Test whether truncating all bits less significant than `ones_place` introduces -/// a relative error less, equal, or greater than 0.5 ULP. -pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering { - if ones_place == 0 { - return Less; - } - let half_bit = ones_place - 1; - if f.get_bit(half_bit) == 0 { - // < 0.5 ULP - return Less; - } - // If all remaining bits are zero, it's = 0.5 ULP, otherwise > 0.5 - // If there are no more bits (half_bit == 0), the below also correctly returns Equal. - for i in 0..half_bit { - if f.get_bit(i) == 1 { - return Greater; - } - } - Equal -} - -/// Converts an ASCII string containing only decimal digits to a `u64`. -/// -/// Does not perform checks for overflow or invalid characters, so if the caller is not careful, -/// the result is bogus and can panic (though it won't be `unsafe`). Additionally, empty strings -/// are treated as zero. This function exists because -/// -/// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and -/// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is -/// more complicated than this entire function. -pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 -where - T: IntoIterator, -{ - let mut result = 0; - for &c in bytes { - result = result * 10 + (c - b'0') as u64; - } - result -} - -/// Converts a string of ASCII digits into a bignum. -/// -/// Like `from_str_unchecked`, this function relies on the parser to weed out non-digits. -pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big { - let mut f = Big::from_small(0); - for &c in integral.iter().chain(fractional) { - let n = (c - b'0') as u32; - f.mul_small(10); - f.add_small(n); - } - f -} - -/// Unwraps a bignum into a 64 bit integer. Panics if the number is too large. -pub fn to_u64(x: &Big) -> u64 { - assert!(x.bit_length() < 64); - let d = x.digits(); - if d.len() < 2 { d[0] as u64 } else { (d[1] as u64) << 32 | d[0] as u64 } -} - -/// Extracts a range of bits. - -/// Index 0 is the least significant bit and the range is half-open as usual. -/// Panics if asked to extract more bits than fit into the return type. -pub fn get_bits(x: &Big, start: usize, end: usize) -> u64 { - assert!(end - start <= 64); - let mut result: u64 = 0; - for i in (start..end).rev() { - result = result << 1 | x.get_bit(i) as u64; - } - result -} diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs new file mode 100644 index 0000000000..36432718af --- /dev/null +++ b/library/core/src/num/dec2flt/number.rs @@ -0,0 +1,86 @@ +//! Representation of a float as the significant digits and exponent. + +use crate::num::dec2flt::float::RawFloat; +use crate::num::dec2flt::fpu::set_precision; + +#[rustfmt::skip] +const INT_POW10: [u64; 16] = [ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, +]; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Number { + pub exponent: i64, + pub mantissa: u64, + pub negative: bool, + pub many_digits: bool, +} + +impl Number { + /// Detect if the float can be accurately reconstructed from native floats. + fn is_fast_path(&self) -> bool { + F::MIN_EXPONENT_FAST_PATH <= self.exponent + && self.exponent <= F::MAX_EXPONENT_DISGUISED_FAST_PATH + && self.mantissa <= F::MAX_MANTISSA_FAST_PATH + && !self.many_digits + } + + /// The fast path algorithmn using machine-sized integers and floats. + /// + /// This is extracted into a separate function so that it can be attempted before constructing + /// a Decimal. This only works if both the mantissa and the exponent + /// can be exactly represented as a machine float, since IEE-754 guarantees + /// no rounding will occur. + /// + /// There is an exception: disguised fast-path cases, where we can shift + /// powers-of-10 from the exponent to the significant digits. + pub fn try_fast_path(&self) -> Option { + // The fast path crucially depends on arithmetic being rounded to the correct number of bits + // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision + // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit. + // The `set_precision` function takes care of setting the precision on architectures which + // require setting it by changing the global state (like the control word of the x87 FPU). + let _cw = set_precision::(); + + if self.is_fast_path::() { + let mut value = if self.exponent <= F::MAX_EXPONENT_FAST_PATH { + // normal fast path + let value = F::from_u64(self.mantissa); + if self.exponent < 0 { + value / F::pow10_fast_path((-self.exponent) as _) + } else { + value * F::pow10_fast_path(self.exponent as _) + } + } else { + // disguised fast path + let shift = self.exponent - F::MAX_EXPONENT_FAST_PATH; + let mantissa = self.mantissa.checked_mul(INT_POW10[shift as usize])?; + if mantissa > F::MAX_MANTISSA_FAST_PATH { + return None; + } + F::from_u64(mantissa) * F::pow10_fast_path(F::MAX_EXPONENT_FAST_PATH as _) + }; + if self.negative { + value = -value; + } + Some(value) + } else { + None + } + } +} diff --git a/library/core/src/num/dec2flt/parse.rs b/library/core/src/num/dec2flt/parse.rs index 858cc3c9b0..fa677bf512 100644 --- a/library/core/src/num/dec2flt/parse.rs +++ b/library/core/src/num/dec2flt/parse.rs @@ -1,121 +1,233 @@ -//! Validating and decomposing a decimal string of the form: -//! -//! `(digits | digits? '.'? digits?) (('e' | 'E') ('+' | '-')? digits)?` -//! -//! In other words, standard floating-point syntax, with two exceptions: No sign, and no -//! handling of "inf" and "NaN". These are handled by the driver function (super::dec2flt). -//! -//! Although recognizing valid inputs is relatively easy, this module also has to reject the -//! countless invalid variations, never panic, and perform numerous checks that the other -//! modules rely on to not panic (or overflow) in turn. -//! To make matters worse, all that happens in a single pass over the input. -//! So, be careful when modifying anything, and double-check with the other modules. -use self::ParseResult::{Invalid, ShortcutToInf, ShortcutToZero, Valid}; -use super::num; - -#[derive(Debug)] -pub enum Sign { - Positive, - Negative, +//! Functions to parse floating-point numbers. + +use crate::num::dec2flt::common::{is_8digits, AsciiStr, ByteSlice}; +use crate::num::dec2flt::float::RawFloat; +use crate::num::dec2flt::number::Number; + +const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000; + +/// Parse 8 digits, loaded as bytes in little-endian order. +/// +/// This uses the trick where every digit is in [0x030, 0x39], +/// and therefore can be parsed in 3 multiplications, much +/// faster than the normal 8. +/// +/// This is based off the algorithm described in "Fast numeric string to +/// int", available here: . +fn parse_8digits(mut v: u64) -> u64 { + const MASK: u64 = 0x0000_00FF_0000_00FF; + const MUL1: u64 = 0x000F_4240_0000_0064; + const MUL2: u64 = 0x0000_2710_0000_0001; + v -= 0x3030_3030_3030_3030; + v = (v * 10) + (v >> 8); // will not overflow, fits in 63 bits + let v1 = (v & MASK).wrapping_mul(MUL1); + let v2 = ((v >> 16) & MASK).wrapping_mul(MUL2); + ((v1.wrapping_add(v2) >> 32) as u32) as u64 } -#[derive(Debug, PartialEq, Eq)] -/// The interesting parts of a decimal string. -pub struct Decimal<'a> { - pub integral: &'a [u8], - pub fractional: &'a [u8], - /// The decimal exponent, guaranteed to have fewer than 18 decimal digits. - pub exp: i64, +/// Parse digits until a non-digit character is found. +fn try_parse_digits(s: &mut AsciiStr<'_>, x: &mut u64) { + // may cause overflows, to be handled later + s.parse_digits(|digit| { + *x = x.wrapping_mul(10).wrapping_add(digit as _); + }); } -impl<'a> Decimal<'a> { - pub fn new(integral: &'a [u8], fractional: &'a [u8], exp: i64) -> Decimal<'a> { - Decimal { integral, fractional, exp } +/// Parse up to 19 digits (the max that can be stored in a 64-bit integer). +fn try_parse_19digits(s: &mut AsciiStr<'_>, x: &mut u64) { + while *x < MIN_19DIGIT_INT { + if let Some(&c) = s.as_ref().first() { + let digit = c.wrapping_sub(b'0'); + if digit < 10 { + *x = (*x * 10) + digit as u64; // no overflows here + // SAFETY: cannot be empty + unsafe { + s.step(); + } + } else { + break; + } + } else { + break; + } } } -#[derive(Debug, PartialEq, Eq)] -pub enum ParseResult<'a> { - Valid(Decimal<'a>), - ShortcutToInf, - ShortcutToZero, - Invalid, +/// Try to parse 8 digits at a time, using an optimized algorithm. +fn try_parse_8digits(s: &mut AsciiStr<'_>, x: &mut u64) { + // may cause overflows, to be handled later + if let Some(v) = s.read_u64() { + if is_8digits(v) { + *x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(v)); + // SAFETY: already ensured the buffer was >= 8 bytes in read_u64. + unsafe { + s.step_by(8); + } + if let Some(v) = s.read_u64() { + if is_8digits(v) { + *x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(v)); + // SAFETY: already ensured the buffer was >= 8 bytes in try_read_u64. + unsafe { + s.step_by(8); + } + } + } + } + } } -/// Checks if the input string is a valid floating point number and if so, locate the integral -/// part, the fractional part, and the exponent in it. Does not handle signs. -pub fn parse_decimal(s: &str) -> ParseResult<'_> { - if s.is_empty() { - return Invalid; +/// Parse the scientific notation component of a float. +fn parse_scientific(s: &mut AsciiStr<'_>) -> Option { + let mut exponent = 0_i64; + let mut negative = false; + if let Some(&c) = s.as_ref().get(0) { + negative = c == b'-'; + if c == b'-' || c == b'+' { + // SAFETY: s cannot be empty + unsafe { + s.step(); + } + } } + if s.first_isdigit() { + s.parse_digits(|digit| { + // no overflows here, saturate well before overflow + if exponent < 0x10000 { + exponent = 10 * exponent + digit as i64; + } + }); + if negative { Some(-exponent) } else { Some(exponent) } + } else { + None + } +} - let s = s.as_bytes(); - let (integral, s) = eat_digits(s); +/// Parse a partial, non-special floating point number. +/// +/// This creates a representation of the float as the +/// significant digits and the decimal exponent. +fn parse_partial_number(s: &[u8], negative: bool) -> Option<(Number, usize)> { + let mut s = AsciiStr::new(s); + let start = s; + debug_assert!(!s.is_empty()); - match s.first() { - None => Valid(Decimal::new(integral, b"", 0)), - Some(&b'e' | &b'E') => { - if integral.is_empty() { - return Invalid; // No digits before 'e' - } + // parse initial digits before dot + let mut mantissa = 0_u64; + let digits_start = s; + try_parse_digits(&mut s, &mut mantissa); + let mut n_digits = s.offset_from(&digits_start); + + // handle dot with the following digits + let mut n_after_dot = 0; + let mut exponent = 0_i64; + let int_end = s; + if s.first_is(b'.') { + // SAFETY: s cannot be empty due to first_is + unsafe { s.step() }; + let before = s; + try_parse_8digits(&mut s, &mut mantissa); + try_parse_digits(&mut s, &mut mantissa); + n_after_dot = s.offset_from(&before); + exponent = -n_after_dot as i64; + } - parse_exp(integral, b"", &s[1..]) + n_digits += n_after_dot; + if n_digits == 0 { + return None; + } + + // handle scientific format + let mut exp_number = 0_i64; + if s.first_is2(b'e', b'E') { + // SAFETY: s cannot be empty + unsafe { + s.step(); } - Some(&b'.') => { - let (fractional, s) = eat_digits(&s[1..]); - if integral.is_empty() && fractional.is_empty() { - // We require at least a single digit before or after the point. - return Invalid; - } + // If None, we have no trailing digits after exponent, or an invalid float. + exp_number = parse_scientific(&mut s)?; + exponent += exp_number; + } - match s.first() { - None => Valid(Decimal::new(integral, fractional, 0)), - Some(&b'e' | &b'E') => parse_exp(integral, fractional, &s[1..]), - _ => Invalid, // Trailing junk after fractional part - } + let len = s.offset_from(&start) as _; + + // handle uncommon case with many digits + if n_digits <= 19 { + return Some((Number { exponent, mantissa, negative, many_digits: false }, len)); + } + + n_digits -= 19; + let mut many_digits = false; + let mut p = digits_start; + while p.first_is2(b'0', b'.') { + // SAFETY: p cannot be empty due to first_is2 + unsafe { + // '0' = b'.' + 2 + n_digits -= p.first_unchecked().saturating_sub(b'0' - 1) as isize; + p.step(); } - _ => Invalid, // Trailing junk after first digit string } -} + if n_digits > 0 { + // at this point we have more than 19 significant digits, let's try again + many_digits = true; + mantissa = 0; + let mut s = digits_start; + try_parse_19digits(&mut s, &mut mantissa); + exponent = if mantissa >= MIN_19DIGIT_INT { + // big int + int_end.offset_from(&s) + } else { + // SAFETY: the next byte must be present and be '.' + // We know this is true because we had more than 19 + // digits previously, so we overflowed a 64-bit integer, + // but parsing only the integral digits produced less + // than 19 digits. That means we must have a decimal + // point, and at least 1 fractional digit. + unsafe { s.step() }; + let before = s; + try_parse_19digits(&mut s, &mut mantissa); + -s.offset_from(&before) + } as i64; + // add back the explicit part + exponent += exp_number; + } -/// Carves off decimal digits up to the first non-digit character. -fn eat_digits(s: &[u8]) -> (&[u8], &[u8]) { - let pos = s.iter().position(|c| !c.is_ascii_digit()).unwrap_or(s.len()); - s.split_at(pos) + Some((Number { exponent, mantissa, negative, many_digits }, len)) } -/// Exponent extraction and error checking. -fn parse_exp<'a>(integral: &'a [u8], fractional: &'a [u8], rest: &'a [u8]) -> ParseResult<'a> { - let (sign, rest) = match rest.first() { - Some(&b'-') => (Sign::Negative, &rest[1..]), - Some(&b'+') => (Sign::Positive, &rest[1..]), - _ => (Sign::Positive, rest), - }; - let (mut number, trailing) = eat_digits(rest); - if !trailing.is_empty() { - return Invalid; // Trailing junk after exponent +/// Try to parse a non-special floating point number. +pub fn parse_number(s: &[u8], negative: bool) -> Option { + if let Some((float, rest)) = parse_partial_number(s, negative) { + if rest == s.len() { + return Some(float); + } } - if number.is_empty() { - return Invalid; // Empty exponent + None +} + +/// Parse a partial representation of a special, non-finite float. +fn parse_partial_inf_nan(s: &[u8]) -> Option<(F, usize)> { + fn parse_inf_rest(s: &[u8]) -> usize { + if s.len() >= 8 && s[3..].as_ref().eq_ignore_case(b"inity") { 8 } else { 3 } } - // At this point, we certainly have a valid string of digits. It may be too long to put into - // an `i64`, but if it's that huge, the input is certainly zero or infinity. Since each zero - // in the decimal digits only adjusts the exponent by +/- 1, at exp = 10^18 the input would - // have to be 17 exabyte (!) of zeros to get even remotely close to being finite. - // This is not exactly a use case we need to cater to. - while number.first() == Some(&b'0') { - number = &number[1..]; + if s.len() >= 3 { + if s.eq_ignore_case(b"nan") { + return Some((F::NAN, 3)); + } else if s.eq_ignore_case(b"inf") { + return Some((F::INFINITY, parse_inf_rest(s))); + } } - if number.len() >= 18 { - return match sign { - Sign::Positive => ShortcutToInf, - Sign::Negative => ShortcutToZero, - }; + None +} + +/// Try to parse a special, non-finite float. +pub fn parse_inf_nan(s: &[u8], negative: bool) -> Option { + if let Some((mut float, rest)) = parse_partial_inf_nan::(s) { + if rest == s.len() { + if negative { + float = -float; + } + return Some(float); + } } - let abs_exp = num::from_str_unchecked(number); - let e = match sign { - Sign::Positive => abs_exp as i64, - Sign::Negative => -(abs_exp as i64), - }; - Valid(Decimal::new(integral, fractional, e)) + None } diff --git a/library/core/src/num/dec2flt/rawfp.rs b/library/core/src/num/dec2flt/rawfp.rs deleted file mode 100644 index 0ab15b23e5..0000000000 --- a/library/core/src/num/dec2flt/rawfp.rs +++ /dev/null @@ -1,363 +0,0 @@ -//! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and needn't be handled. -//! Normal floating point numbers have a canonical representation as (frac, exp) such that the -//! value is 2exp * (1 + sum(frac[N-i] / 2i)) where N is the number of bits. -//! Subnormals are slightly different and weird, but the same principle applies. -//! -//! Here, however, we represent them as (sig, k) with f positive, such that the value is f * -//! 2e. Besides making the "hidden bit" explicit, this changes the exponent by the -//! so-called mantissa shift. -//! -//! Put another way, normally floats are written as (1) but here they are written as (2): -//! -//! 1. `1.101100...11 * 2^m` -//! 2. `1101100...11 * 2^n` -//! -//! We call (1) the **fractional representation** and (2) the **integral representation**. -//! -//! Many functions in this module only handle normal numbers. The dec2flt routines conservatively -//! take the universally-correct slow path (Algorithm M) for very small and very large numbers. -//! That algorithm needs only next_float() which does handle subnormals and zeros. -use crate::cmp::Ordering::{Equal, Greater, Less}; -use crate::convert::{TryFrom, TryInto}; -use crate::fmt::{Debug, LowerExp}; -use crate::num::dec2flt::num::{self, Big}; -use crate::num::dec2flt::table; -use crate::num::diy_float::Fp; -use crate::num::FpCategory; -use crate::num::FpCategory::{Infinite, Nan, Normal, Subnormal, Zero}; -use crate::ops::{Add, Div, Mul, Neg}; - -#[derive(Copy, Clone, Debug)] -pub struct Unpacked { - pub sig: u64, - pub k: i16, -} - -impl Unpacked { - pub fn new(sig: u64, k: i16) -> Self { - Unpacked { sig, k } - } -} - -/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`. -/// -/// See the parent module's doc comment for why this is necessary. -/// -/// Should **never ever** be implemented for other types or be used outside the dec2flt module. -pub trait RawFloat: - Copy + Debug + LowerExp + Mul + Div + Neg -{ - const INFINITY: Self; - const NAN: Self; - const ZERO: Self; - - /// Type used by `to_bits` and `from_bits`. - type Bits: Add + From + TryFrom; - - /// Performs a raw transmutation to an integer. - fn to_bits(self) -> Self::Bits; - - /// Performs a raw transmutation from an integer. - fn from_bits(v: Self::Bits) -> Self; - - /// Returns the category that this number falls into. - fn classify(self) -> FpCategory; - - /// Returns the mantissa, exponent and sign as integers. - fn integer_decode(self) -> (u64, i16, i8); - - /// Decodes the float. - fn unpack(self) -> Unpacked; - - /// Casts from a small integer that can be represented exactly. Panic if the integer can't be - /// represented, the other code in this module makes sure to never let that happen. - fn from_int(x: u64) -> Self; - - /// Gets the value 10e from a pre-computed table. - /// Panics for `e >= CEIL_LOG5_OF_MAX_SIG`. - fn short_fast_pow10(e: usize) -> Self; - - /// What the name says. It's easier to hard code than juggling intrinsics and - /// hoping LLVM constant folds it. - const CEIL_LOG5_OF_MAX_SIG: i16; - - // A conservative bound on the decimal digits of inputs that can't produce overflow or zero or - /// subnormals. Probably the decimal exponent of the maximum normal value, hence the name. - const MAX_NORMAL_DIGITS: usize; - - /// When the most significant decimal digit has a place value greater than this, the number - /// is certainly rounded to infinity. - const INF_CUTOFF: i64; - - /// When the most significant decimal digit has a place value less than this, the number - /// is certainly rounded to zero. - const ZERO_CUTOFF: i64; - - /// The number of bits in the exponent. - const EXP_BITS: u8; - - /// The number of bits in the significand, *including* the hidden bit. - const SIG_BITS: u8; - - /// The number of bits in the significand, *excluding* the hidden bit. - const EXPLICIT_SIG_BITS: u8; - - /// The maximum legal exponent in fractional representation. - const MAX_EXP: i16; - - /// The minimum legal exponent in fractional representation, excluding subnormals. - const MIN_EXP: i16; - - /// `MAX_EXP` for integral representation, i.e., with the shift applied. - const MAX_EXP_INT: i16; - - /// `MAX_EXP` encoded (i.e., with offset bias) - const MAX_ENCODED_EXP: i16; - - /// `MIN_EXP` for integral representation, i.e., with the shift applied. - const MIN_EXP_INT: i16; - - /// The maximum normalized significand in integral representation. - const MAX_SIG: u64; - - /// The minimal normalized significand in integral representation. - const MIN_SIG: u64; -} - -// Mostly a workaround for #34344. -macro_rules! other_constants { - ($type: ident) => { - const EXPLICIT_SIG_BITS: u8 = Self::SIG_BITS - 1; - const MAX_EXP: i16 = (1 << (Self::EXP_BITS - 1)) - 1; - const MIN_EXP: i16 = -::MAX_EXP + 1; - const MAX_EXP_INT: i16 = ::MAX_EXP - (Self::SIG_BITS as i16 - 1); - const MAX_ENCODED_EXP: i16 = (1 << Self::EXP_BITS) - 1; - const MIN_EXP_INT: i16 = ::MIN_EXP - (Self::SIG_BITS as i16 - 1); - const MAX_SIG: u64 = (1 << Self::SIG_BITS) - 1; - const MIN_SIG: u64 = 1 << (Self::SIG_BITS - 1); - - const INFINITY: Self = $type::INFINITY; - const NAN: Self = $type::NAN; - const ZERO: Self = 0.0; - }; -} - -impl RawFloat for f32 { - type Bits = u32; - - const SIG_BITS: u8 = 24; - const EXP_BITS: u8 = 8; - const CEIL_LOG5_OF_MAX_SIG: i16 = 11; - const MAX_NORMAL_DIGITS: usize = 35; - const INF_CUTOFF: i64 = 40; - const ZERO_CUTOFF: i64 = -48; - other_constants!(f32); - - /// Returns the mantissa, exponent and sign as integers. - fn integer_decode(self) -> (u64, i16, i8) { - let bits = self.to_bits(); - let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 }; - let mut exponent: i16 = ((bits >> 23) & 0xff) as i16; - let mantissa = - if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 }; - // Exponent bias + mantissa shift - exponent -= 127 + 23; - (mantissa as u64, exponent, sign) - } - - fn unpack(self) -> Unpacked { - let (sig, exp, _sig) = self.integer_decode(); - Unpacked::new(sig, exp) - } - - fn from_int(x: u64) -> f32 { - // rkruppe is uncertain whether `as` rounds correctly on all platforms. - debug_assert!(x as f32 == fp_to_float(Fp { f: x, e: 0 })); - x as f32 - } - - fn short_fast_pow10(e: usize) -> Self { - table::F32_SHORT_POWERS[e] - } - - fn classify(self) -> FpCategory { - self.classify() - } - fn to_bits(self) -> Self::Bits { - self.to_bits() - } - fn from_bits(v: Self::Bits) -> Self { - Self::from_bits(v) - } -} - -impl RawFloat for f64 { - type Bits = u64; - - const SIG_BITS: u8 = 53; - const EXP_BITS: u8 = 11; - const CEIL_LOG5_OF_MAX_SIG: i16 = 23; - const MAX_NORMAL_DIGITS: usize = 305; - const INF_CUTOFF: i64 = 310; - const ZERO_CUTOFF: i64 = -326; - other_constants!(f64); - - /// Returns the mantissa, exponent and sign as integers. - fn integer_decode(self) -> (u64, i16, i8) { - let bits = self.to_bits(); - let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; - let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; - let mantissa = if exponent == 0 { - (bits & 0xfffffffffffff) << 1 - } else { - (bits & 0xfffffffffffff) | 0x10000000000000 - }; - // Exponent bias + mantissa shift - exponent -= 1023 + 52; - (mantissa, exponent, sign) - } - - fn unpack(self) -> Unpacked { - let (sig, exp, _sig) = self.integer_decode(); - Unpacked::new(sig, exp) - } - - fn from_int(x: u64) -> f64 { - // rkruppe is uncertain whether `as` rounds correctly on all platforms. - debug_assert!(x as f64 == fp_to_float(Fp { f: x, e: 0 })); - x as f64 - } - - fn short_fast_pow10(e: usize) -> Self { - table::F64_SHORT_POWERS[e] - } - - fn classify(self) -> FpCategory { - self.classify() - } - fn to_bits(self) -> Self::Bits { - self.to_bits() - } - fn from_bits(v: Self::Bits) -> Self { - Self::from_bits(v) - } -} - -/// Converts an `Fp` to the closest machine float type. -/// Does not handle subnormal results. -pub fn fp_to_float(x: Fp) -> T { - let x = x.normalize(); - // x.f is 64 bit, so x.e has a mantissa shift of 63 - let e = x.e + 63; - if e > T::MAX_EXP { - panic!("fp_to_float: exponent {} too large", e) - } else if e > T::MIN_EXP { - encode_normal(round_normal::(x)) - } else { - panic!("fp_to_float: exponent {} too small", e) - } -} - -/// Round the 64-bit significand to T::SIG_BITS bits with half-to-even. -/// Does not handle exponent overflow. -pub fn round_normal(x: Fp) -> Unpacked { - let excess = 64 - T::SIG_BITS as i16; - let half: u64 = 1 << (excess - 1); - let (q, rem) = (x.f >> excess, x.f & ((1 << excess) - 1)); - assert_eq!(q << excess | rem, x.f); - // Adjust mantissa shift - let k = x.e + excess; - if rem < half { - Unpacked::new(q, k) - } else if rem == half && (q % 2) == 0 { - Unpacked::new(q, k) - } else if q == T::MAX_SIG { - Unpacked::new(T::MIN_SIG, k + 1) - } else { - Unpacked::new(q + 1, k) - } -} - -/// Inverse of `RawFloat::unpack()` for normalized numbers. -/// Panics if the significand or exponent are not valid for normalized numbers. -pub fn encode_normal(x: Unpacked) -> T { - debug_assert!( - T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG, - "encode_normal: significand not normalized" - ); - // Remove the hidden bit - let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS); - // Adjust the exponent for exponent bias and mantissa shift - let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16; - debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP, "encode_normal: exponent out of range"); - // Leave sign bit at 0 ("+"), our numbers are all positive - let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc; - T::from_bits(bits.try_into().unwrap_or_else(|_| unreachable!())) -} - -/// Construct a subnormal. A mantissa of 0 is allowed and constructs zero. -pub fn encode_subnormal(significand: u64) -> T { - assert!(significand < T::MIN_SIG, "encode_subnormal: not actually subnormal"); - // Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits. - T::from_bits(significand.try_into().unwrap_or_else(|_| unreachable!())) -} - -/// Approximate a bignum with an Fp. Rounds within 0.5 ULP with half-to-even. -pub fn big_to_fp(f: &Big) -> Fp { - let end = f.bit_length(); - assert!(end != 0, "big_to_fp: unexpectedly, input is zero"); - let start = end.saturating_sub(64); - let leading = num::get_bits(f, start, end); - // We cut off all bits prior to the index `start`, i.e., we effectively right-shift by - // an amount of `start`, so this is also the exponent we need. - let e = start as i16; - let rounded_down = Fp { f: leading, e }.normalize(); - // Round (half-to-even) depending on the truncated bits. - match num::compare_with_half_ulp(f, start) { - Less => rounded_down, - Equal if leading % 2 == 0 => rounded_down, - Equal | Greater => match leading.checked_add(1) { - Some(f) => Fp { f, e }.normalize(), - None => Fp { f: 1 << 63, e: e + 1 }, - }, - } -} - -/// Finds the largest floating point number strictly smaller than the argument. -/// Does not handle subnormals, zero, or exponent underflow. -pub fn prev_float(x: T) -> T { - match x.classify() { - Infinite => panic!("prev_float: argument is infinite"), - Nan => panic!("prev_float: argument is NaN"), - Subnormal => panic!("prev_float: argument is subnormal"), - Zero => panic!("prev_float: argument is zero"), - Normal => { - let Unpacked { sig, k } = x.unpack(); - if sig == T::MIN_SIG { - encode_normal(Unpacked::new(T::MAX_SIG, k - 1)) - } else { - encode_normal(Unpacked::new(sig - 1, k)) - } - } - } -} - -// Find the smallest floating point number strictly larger than the argument. -// This operation is saturating, i.e., next_float(inf) == inf. -// Unlike most code in this module, this function does handle zero, subnormals, and infinities. -// However, like all other code here, it does not deal with NaN and negative numbers. -pub fn next_float(x: T) -> T { - match x.classify() { - Nan => panic!("next_float: argument is NaN"), - Infinite => T::INFINITY, - // This seems too good to be true, but it works. - // 0.0 is encoded as the all-zero word. Subnormals are 0x000m...m where m is the mantissa. - // In particular, the smallest subnormal is 0x0...01 and the largest is 0x000F...F. - // The smallest normal number is 0x0010...0, so this corner case works as well. - // If the increment overflows the mantissa, the carry bit increments the exponent as we - // want, and the mantissa bits become zero. Because of the hidden bit convention, this - // too is exactly what we want! - // Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY. - Zero | Subnormal | Normal => T::from_bits(x.to_bits() + T::Bits::from(1u8)), - } -} diff --git a/library/core/src/num/dec2flt/slow.rs b/library/core/src/num/dec2flt/slow.rs new file mode 100644 index 0000000000..bf1044033e --- /dev/null +++ b/library/core/src/num/dec2flt/slow.rs @@ -0,0 +1,109 @@ +//! Slow, fallback algorithm for cases the Eisel-Lemire algorithm cannot round. + +use crate::num::dec2flt::common::BiasedFp; +use crate::num::dec2flt::decimal::{parse_decimal, Decimal}; +use crate::num::dec2flt::float::RawFloat; + +/// Parse the significant digits and biased, binary exponent of a float. +/// +/// This is a fallback algorithm that uses a big-integer representation +/// of the float, and therefore is considerably slower than faster +/// approximations. However, it will always determine how to round +/// the significant digits to the nearest machine float, allowing +/// use to handle near half-way cases. +/// +/// Near half-way cases are halfway between two consecutive machine floats. +/// For example, the float `16777217.0` has a bitwise representation of +/// `100000000000000000000000 1`. Rounding to a single-precision float, +/// the trailing `1` is truncated. Using round-nearest, tie-even, any +/// value above `16777217.0` must be rounded up to `16777218.0`, while +/// any value before or equal to `16777217.0` must be rounded down +/// to `16777216.0`. These near-halfway conversions therefore may require +/// a large number of digits to unambiguously determine how to round. +/// +/// The algorithms described here are based on "Processing Long Numbers Quickly", +/// available here: . +pub(crate) fn parse_long_mantissa(s: &[u8]) -> BiasedFp { + const MAX_SHIFT: usize = 60; + const NUM_POWERS: usize = 19; + const POWERS: [u8; 19] = + [0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59]; + + let get_shift = |n| { + if n < NUM_POWERS { POWERS[n] as usize } else { MAX_SHIFT } + }; + + let fp_zero = BiasedFp::zero_pow2(0); + let fp_inf = BiasedFp::zero_pow2(F::INFINITE_POWER); + + let mut d = parse_decimal(s); + + // Short-circuit if the value can only be a literal 0 or infinity. + if d.num_digits == 0 || d.decimal_point < -324 { + return fp_zero; + } else if d.decimal_point >= 310 { + return fp_inf; + } + let mut exp2 = 0_i32; + // Shift right toward (1/2 ... 1]. + while d.decimal_point > 0 { + let n = d.decimal_point as usize; + let shift = get_shift(n); + d.right_shift(shift); + if d.decimal_point < -Decimal::DECIMAL_POINT_RANGE { + return fp_zero; + } + exp2 += shift as i32; + } + // Shift left toward (1/2 ... 1]. + while d.decimal_point <= 0 { + let shift = if d.decimal_point == 0 { + match d.digits[0] { + digit if digit >= 5 => break, + 0 | 1 => 2, + _ => 1, + } + } else { + get_shift((-d.decimal_point) as _) + }; + d.left_shift(shift); + if d.decimal_point > Decimal::DECIMAL_POINT_RANGE { + return fp_inf; + } + exp2 -= shift as i32; + } + // We are now in the range [1/2 ... 1] but the binary format uses [1 ... 2]. + exp2 -= 1; + while (F::MINIMUM_EXPONENT + 1) > exp2 { + let mut n = ((F::MINIMUM_EXPONENT + 1) - exp2) as usize; + if n > MAX_SHIFT { + n = MAX_SHIFT; + } + d.right_shift(n); + exp2 += n as i32; + } + if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER { + return fp_inf; + } + // Shift the decimal to the hidden bit, and then round the value + // to get the high mantissa+1 bits. + d.left_shift(F::MANTISSA_EXPLICIT_BITS + 1); + let mut mantissa = d.round(); + if mantissa >= (1_u64 << (F::MANTISSA_EXPLICIT_BITS + 1)) { + // Rounding up overflowed to the carry bit, need to + // shift back to the hidden bit. + d.right_shift(1); + exp2 += 1; + mantissa = d.round(); + if (exp2 - F::MINIMUM_EXPONENT) >= F::INFINITE_POWER { + return fp_inf; + } + } + let mut power2 = exp2 - F::MINIMUM_EXPONENT; + if mantissa < (1_u64 << F::MANTISSA_EXPLICIT_BITS) { + power2 -= 1; + } + // Zero out all the bits above the explicit mantissa bits. + mantissa &= (1_u64 << F::MANTISSA_EXPLICIT_BITS) - 1; + BiasedFp { f: mantissa, e: power2 } +} diff --git a/library/core/src/num/dec2flt/table.rs b/library/core/src/num/dec2flt/table.rs index 97b497e81e..4856074a62 100644 --- a/library/core/src/num/dec2flt/table.rs +++ b/library/core/src/num/dec2flt/table.rs @@ -1,1277 +1,670 @@ -//! Tables of approximations of powers of ten. +//! Pre-computed tables powers-of-5 for extended-precision representations. +//! +//! These tables enable fast scaling of the significant digits +//! of a float to the decimal exponent, with minimal rounding +//! errors, in a 128 or 192-bit representation. +//! //! DO NOT MODIFY: Generated by `src/etc/dec2flt_table.py` -pub const MIN_E: i16 = -305; -pub const MAX_E: i16 = 305; +pub const SMALLEST_POWER_OF_FIVE: i32 = -342; +pub const LARGEST_POWER_OF_FIVE: i32 = 308; +pub const N_POWERS_OF_FIVE: usize = (LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize; +// Use static to avoid long compile times: Rust compiler errors +// can have the entire table compiled multiple times, and then +// emit code multiple times, even if it's stripped out in +// the final binary. #[rustfmt::skip] -pub static POWERS: ([u64; 611], [i16; 611]) = ( - [ - 0xe0b62e2929aba83c, - 0x8c71dcd9ba0b4926, - 0xaf8e5410288e1b6f, - 0xdb71e91432b1a24b, - 0x892731ac9faf056f, - 0xab70fe17c79ac6ca, - 0xd64d3d9db981787d, - 0x85f0468293f0eb4e, - 0xa76c582338ed2622, - 0xd1476e2c07286faa, - 0x82cca4db847945ca, - 0xa37fce126597973d, - 0xcc5fc196fefd7d0c, - 0xff77b1fcbebcdc4f, - 0x9faacf3df73609b1, - 0xc795830d75038c1e, - 0xf97ae3d0d2446f25, - 0x9becce62836ac577, - 0xc2e801fb244576d5, - 0xf3a20279ed56d48a, - 0x9845418c345644d7, - 0xbe5691ef416bd60c, - 0xedec366b11c6cb8f, - 0x94b3a202eb1c3f39, - 0xb9e08a83a5e34f08, - 0xe858ad248f5c22ca, - 0x91376c36d99995be, - 0xb58547448ffffb2e, - 0xe2e69915b3fff9f9, - 0x8dd01fad907ffc3c, - 0xb1442798f49ffb4b, - 0xdd95317f31c7fa1d, - 0x8a7d3eef7f1cfc52, - 0xad1c8eab5ee43b67, - 0xd863b256369d4a41, - 0x873e4f75e2224e68, - 0xa90de3535aaae202, - 0xd3515c2831559a83, - 0x8412d9991ed58092, - 0xa5178fff668ae0b6, - 0xce5d73ff402d98e4, - 0x80fa687f881c7f8e, - 0xa139029f6a239f72, - 0xc987434744ac874f, - 0xfbe9141915d7a922, - 0x9d71ac8fada6c9b5, - 0xc4ce17b399107c23, - 0xf6019da07f549b2b, - 0x99c102844f94e0fb, - 0xc0314325637a193a, - 0xf03d93eebc589f88, - 0x96267c7535b763b5, - 0xbbb01b9283253ca3, - 0xea9c227723ee8bcb, - 0x92a1958a7675175f, - 0xb749faed14125d37, - 0xe51c79a85916f485, - 0x8f31cc0937ae58d3, - 0xb2fe3f0b8599ef08, - 0xdfbdcece67006ac9, - 0x8bd6a141006042be, - 0xaecc49914078536d, - 0xda7f5bf590966849, - 0x888f99797a5e012d, - 0xaab37fd7d8f58179, - 0xd5605fcdcf32e1d7, - 0x855c3be0a17fcd26, - 0xa6b34ad8c9dfc070, - 0xd0601d8efc57b08c, - 0x823c12795db6ce57, - 0xa2cb1717b52481ed, - 0xcb7ddcdda26da269, - 0xfe5d54150b090b03, - 0x9efa548d26e5a6e2, - 0xc6b8e9b0709f109a, - 0xf867241c8cc6d4c1, - 0x9b407691d7fc44f8, - 0xc21094364dfb5637, - 0xf294b943e17a2bc4, - 0x979cf3ca6cec5b5b, - 0xbd8430bd08277231, - 0xece53cec4a314ebe, - 0x940f4613ae5ed137, - 0xb913179899f68584, - 0xe757dd7ec07426e5, - 0x9096ea6f3848984f, - 0xb4bca50b065abe63, - 0xe1ebce4dc7f16dfc, - 0x8d3360f09cf6e4bd, - 0xb080392cc4349ded, - 0xdca04777f541c568, - 0x89e42caaf9491b61, - 0xac5d37d5b79b6239, - 0xd77485cb25823ac7, - 0x86a8d39ef77164bd, - 0xa8530886b54dbdec, - 0xd267caa862a12d67, - 0x8380dea93da4bc60, - 0xa46116538d0deb78, - 0xcd795be870516656, - 0x806bd9714632dff6, - 0xa086cfcd97bf97f4, - 0xc8a883c0fdaf7df0, - 0xfad2a4b13d1b5d6c, - 0x9cc3a6eec6311a64, - 0xc3f490aa77bd60fd, - 0xf4f1b4d515acb93c, - 0x991711052d8bf3c5, - 0xbf5cd54678eef0b7, - 0xef340a98172aace5, - 0x9580869f0e7aac0f, - 0xbae0a846d2195713, - 0xe998d258869facd7, - 0x91ff83775423cc06, - 0xb67f6455292cbf08, - 0xe41f3d6a7377eeca, - 0x8e938662882af53e, - 0xb23867fb2a35b28e, - 0xdec681f9f4c31f31, - 0x8b3c113c38f9f37f, - 0xae0b158b4738705f, - 0xd98ddaee19068c76, - 0x87f8a8d4cfa417ca, - 0xa9f6d30a038d1dbc, - 0xd47487cc8470652b, - 0x84c8d4dfd2c63f3b, - 0xa5fb0a17c777cf0a, - 0xcf79cc9db955c2cc, - 0x81ac1fe293d599c0, - 0xa21727db38cb0030, - 0xca9cf1d206fdc03c, - 0xfd442e4688bd304b, - 0x9e4a9cec15763e2f, - 0xc5dd44271ad3cdba, - 0xf7549530e188c129, - 0x9a94dd3e8cf578ba, - 0xc13a148e3032d6e8, - 0xf18899b1bc3f8ca2, - 0x96f5600f15a7b7e5, - 0xbcb2b812db11a5de, - 0xebdf661791d60f56, - 0x936b9fcebb25c996, - 0xb84687c269ef3bfb, - 0xe65829b3046b0afa, - 0x8ff71a0fe2c2e6dc, - 0xb3f4e093db73a093, - 0xe0f218b8d25088b8, - 0x8c974f7383725573, - 0xafbd2350644eead0, - 0xdbac6c247d62a584, - 0x894bc396ce5da772, - 0xab9eb47c81f5114f, - 0xd686619ba27255a3, - 0x8613fd0145877586, - 0xa798fc4196e952e7, - 0xd17f3b51fca3a7a1, - 0x82ef85133de648c5, - 0xa3ab66580d5fdaf6, - 0xcc963fee10b7d1b3, - 0xffbbcfe994e5c620, - 0x9fd561f1fd0f9bd4, - 0xc7caba6e7c5382c9, - 0xf9bd690a1b68637b, - 0x9c1661a651213e2d, - 0xc31bfa0fe5698db8, - 0xf3e2f893dec3f126, - 0x986ddb5c6b3a76b8, - 0xbe89523386091466, - 0xee2ba6c0678b597f, - 0x94db483840b717f0, - 0xba121a4650e4ddec, - 0xe896a0d7e51e1566, - 0x915e2486ef32cd60, - 0xb5b5ada8aaff80b8, - 0xe3231912d5bf60e6, - 0x8df5efabc5979c90, - 0xb1736b96b6fd83b4, - 0xddd0467c64bce4a1, - 0x8aa22c0dbef60ee4, - 0xad4ab7112eb3929e, - 0xd89d64d57a607745, - 0x87625f056c7c4a8b, - 0xa93af6c6c79b5d2e, - 0xd389b47879823479, - 0x843610cb4bf160cc, - 0xa54394fe1eedb8ff, - 0xce947a3da6a9273e, - 0x811ccc668829b887, - 0xa163ff802a3426a9, - 0xc9bcff6034c13053, - 0xfc2c3f3841f17c68, - 0x9d9ba7832936edc1, - 0xc5029163f384a931, - 0xf64335bcf065d37d, - 0x99ea0196163fa42e, - 0xc06481fb9bcf8d3a, - 0xf07da27a82c37088, - 0x964e858c91ba2655, - 0xbbe226efb628afeb, - 0xeadab0aba3b2dbe5, - 0x92c8ae6b464fc96f, - 0xb77ada0617e3bbcb, - 0xe55990879ddcaabe, - 0x8f57fa54c2a9eab7, - 0xb32df8e9f3546564, - 0xdff9772470297ebd, - 0x8bfbea76c619ef36, - 0xaefae51477a06b04, - 0xdab99e59958885c5, - 0x88b402f7fd75539b, - 0xaae103b5fcd2a882, - 0xd59944a37c0752a2, - 0x857fcae62d8493a5, - 0xa6dfbd9fb8e5b88f, - 0xd097ad07a71f26b2, - 0x825ecc24c8737830, - 0xa2f67f2dfa90563b, - 0xcbb41ef979346bca, - 0xfea126b7d78186bd, - 0x9f24b832e6b0f436, - 0xc6ede63fa05d3144, - 0xf8a95fcf88747d94, - 0x9b69dbe1b548ce7d, - 0xc24452da229b021c, - 0xf2d56790ab41c2a3, - 0x97c560ba6b0919a6, - 0xbdb6b8e905cb600f, - 0xed246723473e3813, - 0x9436c0760c86e30c, - 0xb94470938fa89bcf, - 0xe7958cb87392c2c3, - 0x90bd77f3483bb9ba, - 0xb4ecd5f01a4aa828, - 0xe2280b6c20dd5232, - 0x8d590723948a535f, - 0xb0af48ec79ace837, - 0xdcdb1b2798182245, - 0x8a08f0f8bf0f156b, - 0xac8b2d36eed2dac6, - 0xd7adf884aa879177, - 0x86ccbb52ea94baeb, - 0xa87fea27a539e9a5, - 0xd29fe4b18e88640f, - 0x83a3eeeef9153e89, - 0xa48ceaaab75a8e2b, - 0xcdb02555653131b6, - 0x808e17555f3ebf12, - 0xa0b19d2ab70e6ed6, - 0xc8de047564d20a8c, - 0xfb158592be068d2f, - 0x9ced737bb6c4183d, - 0xc428d05aa4751e4d, - 0xf53304714d9265e0, - 0x993fe2c6d07b7fac, - 0xbf8fdb78849a5f97, - 0xef73d256a5c0f77d, - 0x95a8637627989aae, - 0xbb127c53b17ec159, - 0xe9d71b689dde71b0, - 0x9226712162ab070e, - 0xb6b00d69bb55c8d1, - 0xe45c10c42a2b3b06, - 0x8eb98a7a9a5b04e3, - 0xb267ed1940f1c61c, - 0xdf01e85f912e37a3, - 0x8b61313bbabce2c6, - 0xae397d8aa96c1b78, - 0xd9c7dced53c72256, - 0x881cea14545c7575, - 0xaa242499697392d3, - 0xd4ad2dbfc3d07788, - 0x84ec3c97da624ab5, - 0xa6274bbdd0fadd62, - 0xcfb11ead453994ba, - 0x81ceb32c4b43fcf5, - 0xa2425ff75e14fc32, - 0xcad2f7f5359a3b3e, - 0xfd87b5f28300ca0e, - 0x9e74d1b791e07e48, - 0xc612062576589ddb, - 0xf79687aed3eec551, - 0x9abe14cd44753b53, - 0xc16d9a0095928a27, - 0xf1c90080baf72cb1, - 0x971da05074da7bef, - 0xbce5086492111aeb, - 0xec1e4a7db69561a5, - 0x9392ee8e921d5d07, - 0xb877aa3236a4b449, - 0xe69594bec44de15b, - 0x901d7cf73ab0acd9, - 0xb424dc35095cd80f, - 0xe12e13424bb40e13, - 0x8cbccc096f5088cc, - 0xafebff0bcb24aaff, - 0xdbe6fecebdedd5bf, - 0x89705f4136b4a597, - 0xabcc77118461cefd, - 0xd6bf94d5e57a42bc, - 0x8637bd05af6c69b6, - 0xa7c5ac471b478423, - 0xd1b71758e219652c, - 0x83126e978d4fdf3b, - 0xa3d70a3d70a3d70a, - 0xcccccccccccccccd, - 0x8000000000000000, - 0xa000000000000000, - 0xc800000000000000, - 0xfa00000000000000, - 0x9c40000000000000, - 0xc350000000000000, - 0xf424000000000000, - 0x9896800000000000, - 0xbebc200000000000, - 0xee6b280000000000, - 0x9502f90000000000, - 0xba43b74000000000, - 0xe8d4a51000000000, - 0x9184e72a00000000, - 0xb5e620f480000000, - 0xe35fa931a0000000, - 0x8e1bc9bf04000000, - 0xb1a2bc2ec5000000, - 0xde0b6b3a76400000, - 0x8ac7230489e80000, - 0xad78ebc5ac620000, - 0xd8d726b7177a8000, - 0x878678326eac9000, - 0xa968163f0a57b400, - 0xd3c21bcecceda100, - 0x84595161401484a0, - 0xa56fa5b99019a5c8, - 0xcecb8f27f4200f3a, - 0x813f3978f8940984, - 0xa18f07d736b90be5, - 0xc9f2c9cd04674edf, - 0xfc6f7c4045812296, - 0x9dc5ada82b70b59e, - 0xc5371912364ce305, - 0xf684df56c3e01bc7, - 0x9a130b963a6c115c, - 0xc097ce7bc90715b3, - 0xf0bdc21abb48db20, - 0x96769950b50d88f4, - 0xbc143fa4e250eb31, - 0xeb194f8e1ae525fd, - 0x92efd1b8d0cf37be, - 0xb7abc627050305ae, - 0xe596b7b0c643c719, - 0x8f7e32ce7bea5c70, - 0xb35dbf821ae4f38c, - 0xe0352f62a19e306f, - 0x8c213d9da502de45, - 0xaf298d050e4395d7, - 0xdaf3f04651d47b4c, - 0x88d8762bf324cd10, - 0xab0e93b6efee0054, - 0xd5d238a4abe98068, - 0x85a36366eb71f041, - 0xa70c3c40a64e6c52, - 0xd0cf4b50cfe20766, - 0x82818f1281ed44a0, - 0xa321f2d7226895c8, - 0xcbea6f8ceb02bb3a, - 0xfee50b7025c36a08, - 0x9f4f2726179a2245, - 0xc722f0ef9d80aad6, - 0xf8ebad2b84e0d58c, - 0x9b934c3b330c8577, - 0xc2781f49ffcfa6d5, - 0xf316271c7fc3908b, - 0x97edd871cfda3a57, - 0xbde94e8e43d0c8ec, - 0xed63a231d4c4fb27, - 0x945e455f24fb1cf9, - 0xb975d6b6ee39e437, - 0xe7d34c64a9c85d44, - 0x90e40fbeea1d3a4b, - 0xb51d13aea4a488dd, - 0xe264589a4dcdab15, - 0x8d7eb76070a08aed, - 0xb0de65388cc8ada8, - 0xdd15fe86affad912, - 0x8a2dbf142dfcc7ab, - 0xacb92ed9397bf996, - 0xd7e77a8f87daf7fc, - 0x86f0ac99b4e8dafd, - 0xa8acd7c0222311bd, - 0xd2d80db02aabd62c, - 0x83c7088e1aab65db, - 0xa4b8cab1a1563f52, - 0xcde6fd5e09abcf27, - 0x80b05e5ac60b6178, - 0xa0dc75f1778e39d6, - 0xc913936dd571c84c, - 0xfb5878494ace3a5f, - 0x9d174b2dcec0e47b, - 0xc45d1df942711d9a, - 0xf5746577930d6501, - 0x9968bf6abbe85f20, - 0xbfc2ef456ae276e9, - 0xefb3ab16c59b14a3, - 0x95d04aee3b80ece6, - 0xbb445da9ca61281f, - 0xea1575143cf97227, - 0x924d692ca61be758, - 0xb6e0c377cfa2e12e, - 0xe498f455c38b997a, - 0x8edf98b59a373fec, - 0xb2977ee300c50fe7, - 0xdf3d5e9bc0f653e1, - 0x8b865b215899f46d, - 0xae67f1e9aec07188, - 0xda01ee641a708dea, - 0x884134fe908658b2, - 0xaa51823e34a7eedf, - 0xd4e5e2cdc1d1ea96, - 0x850fadc09923329e, - 0xa6539930bf6bff46, - 0xcfe87f7cef46ff17, - 0x81f14fae158c5f6e, - 0xa26da3999aef774a, - 0xcb090c8001ab551c, - 0xfdcb4fa002162a63, - 0x9e9f11c4014dda7e, - 0xc646d63501a1511e, - 0xf7d88bc24209a565, - 0x9ae757596946075f, - 0xc1a12d2fc3978937, - 0xf209787bb47d6b85, - 0x9745eb4d50ce6333, - 0xbd176620a501fc00, - 0xec5d3fa8ce427b00, - 0x93ba47c980e98ce0, - 0xb8a8d9bbe123f018, - 0xe6d3102ad96cec1e, - 0x9043ea1ac7e41393, - 0xb454e4a179dd1877, - 0xe16a1dc9d8545e95, - 0x8ce2529e2734bb1d, - 0xb01ae745b101e9e4, - 0xdc21a1171d42645d, - 0x899504ae72497eba, - 0xabfa45da0edbde69, - 0xd6f8d7509292d603, - 0x865b86925b9bc5c2, - 0xa7f26836f282b733, - 0xd1ef0244af2364ff, - 0x8335616aed761f1f, - 0xa402b9c5a8d3a6e7, - 0xcd036837130890a1, - 0x802221226be55a65, - 0xa02aa96b06deb0fe, - 0xc83553c5c8965d3d, - 0xfa42a8b73abbf48d, - 0x9c69a97284b578d8, - 0xc38413cf25e2d70e, - 0xf46518c2ef5b8cd1, - 0x98bf2f79d5993803, - 0xbeeefb584aff8604, - 0xeeaaba2e5dbf6785, - 0x952ab45cfa97a0b3, - 0xba756174393d88e0, - 0xe912b9d1478ceb17, - 0x91abb422ccb812ef, - 0xb616a12b7fe617aa, - 0xe39c49765fdf9d95, - 0x8e41ade9fbebc27d, - 0xb1d219647ae6b31c, - 0xde469fbd99a05fe3, - 0x8aec23d680043bee, - 0xada72ccc20054aea, - 0xd910f7ff28069da4, - 0x87aa9aff79042287, - 0xa99541bf57452b28, - 0xd3fa922f2d1675f2, - 0x847c9b5d7c2e09b7, - 0xa59bc234db398c25, - 0xcf02b2c21207ef2f, - 0x8161afb94b44f57d, - 0xa1ba1ba79e1632dc, - 0xca28a291859bbf93, - 0xfcb2cb35e702af78, - 0x9defbf01b061adab, - 0xc56baec21c7a1916, - 0xf6c69a72a3989f5c, - 0x9a3c2087a63f6399, - 0xc0cb28a98fcf3c80, - 0xf0fdf2d3f3c30b9f, - 0x969eb7c47859e744, - 0xbc4665b596706115, - 0xeb57ff22fc0c795a, - 0x9316ff75dd87cbd8, - 0xb7dcbf5354e9bece, - 0xe5d3ef282a242e82, - 0x8fa475791a569d11, - 0xb38d92d760ec4455, - 0xe070f78d3927556b, - 0x8c469ab843b89563, - 0xaf58416654a6babb, - 0xdb2e51bfe9d0696a, - 0x88fcf317f22241e2, - 0xab3c2fddeeaad25b, - 0xd60b3bd56a5586f2, - 0x85c7056562757457, - 0xa738c6bebb12d16d, - 0xd106f86e69d785c8, - 0x82a45b450226b39d, - 0xa34d721642b06084, - 0xcc20ce9bd35c78a5, - 0xff290242c83396ce, - 0x9f79a169bd203e41, - 0xc75809c42c684dd1, - 0xf92e0c3537826146, - 0x9bbcc7a142b17ccc, - 0xc2abf989935ddbfe, - 0xf356f7ebf83552fe, - 0x98165af37b2153df, - 0xbe1bf1b059e9a8d6, - 0xeda2ee1c7064130c, - 0x9485d4d1c63e8be8, - 0xb9a74a0637ce2ee1, - 0xe8111c87c5c1ba9a, - 0x910ab1d4db9914a0, - 0xb54d5e4a127f59c8, - 0xe2a0b5dc971f303a, - 0x8da471a9de737e24, - 0xb10d8e1456105dad, - 0xdd50f1996b947519, - 0x8a5296ffe33cc930, - 0xace73cbfdc0bfb7b, - 0xd8210befd30efa5a, - 0x8714a775e3e95c78, - 0xa8d9d1535ce3b396, - 0xd31045a8341ca07c, - 0x83ea2b892091e44e, - 0xa4e4b66b68b65d61, - 0xce1de40642e3f4b9, - 0x80d2ae83e9ce78f4, - 0xa1075a24e4421731, - 0xc94930ae1d529cfd, - 0xfb9b7cd9a4a7443c, - 0x9d412e0806e88aa6, - 0xc491798a08a2ad4f, - 0xf5b5d7ec8acb58a3, - 0x9991a6f3d6bf1766, - 0xbff610b0cc6edd3f, - 0xeff394dcff8a948f, - 0x95f83d0a1fb69cd9, - 0xbb764c4ca7a44410, - 0xea53df5fd18d5514, - 0x92746b9be2f8552c, - 0xb7118682dbb66a77, - 0xe4d5e82392a40515, - 0x8f05b1163ba6832d, - 0xb2c71d5bca9023f8, - 0xdf78e4b2bd342cf7, - 0x8bab8eefb6409c1a, - 0xae9672aba3d0c321, - 0xda3c0f568cc4f3e9, - 0x8865899617fb1871, - 0xaa7eebfb9df9de8e, - 0xd51ea6fa85785631, - 0x8533285c936b35df, - 0xa67ff273b8460357, - 0xd01fef10a657842c, - 0x8213f56a67f6b29c, - 0xa298f2c501f45f43, - 0xcb3f2f7642717713, - 0xfe0efb53d30dd4d8, - 0x9ec95d1463e8a507, - 0xc67bb4597ce2ce49, - 0xf81aa16fdc1b81db, - 0x9b10a4e5e9913129, - 0xc1d4ce1f63f57d73, - 0xf24a01a73cf2dcd0, - 0x976e41088617ca02, - 0xbd49d14aa79dbc82, - 0xec9c459d51852ba3, - 0x93e1ab8252f33b46, - 0xb8da1662e7b00a17, - 0xe7109bfba19c0c9d, - 0x906a617d450187e2, - 0xb484f9dc9641e9db, - 0xe1a63853bbd26451, - 0x8d07e33455637eb3, - 0xb049dc016abc5e60, - 0xdc5c5301c56b75f7, - 0x89b9b3e11b6329bb, - 0xac2820d9623bf429, - 0xd732290fbacaf134, - 0x867f59a9d4bed6c0, - 0xa81f301449ee8c70, - 0xd226fc195c6a2f8c, - 0x83585d8fd9c25db8, - 0xa42e74f3d032f526, - 0xcd3a1230c43fb26f, - 0x80444b5e7aa7cf85, - 0xa0555e361951c367, - 0xc86ab5c39fa63441, - 0xfa856334878fc151, - 0x9c935e00d4b9d8d2, - 0xc3b8358109e84f07, - 0xf4a642e14c6262c9, - 0x98e7e9cccfbd7dbe, - 0xbf21e44003acdd2d, - 0xeeea5d5004981478, - 0x95527a5202df0ccb, - 0xbaa718e68396cffe, - 0xe950df20247c83fd, - 0x91d28b7416cdd27e, - ], - [ - -1077, - -1073, - -1070, - -1067, - -1063, - -1060, - -1057, - -1053, - -1050, - -1047, - -1043, - -1040, - -1037, - -1034, - -1030, - -1027, - -1024, - -1020, - -1017, - -1014, - -1010, - -1007, - -1004, - -1000, - -997, - -994, - -990, - -987, - -984, - -980, - -977, - -974, - -970, - -967, - -964, - -960, - -957, - -954, - -950, - -947, - -944, - -940, - -937, - -934, - -931, - -927, - -924, - -921, - -917, - -914, - -911, - -907, - -904, - -901, - -897, - -894, - -891, - -887, - -884, - -881, - -877, - -874, - -871, - -867, - -864, - -861, - -857, - -854, - -851, - -847, - -844, - -841, - -838, - -834, - -831, - -828, - -824, - -821, - -818, - -814, - -811, - -808, - -804, - -801, - -798, - -794, - -791, - -788, - -784, - -781, - -778, - -774, - -771, - -768, - -764, - -761, - -758, - -754, - -751, - -748, - -744, - -741, - -738, - -735, - -731, - -728, - -725, - -721, - -718, - -715, - -711, - -708, - -705, - -701, - -698, - -695, - -691, - -688, - -685, - -681, - -678, - -675, - -671, - -668, - -665, - -661, - -658, - -655, - -651, - -648, - -645, - -642, - -638, - -635, - -632, - -628, - -625, - -622, - -618, - -615, - -612, - -608, - -605, - -602, - -598, - -595, - -592, - -588, - -585, - -582, - -578, - -575, - -572, - -568, - -565, - -562, - -558, - -555, - -552, - -549, - -545, - -542, - -539, - -535, - -532, - -529, - -525, - -522, - -519, - -515, - -512, - -509, - -505, - -502, - -499, - -495, - -492, - -489, - -485, - -482, - -479, - -475, - -472, - -469, - -465, - -462, - -459, - -455, - -452, - -449, - -446, - -442, - -439, - -436, - -432, - -429, - -426, - -422, - -419, - -416, - -412, - -409, - -406, - -402, - -399, - -396, - -392, - -389, - -386, - -382, - -379, - -376, - -372, - -369, - -366, - -362, - -359, - -356, - -353, - -349, - -346, - -343, - -339, - -336, - -333, - -329, - -326, - -323, - -319, - -316, - -313, - -309, - -306, - -303, - -299, - -296, - -293, - -289, - -286, - -283, - -279, - -276, - -273, - -269, - -266, - -263, - -259, - -256, - -253, - -250, - -246, - -243, - -240, - -236, - -233, - -230, - -226, - -223, - -220, - -216, - -213, - -210, - -206, - -203, - -200, - -196, - -193, - -190, - -186, - -183, - -180, - -176, - -173, - -170, - -166, - -163, - -160, - -157, - -153, - -150, - -147, - -143, - -140, - -137, - -133, - -130, - -127, - -123, - -120, - -117, - -113, - -110, - -107, - -103, - -100, - -97, - -93, - -90, - -87, - -83, - -80, - -77, - -73, - -70, - -67, - -63, - -60, - -57, - -54, - -50, - -47, - -44, - -40, - -37, - -34, - -30, - -27, - -24, - -20, - -17, - -14, - -10, - -7, - -4, - 0, - 3, - 6, - 10, - 13, - 16, - 20, - 23, - 26, - 30, - 33, - 36, - 39, - 43, - 46, - 49, - 53, - 56, - 59, - 63, - 66, - 69, - 73, - 76, - 79, - 83, - 86, - 89, - 93, - 96, - 99, - 103, - 106, - 109, - 113, - 116, - 119, - 123, - 126, - 129, - 132, - 136, - 139, - 142, - 146, - 149, - 152, - 156, - 159, - 162, - 166, - 169, - 172, - 176, - 179, - 182, - 186, - 189, - 192, - 196, - 199, - 202, - 206, - 209, - 212, - 216, - 219, - 222, - 226, - 229, - 232, - 235, - 239, - 242, - 245, - 249, - 252, - 255, - 259, - 262, - 265, - 269, - 272, - 275, - 279, - 282, - 285, - 289, - 292, - 295, - 299, - 302, - 305, - 309, - 312, - 315, - 319, - 322, - 325, - 328, - 332, - 335, - 338, - 342, - 345, - 348, - 352, - 355, - 358, - 362, - 365, - 368, - 372, - 375, - 378, - 382, - 385, - 388, - 392, - 395, - 398, - 402, - 405, - 408, - 412, - 415, - 418, - 422, - 425, - 428, - 431, - 435, - 438, - 441, - 445, - 448, - 451, - 455, - 458, - 461, - 465, - 468, - 471, - 475, - 478, - 481, - 485, - 488, - 491, - 495, - 498, - 501, - 505, - 508, - 511, - 515, - 518, - 521, - 524, - 528, - 531, - 534, - 538, - 541, - 544, - 548, - 551, - 554, - 558, - 561, - 564, - 568, - 571, - 574, - 578, - 581, - 584, - 588, - 591, - 594, - 598, - 601, - 604, - 608, - 611, - 614, - 617, - 621, - 624, - 627, - 631, - 634, - 637, - 641, - 644, - 647, - 651, - 654, - 657, - 661, - 664, - 667, - 671, - 674, - 677, - 681, - 684, - 687, - 691, - 694, - 697, - 701, - 704, - 707, - 711, - 714, - 717, - 720, - 724, - 727, - 730, - 734, - 737, - 740, - 744, - 747, - 750, - 754, - 757, - 760, - 764, - 767, - 770, - 774, - 777, - 780, - 784, - 787, - 790, - 794, - 797, - 800, - 804, - 807, - 810, - 813, - 817, - 820, - 823, - 827, - 830, - 833, - 837, - 840, - 843, - 847, - 850, - 853, - 857, - 860, - 863, - 867, - 870, - 873, - 877, - 880, - 883, - 887, - 890, - 893, - 897, - 900, - 903, - 907, - 910, - 913, - 916, - 920, - 923, - 926, - 930, - 933, - 936, - 940, - 943, - 946, - 950, - ], -); - -#[rustfmt::skip] -pub const F32_SHORT_POWERS: [f32; 11] = [ - 1e0, - 1e1, - 1e2, - 1e3, - 1e4, - 1e5, - 1e6, - 1e7, - 1e8, - 1e9, - 1e10, -]; - -#[rustfmt::skip] -pub const F64_SHORT_POWERS: [f64; 23] = [ - 1e0, - 1e1, - 1e2, - 1e3, - 1e4, - 1e5, - 1e6, - 1e7, - 1e8, - 1e9, - 1e10, - 1e11, - 1e12, - 1e13, - 1e14, - 1e15, - 1e16, - 1e17, - 1e18, - 1e19, - 1e20, - 1e21, - 1e22, +pub static POWER_OF_FIVE_128: [(u64, u64); N_POWERS_OF_FIVE] = [ + (0xeef453d6923bd65a, 0x113faa2906a13b3f), // 5^-342 + (0x9558b4661b6565f8, 0x4ac7ca59a424c507), // 5^-341 + (0xbaaee17fa23ebf76, 0x5d79bcf00d2df649), // 5^-340 + (0xe95a99df8ace6f53, 0xf4d82c2c107973dc), // 5^-339 + (0x91d8a02bb6c10594, 0x79071b9b8a4be869), // 5^-338 + (0xb64ec836a47146f9, 0x9748e2826cdee284), // 5^-337 + (0xe3e27a444d8d98b7, 0xfd1b1b2308169b25), // 5^-336 + (0x8e6d8c6ab0787f72, 0xfe30f0f5e50e20f7), // 5^-335 + (0xb208ef855c969f4f, 0xbdbd2d335e51a935), // 5^-334 + (0xde8b2b66b3bc4723, 0xad2c788035e61382), // 5^-333 + (0x8b16fb203055ac76, 0x4c3bcb5021afcc31), // 5^-332 + (0xaddcb9e83c6b1793, 0xdf4abe242a1bbf3d), // 5^-331 + (0xd953e8624b85dd78, 0xd71d6dad34a2af0d), // 5^-330 + (0x87d4713d6f33aa6b, 0x8672648c40e5ad68), // 5^-329 + (0xa9c98d8ccb009506, 0x680efdaf511f18c2), // 5^-328 + (0xd43bf0effdc0ba48, 0x212bd1b2566def2), // 5^-327 + (0x84a57695fe98746d, 0x14bb630f7604b57), // 5^-326 + (0xa5ced43b7e3e9188, 0x419ea3bd35385e2d), // 5^-325 + (0xcf42894a5dce35ea, 0x52064cac828675b9), // 5^-324 + (0x818995ce7aa0e1b2, 0x7343efebd1940993), // 5^-323 + (0xa1ebfb4219491a1f, 0x1014ebe6c5f90bf8), // 5^-322 + (0xca66fa129f9b60a6, 0xd41a26e077774ef6), // 5^-321 + (0xfd00b897478238d0, 0x8920b098955522b4), // 5^-320 + (0x9e20735e8cb16382, 0x55b46e5f5d5535b0), // 5^-319 + (0xc5a890362fddbc62, 0xeb2189f734aa831d), // 5^-318 + (0xf712b443bbd52b7b, 0xa5e9ec7501d523e4), // 5^-317 + (0x9a6bb0aa55653b2d, 0x47b233c92125366e), // 5^-316 + (0xc1069cd4eabe89f8, 0x999ec0bb696e840a), // 5^-315 + (0xf148440a256e2c76, 0xc00670ea43ca250d), // 5^-314 + (0x96cd2a865764dbca, 0x380406926a5e5728), // 5^-313 + (0xbc807527ed3e12bc, 0xc605083704f5ecf2), // 5^-312 + (0xeba09271e88d976b, 0xf7864a44c633682e), // 5^-311 + (0x93445b8731587ea3, 0x7ab3ee6afbe0211d), // 5^-310 + (0xb8157268fdae9e4c, 0x5960ea05bad82964), // 5^-309 + (0xe61acf033d1a45df, 0x6fb92487298e33bd), // 5^-308 + (0x8fd0c16206306bab, 0xa5d3b6d479f8e056), // 5^-307 + (0xb3c4f1ba87bc8696, 0x8f48a4899877186c), // 5^-306 + (0xe0b62e2929aba83c, 0x331acdabfe94de87), // 5^-305 + (0x8c71dcd9ba0b4925, 0x9ff0c08b7f1d0b14), // 5^-304 + (0xaf8e5410288e1b6f, 0x7ecf0ae5ee44dd9), // 5^-303 + (0xdb71e91432b1a24a, 0xc9e82cd9f69d6150), // 5^-302 + (0x892731ac9faf056e, 0xbe311c083a225cd2), // 5^-301 + (0xab70fe17c79ac6ca, 0x6dbd630a48aaf406), // 5^-300 + (0xd64d3d9db981787d, 0x92cbbccdad5b108), // 5^-299 + (0x85f0468293f0eb4e, 0x25bbf56008c58ea5), // 5^-298 + (0xa76c582338ed2621, 0xaf2af2b80af6f24e), // 5^-297 + (0xd1476e2c07286faa, 0x1af5af660db4aee1), // 5^-296 + (0x82cca4db847945ca, 0x50d98d9fc890ed4d), // 5^-295 + (0xa37fce126597973c, 0xe50ff107bab528a0), // 5^-294 + (0xcc5fc196fefd7d0c, 0x1e53ed49a96272c8), // 5^-293 + (0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7a), // 5^-292 + (0x9faacf3df73609b1, 0x77b191618c54e9ac), // 5^-291 + (0xc795830d75038c1d, 0xd59df5b9ef6a2417), // 5^-290 + (0xf97ae3d0d2446f25, 0x4b0573286b44ad1d), // 5^-289 + (0x9becce62836ac577, 0x4ee367f9430aec32), // 5^-288 + (0xc2e801fb244576d5, 0x229c41f793cda73f), // 5^-287 + (0xf3a20279ed56d48a, 0x6b43527578c1110f), // 5^-286 + (0x9845418c345644d6, 0x830a13896b78aaa9), // 5^-285 + (0xbe5691ef416bd60c, 0x23cc986bc656d553), // 5^-284 + (0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa8), // 5^-283 + (0x94b3a202eb1c3f39, 0x7bf7d71432f3d6a9), // 5^-282 + (0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc53), // 5^-281 + (0xe858ad248f5c22c9, 0xd1b3400f8f9cff68), // 5^-280 + (0x91376c36d99995be, 0x23100809b9c21fa1), // 5^-279 + (0xb58547448ffffb2d, 0xabd40a0c2832a78a), // 5^-278 + (0xe2e69915b3fff9f9, 0x16c90c8f323f516c), // 5^-277 + (0x8dd01fad907ffc3b, 0xae3da7d97f6792e3), // 5^-276 + (0xb1442798f49ffb4a, 0x99cd11cfdf41779c), // 5^-275 + (0xdd95317f31c7fa1d, 0x40405643d711d583), // 5^-274 + (0x8a7d3eef7f1cfc52, 0x482835ea666b2572), // 5^-273 + (0xad1c8eab5ee43b66, 0xda3243650005eecf), // 5^-272 + (0xd863b256369d4a40, 0x90bed43e40076a82), // 5^-271 + (0x873e4f75e2224e68, 0x5a7744a6e804a291), // 5^-270 + (0xa90de3535aaae202, 0x711515d0a205cb36), // 5^-269 + (0xd3515c2831559a83, 0xd5a5b44ca873e03), // 5^-268 + (0x8412d9991ed58091, 0xe858790afe9486c2), // 5^-267 + (0xa5178fff668ae0b6, 0x626e974dbe39a872), // 5^-266 + (0xce5d73ff402d98e3, 0xfb0a3d212dc8128f), // 5^-265 + (0x80fa687f881c7f8e, 0x7ce66634bc9d0b99), // 5^-264 + (0xa139029f6a239f72, 0x1c1fffc1ebc44e80), // 5^-263 + (0xc987434744ac874e, 0xa327ffb266b56220), // 5^-262 + (0xfbe9141915d7a922, 0x4bf1ff9f0062baa8), // 5^-261 + (0x9d71ac8fada6c9b5, 0x6f773fc3603db4a9), // 5^-260 + (0xc4ce17b399107c22, 0xcb550fb4384d21d3), // 5^-259 + (0xf6019da07f549b2b, 0x7e2a53a146606a48), // 5^-258 + (0x99c102844f94e0fb, 0x2eda7444cbfc426d), // 5^-257 + (0xc0314325637a1939, 0xfa911155fefb5308), // 5^-256 + (0xf03d93eebc589f88, 0x793555ab7eba27ca), // 5^-255 + (0x96267c7535b763b5, 0x4bc1558b2f3458de), // 5^-254 + (0xbbb01b9283253ca2, 0x9eb1aaedfb016f16), // 5^-253 + (0xea9c227723ee8bcb, 0x465e15a979c1cadc), // 5^-252 + (0x92a1958a7675175f, 0xbfacd89ec191ec9), // 5^-251 + (0xb749faed14125d36, 0xcef980ec671f667b), // 5^-250 + (0xe51c79a85916f484, 0x82b7e12780e7401a), // 5^-249 + (0x8f31cc0937ae58d2, 0xd1b2ecb8b0908810), // 5^-248 + (0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa15), // 5^-247 + (0xdfbdcece67006ac9, 0x67a791e093e1d49a), // 5^-246 + (0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e0), // 5^-245 + (0xaecc49914078536d, 0x58fae9f773886e18), // 5^-244 + (0xda7f5bf590966848, 0xaf39a475506a899e), // 5^-243 + (0x888f99797a5e012d, 0x6d8406c952429603), // 5^-242 + (0xaab37fd7d8f58178, 0xc8e5087ba6d33b83), // 5^-241 + (0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a64), // 5^-240 + (0x855c3be0a17fcd26, 0x5cf2eea09a55067f), // 5^-239 + (0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481e), // 5^-238 + (0xd0601d8efc57b08b, 0xf13b94daf124da26), // 5^-237 + (0x823c12795db6ce57, 0x76c53d08d6b70858), // 5^-236 + (0xa2cb1717b52481ed, 0x54768c4b0c64ca6e), // 5^-235 + (0xcb7ddcdda26da268, 0xa9942f5dcf7dfd09), // 5^-234 + (0xfe5d54150b090b02, 0xd3f93b35435d7c4c), // 5^-233 + (0x9efa548d26e5a6e1, 0xc47bc5014a1a6daf), // 5^-232 + (0xc6b8e9b0709f109a, 0x359ab6419ca1091b), // 5^-231 + (0xf867241c8cc6d4c0, 0xc30163d203c94b62), // 5^-230 + (0x9b407691d7fc44f8, 0x79e0de63425dcf1d), // 5^-229 + (0xc21094364dfb5636, 0x985915fc12f542e4), // 5^-228 + (0xf294b943e17a2bc4, 0x3e6f5b7b17b2939d), // 5^-227 + (0x979cf3ca6cec5b5a, 0xa705992ceecf9c42), // 5^-226 + (0xbd8430bd08277231, 0x50c6ff782a838353), // 5^-225 + (0xece53cec4a314ebd, 0xa4f8bf5635246428), // 5^-224 + (0x940f4613ae5ed136, 0x871b7795e136be99), // 5^-223 + (0xb913179899f68584, 0x28e2557b59846e3f), // 5^-222 + (0xe757dd7ec07426e5, 0x331aeada2fe589cf), // 5^-221 + (0x9096ea6f3848984f, 0x3ff0d2c85def7621), // 5^-220 + (0xb4bca50b065abe63, 0xfed077a756b53a9), // 5^-219 + (0xe1ebce4dc7f16dfb, 0xd3e8495912c62894), // 5^-218 + (0x8d3360f09cf6e4bd, 0x64712dd7abbbd95c), // 5^-217 + (0xb080392cc4349dec, 0xbd8d794d96aacfb3), // 5^-216 + (0xdca04777f541c567, 0xecf0d7a0fc5583a0), // 5^-215 + (0x89e42caaf9491b60, 0xf41686c49db57244), // 5^-214 + (0xac5d37d5b79b6239, 0x311c2875c522ced5), // 5^-213 + (0xd77485cb25823ac7, 0x7d633293366b828b), // 5^-212 + (0x86a8d39ef77164bc, 0xae5dff9c02033197), // 5^-211 + (0xa8530886b54dbdeb, 0xd9f57f830283fdfc), // 5^-210 + (0xd267caa862a12d66, 0xd072df63c324fd7b), // 5^-209 + (0x8380dea93da4bc60, 0x4247cb9e59f71e6d), // 5^-208 + (0xa46116538d0deb78, 0x52d9be85f074e608), // 5^-207 + (0xcd795be870516656, 0x67902e276c921f8b), // 5^-206 + (0x806bd9714632dff6, 0xba1cd8a3db53b6), // 5^-205 + (0xa086cfcd97bf97f3, 0x80e8a40eccd228a4), // 5^-204 + (0xc8a883c0fdaf7df0, 0x6122cd128006b2cd), // 5^-203 + (0xfad2a4b13d1b5d6c, 0x796b805720085f81), // 5^-202 + (0x9cc3a6eec6311a63, 0xcbe3303674053bb0), // 5^-201 + (0xc3f490aa77bd60fc, 0xbedbfc4411068a9c), // 5^-200 + (0xf4f1b4d515acb93b, 0xee92fb5515482d44), // 5^-199 + (0x991711052d8bf3c5, 0x751bdd152d4d1c4a), // 5^-198 + (0xbf5cd54678eef0b6, 0xd262d45a78a0635d), // 5^-197 + (0xef340a98172aace4, 0x86fb897116c87c34), // 5^-196 + (0x9580869f0e7aac0e, 0xd45d35e6ae3d4da0), // 5^-195 + (0xbae0a846d2195712, 0x8974836059cca109), // 5^-194 + (0xe998d258869facd7, 0x2bd1a438703fc94b), // 5^-193 + (0x91ff83775423cc06, 0x7b6306a34627ddcf), // 5^-192 + (0xb67f6455292cbf08, 0x1a3bc84c17b1d542), // 5^-191 + (0xe41f3d6a7377eeca, 0x20caba5f1d9e4a93), // 5^-190 + (0x8e938662882af53e, 0x547eb47b7282ee9c), // 5^-189 + (0xb23867fb2a35b28d, 0xe99e619a4f23aa43), // 5^-188 + (0xdec681f9f4c31f31, 0x6405fa00e2ec94d4), // 5^-187 + (0x8b3c113c38f9f37e, 0xde83bc408dd3dd04), // 5^-186 + (0xae0b158b4738705e, 0x9624ab50b148d445), // 5^-185 + (0xd98ddaee19068c76, 0x3badd624dd9b0957), // 5^-184 + (0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d6), // 5^-183 + (0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4c), // 5^-182 + (0xd47487cc8470652b, 0x7647c3200069671f), // 5^-181 + (0x84c8d4dfd2c63f3b, 0x29ecd9f40041e073), // 5^-180 + (0xa5fb0a17c777cf09, 0xf468107100525890), // 5^-179 + (0xcf79cc9db955c2cc, 0x7182148d4066eeb4), // 5^-178 + (0x81ac1fe293d599bf, 0xc6f14cd848405530), // 5^-177 + (0xa21727db38cb002f, 0xb8ada00e5a506a7c), // 5^-176 + (0xca9cf1d206fdc03b, 0xa6d90811f0e4851c), // 5^-175 + (0xfd442e4688bd304a, 0x908f4a166d1da663), // 5^-174 + (0x9e4a9cec15763e2e, 0x9a598e4e043287fe), // 5^-173 + (0xc5dd44271ad3cdba, 0x40eff1e1853f29fd), // 5^-172 + (0xf7549530e188c128, 0xd12bee59e68ef47c), // 5^-171 + (0x9a94dd3e8cf578b9, 0x82bb74f8301958ce), // 5^-170 + (0xc13a148e3032d6e7, 0xe36a52363c1faf01), // 5^-169 + (0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac1), // 5^-168 + (0x96f5600f15a7b7e5, 0x29ab103a5ef8c0b9), // 5^-167 + (0xbcb2b812db11a5de, 0x7415d448f6b6f0e7), // 5^-166 + (0xebdf661791d60f56, 0x111b495b3464ad21), // 5^-165 + (0x936b9fcebb25c995, 0xcab10dd900beec34), // 5^-164 + (0xb84687c269ef3bfb, 0x3d5d514f40eea742), // 5^-163 + (0xe65829b3046b0afa, 0xcb4a5a3112a5112), // 5^-162 + (0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ab), // 5^-161 + (0xb3f4e093db73a093, 0x59ed216765690f56), // 5^-160 + (0xe0f218b8d25088b8, 0x306869c13ec3532c), // 5^-159 + (0x8c974f7383725573, 0x1e414218c73a13fb), // 5^-158 + (0xafbd2350644eeacf, 0xe5d1929ef90898fa), // 5^-157 + (0xdbac6c247d62a583, 0xdf45f746b74abf39), // 5^-156 + (0x894bc396ce5da772, 0x6b8bba8c328eb783), // 5^-155 + (0xab9eb47c81f5114f, 0x66ea92f3f326564), // 5^-154 + (0xd686619ba27255a2, 0xc80a537b0efefebd), // 5^-153 + (0x8613fd0145877585, 0xbd06742ce95f5f36), // 5^-152 + (0xa798fc4196e952e7, 0x2c48113823b73704), // 5^-151 + (0xd17f3b51fca3a7a0, 0xf75a15862ca504c5), // 5^-150 + (0x82ef85133de648c4, 0x9a984d73dbe722fb), // 5^-149 + (0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebba), // 5^-148 + (0xcc963fee10b7d1b3, 0x318df905079926a8), // 5^-147 + (0xffbbcfe994e5c61f, 0xfdf17746497f7052), // 5^-146 + (0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa633), // 5^-145 + (0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc0), // 5^-144 + (0xf9bd690a1b68637b, 0x3dfdce7aa3c673b0), // 5^-143 + (0x9c1661a651213e2d, 0x6bea10ca65c084e), // 5^-142 + (0xc31bfa0fe5698db8, 0x486e494fcff30a62), // 5^-141 + (0xf3e2f893dec3f126, 0x5a89dba3c3efccfa), // 5^-140 + (0x986ddb5c6b3a76b7, 0xf89629465a75e01c), // 5^-139 + (0xbe89523386091465, 0xf6bbb397f1135823), // 5^-138 + (0xee2ba6c0678b597f, 0x746aa07ded582e2c), // 5^-137 + (0x94db483840b717ef, 0xa8c2a44eb4571cdc), // 5^-136 + (0xba121a4650e4ddeb, 0x92f34d62616ce413), // 5^-135 + (0xe896a0d7e51e1566, 0x77b020baf9c81d17), // 5^-134 + (0x915e2486ef32cd60, 0xace1474dc1d122e), // 5^-133 + (0xb5b5ada8aaff80b8, 0xd819992132456ba), // 5^-132 + (0xe3231912d5bf60e6, 0x10e1fff697ed6c69), // 5^-131 + (0x8df5efabc5979c8f, 0xca8d3ffa1ef463c1), // 5^-130 + (0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb2), // 5^-129 + (0xddd0467c64bce4a0, 0xac7cb3f6d05ddbde), // 5^-128 + (0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96b), // 5^-127 + (0xad4ab7112eb3929d, 0x86c16c98d2c953c6), // 5^-126 + (0xd89d64d57a607744, 0xe871c7bf077ba8b7), // 5^-125 + (0x87625f056c7c4a8b, 0x11471cd764ad4972), // 5^-124 + (0xa93af6c6c79b5d2d, 0xd598e40d3dd89bcf), // 5^-123 + (0xd389b47879823479, 0x4aff1d108d4ec2c3), // 5^-122 + (0x843610cb4bf160cb, 0xcedf722a585139ba), // 5^-121 + (0xa54394fe1eedb8fe, 0xc2974eb4ee658828), // 5^-120 + (0xce947a3da6a9273e, 0x733d226229feea32), // 5^-119 + (0x811ccc668829b887, 0x806357d5a3f525f), // 5^-118 + (0xa163ff802a3426a8, 0xca07c2dcb0cf26f7), // 5^-117 + (0xc9bcff6034c13052, 0xfc89b393dd02f0b5), // 5^-116 + (0xfc2c3f3841f17c67, 0xbbac2078d443ace2), // 5^-115 + (0x9d9ba7832936edc0, 0xd54b944b84aa4c0d), // 5^-114 + (0xc5029163f384a931, 0xa9e795e65d4df11), // 5^-113 + (0xf64335bcf065d37d, 0x4d4617b5ff4a16d5), // 5^-112 + (0x99ea0196163fa42e, 0x504bced1bf8e4e45), // 5^-111 + (0xc06481fb9bcf8d39, 0xe45ec2862f71e1d6), // 5^-110 + (0xf07da27a82c37088, 0x5d767327bb4e5a4c), // 5^-109 + (0x964e858c91ba2655, 0x3a6a07f8d510f86f), // 5^-108 + (0xbbe226efb628afea, 0x890489f70a55368b), // 5^-107 + (0xeadab0aba3b2dbe5, 0x2b45ac74ccea842e), // 5^-106 + (0x92c8ae6b464fc96f, 0x3b0b8bc90012929d), // 5^-105 + (0xb77ada0617e3bbcb, 0x9ce6ebb40173744), // 5^-104 + (0xe55990879ddcaabd, 0xcc420a6a101d0515), // 5^-103 + (0x8f57fa54c2a9eab6, 0x9fa946824a12232d), // 5^-102 + (0xb32df8e9f3546564, 0x47939822dc96abf9), // 5^-101 + (0xdff9772470297ebd, 0x59787e2b93bc56f7), // 5^-100 + (0x8bfbea76c619ef36, 0x57eb4edb3c55b65a), // 5^-99 + (0xaefae51477a06b03, 0xede622920b6b23f1), // 5^-98 + (0xdab99e59958885c4, 0xe95fab368e45eced), // 5^-97 + (0x88b402f7fd75539b, 0x11dbcb0218ebb414), // 5^-96 + (0xaae103b5fcd2a881, 0xd652bdc29f26a119), // 5^-95 + (0xd59944a37c0752a2, 0x4be76d3346f0495f), // 5^-94 + (0x857fcae62d8493a5, 0x6f70a4400c562ddb), // 5^-93 + (0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb952), // 5^-92 + (0xd097ad07a71f26b2, 0x7e2000a41346a7a7), // 5^-91 + (0x825ecc24c873782f, 0x8ed400668c0c28c8), // 5^-90 + (0xa2f67f2dfa90563b, 0x728900802f0f32fa), // 5^-89 + (0xcbb41ef979346bca, 0x4f2b40a03ad2ffb9), // 5^-88 + (0xfea126b7d78186bc, 0xe2f610c84987bfa8), // 5^-87 + (0x9f24b832e6b0f436, 0xdd9ca7d2df4d7c9), // 5^-86 + (0xc6ede63fa05d3143, 0x91503d1c79720dbb), // 5^-85 + (0xf8a95fcf88747d94, 0x75a44c6397ce912a), // 5^-84 + (0x9b69dbe1b548ce7c, 0xc986afbe3ee11aba), // 5^-83 + (0xc24452da229b021b, 0xfbe85badce996168), // 5^-82 + (0xf2d56790ab41c2a2, 0xfae27299423fb9c3), // 5^-81 + (0x97c560ba6b0919a5, 0xdccd879fc967d41a), // 5^-80 + (0xbdb6b8e905cb600f, 0x5400e987bbc1c920), // 5^-79 + (0xed246723473e3813, 0x290123e9aab23b68), // 5^-78 + (0x9436c0760c86e30b, 0xf9a0b6720aaf6521), // 5^-77 + (0xb94470938fa89bce, 0xf808e40e8d5b3e69), // 5^-76 + (0xe7958cb87392c2c2, 0xb60b1d1230b20e04), // 5^-75 + (0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c2), // 5^-74 + (0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af3), // 5^-73 + (0xe2280b6c20dd5232, 0x25c6da63c38de1b0), // 5^-72 + (0x8d590723948a535f, 0x579c487e5a38ad0e), // 5^-71 + (0xb0af48ec79ace837, 0x2d835a9df0c6d851), // 5^-70 + (0xdcdb1b2798182244, 0xf8e431456cf88e65), // 5^-69 + (0x8a08f0f8bf0f156b, 0x1b8e9ecb641b58ff), // 5^-68 + (0xac8b2d36eed2dac5, 0xe272467e3d222f3f), // 5^-67 + (0xd7adf884aa879177, 0x5b0ed81dcc6abb0f), // 5^-66 + (0x86ccbb52ea94baea, 0x98e947129fc2b4e9), // 5^-65 + (0xa87fea27a539e9a5, 0x3f2398d747b36224), // 5^-64 + (0xd29fe4b18e88640e, 0x8eec7f0d19a03aad), // 5^-63 + (0x83a3eeeef9153e89, 0x1953cf68300424ac), // 5^-62 + (0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd7), // 5^-61 + (0xcdb02555653131b6, 0x3792f412cb06794d), // 5^-60 + (0x808e17555f3ebf11, 0xe2bbd88bbee40bd0), // 5^-59 + (0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec4), // 5^-58 + (0xc8de047564d20a8b, 0xf245825a5a445275), // 5^-57 + (0xfb158592be068d2e, 0xeed6e2f0f0d56712), // 5^-56 + (0x9ced737bb6c4183d, 0x55464dd69685606b), // 5^-55 + (0xc428d05aa4751e4c, 0xaa97e14c3c26b886), // 5^-54 + (0xf53304714d9265df, 0xd53dd99f4b3066a8), // 5^-53 + (0x993fe2c6d07b7fab, 0xe546a8038efe4029), // 5^-52 + (0xbf8fdb78849a5f96, 0xde98520472bdd033), // 5^-51 + (0xef73d256a5c0f77c, 0x963e66858f6d4440), // 5^-50 + (0x95a8637627989aad, 0xdde7001379a44aa8), // 5^-49 + (0xbb127c53b17ec159, 0x5560c018580d5d52), // 5^-48 + (0xe9d71b689dde71af, 0xaab8f01e6e10b4a6), // 5^-47 + (0x9226712162ab070d, 0xcab3961304ca70e8), // 5^-46 + (0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d22), // 5^-45 + (0xe45c10c42a2b3b05, 0x8cb89a7db77c506a), // 5^-44 + (0x8eb98a7a9a5b04e3, 0x77f3608e92adb242), // 5^-43 + (0xb267ed1940f1c61c, 0x55f038b237591ed3), // 5^-42 + (0xdf01e85f912e37a3, 0x6b6c46dec52f6688), // 5^-41 + (0x8b61313bbabce2c6, 0x2323ac4b3b3da015), // 5^-40 + (0xae397d8aa96c1b77, 0xabec975e0a0d081a), // 5^-39 + (0xd9c7dced53c72255, 0x96e7bd358c904a21), // 5^-38 + (0x881cea14545c7575, 0x7e50d64177da2e54), // 5^-37 + (0xaa242499697392d2, 0xdde50bd1d5d0b9e9), // 5^-36 + (0xd4ad2dbfc3d07787, 0x955e4ec64b44e864), // 5^-35 + (0x84ec3c97da624ab4, 0xbd5af13bef0b113e), // 5^-34 + (0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58e), // 5^-33 + (0xcfb11ead453994ba, 0x67de18eda5814af2), // 5^-32 + (0x81ceb32c4b43fcf4, 0x80eacf948770ced7), // 5^-31 + (0xa2425ff75e14fc31, 0xa1258379a94d028d), // 5^-30 + (0xcad2f7f5359a3b3e, 0x96ee45813a04330), // 5^-29 + (0xfd87b5f28300ca0d, 0x8bca9d6e188853fc), // 5^-28 + (0x9e74d1b791e07e48, 0x775ea264cf55347e), // 5^-27 + (0xc612062576589dda, 0x95364afe032a819e), // 5^-26 + (0xf79687aed3eec551, 0x3a83ddbd83f52205), // 5^-25 + (0x9abe14cd44753b52, 0xc4926a9672793543), // 5^-24 + (0xc16d9a0095928a27, 0x75b7053c0f178294), // 5^-23 + (0xf1c90080baf72cb1, 0x5324c68b12dd6339), // 5^-22 + (0x971da05074da7bee, 0xd3f6fc16ebca5e04), // 5^-21 + (0xbce5086492111aea, 0x88f4bb1ca6bcf585), // 5^-20 + (0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6), // 5^-19 + (0x9392ee8e921d5d07, 0x3aff322e62439fd0), // 5^-18 + (0xb877aa3236a4b449, 0x9befeb9fad487c3), // 5^-17 + (0xe69594bec44de15b, 0x4c2ebe687989a9b4), // 5^-16 + (0x901d7cf73ab0acd9, 0xf9d37014bf60a11), // 5^-15 + (0xb424dc35095cd80f, 0x538484c19ef38c95), // 5^-14 + (0xe12e13424bb40e13, 0x2865a5f206b06fba), // 5^-13 + (0x8cbccc096f5088cb, 0xf93f87b7442e45d4), // 5^-12 + (0xafebff0bcb24aafe, 0xf78f69a51539d749), // 5^-11 + (0xdbe6fecebdedd5be, 0xb573440e5a884d1c), // 5^-10 + (0x89705f4136b4a597, 0x31680a88f8953031), // 5^-9 + (0xabcc77118461cefc, 0xfdc20d2b36ba7c3e), // 5^-8 + (0xd6bf94d5e57a42bc, 0x3d32907604691b4d), // 5^-7 + (0x8637bd05af6c69b5, 0xa63f9a49c2c1b110), // 5^-6 + (0xa7c5ac471b478423, 0xfcf80dc33721d54), // 5^-5 + (0xd1b71758e219652b, 0xd3c36113404ea4a9), // 5^-4 + (0x83126e978d4fdf3b, 0x645a1cac083126ea), // 5^-3 + (0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4), // 5^-2 + (0xcccccccccccccccc, 0xcccccccccccccccd), // 5^-1 + (0x8000000000000000, 0x0), // 5^0 + (0xa000000000000000, 0x0), // 5^1 + (0xc800000000000000, 0x0), // 5^2 + (0xfa00000000000000, 0x0), // 5^3 + (0x9c40000000000000, 0x0), // 5^4 + (0xc350000000000000, 0x0), // 5^5 + (0xf424000000000000, 0x0), // 5^6 + (0x9896800000000000, 0x0), // 5^7 + (0xbebc200000000000, 0x0), // 5^8 + (0xee6b280000000000, 0x0), // 5^9 + (0x9502f90000000000, 0x0), // 5^10 + (0xba43b74000000000, 0x0), // 5^11 + (0xe8d4a51000000000, 0x0), // 5^12 + (0x9184e72a00000000, 0x0), // 5^13 + (0xb5e620f480000000, 0x0), // 5^14 + (0xe35fa931a0000000, 0x0), // 5^15 + (0x8e1bc9bf04000000, 0x0), // 5^16 + (0xb1a2bc2ec5000000, 0x0), // 5^17 + (0xde0b6b3a76400000, 0x0), // 5^18 + (0x8ac7230489e80000, 0x0), // 5^19 + (0xad78ebc5ac620000, 0x0), // 5^20 + (0xd8d726b7177a8000, 0x0), // 5^21 + (0x878678326eac9000, 0x0), // 5^22 + (0xa968163f0a57b400, 0x0), // 5^23 + (0xd3c21bcecceda100, 0x0), // 5^24 + (0x84595161401484a0, 0x0), // 5^25 + (0xa56fa5b99019a5c8, 0x0), // 5^26 + (0xcecb8f27f4200f3a, 0x0), // 5^27 + (0x813f3978f8940984, 0x4000000000000000), // 5^28 + (0xa18f07d736b90be5, 0x5000000000000000), // 5^29 + (0xc9f2c9cd04674ede, 0xa400000000000000), // 5^30 + (0xfc6f7c4045812296, 0x4d00000000000000), // 5^31 + (0x9dc5ada82b70b59d, 0xf020000000000000), // 5^32 + (0xc5371912364ce305, 0x6c28000000000000), // 5^33 + (0xf684df56c3e01bc6, 0xc732000000000000), // 5^34 + (0x9a130b963a6c115c, 0x3c7f400000000000), // 5^35 + (0xc097ce7bc90715b3, 0x4b9f100000000000), // 5^36 + (0xf0bdc21abb48db20, 0x1e86d40000000000), // 5^37 + (0x96769950b50d88f4, 0x1314448000000000), // 5^38 + (0xbc143fa4e250eb31, 0x17d955a000000000), // 5^39 + (0xeb194f8e1ae525fd, 0x5dcfab0800000000), // 5^40 + (0x92efd1b8d0cf37be, 0x5aa1cae500000000), // 5^41 + (0xb7abc627050305ad, 0xf14a3d9e40000000), // 5^42 + (0xe596b7b0c643c719, 0x6d9ccd05d0000000), // 5^43 + (0x8f7e32ce7bea5c6f, 0xe4820023a2000000), // 5^44 + (0xb35dbf821ae4f38b, 0xdda2802c8a800000), // 5^45 + (0xe0352f62a19e306e, 0xd50b2037ad200000), // 5^46 + (0x8c213d9da502de45, 0x4526f422cc340000), // 5^47 + (0xaf298d050e4395d6, 0x9670b12b7f410000), // 5^48 + (0xdaf3f04651d47b4c, 0x3c0cdd765f114000), // 5^49 + (0x88d8762bf324cd0f, 0xa5880a69fb6ac800), // 5^50 + (0xab0e93b6efee0053, 0x8eea0d047a457a00), // 5^51 + (0xd5d238a4abe98068, 0x72a4904598d6d880), // 5^52 + (0x85a36366eb71f041, 0x47a6da2b7f864750), // 5^53 + (0xa70c3c40a64e6c51, 0x999090b65f67d924), // 5^54 + (0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d), // 5^55 + (0x82818f1281ed449f, 0xbff8f10e7a8921a4), // 5^56 + (0xa321f2d7226895c7, 0xaff72d52192b6a0d), // 5^57 + (0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490), // 5^58 + (0xfee50b7025c36a08, 0x2f236d04753d5b4), // 5^59 + (0x9f4f2726179a2245, 0x1d762422c946590), // 5^60 + (0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5), // 5^61 + (0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2), // 5^62 + (0x9b934c3b330c8577, 0x63cc55f49f88eb2f), // 5^63 + (0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb), // 5^64 + (0xf316271c7fc3908a, 0x8bef464e3945ef7a), // 5^65 + (0x97edd871cfda3a56, 0x97758bf0e3cbb5ac), // 5^66 + (0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317), // 5^67 + (0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd), // 5^68 + (0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a), // 5^69 + (0xb975d6b6ee39e436, 0xb3e2fd538e122b44), // 5^70 + (0xe7d34c64a9c85d44, 0x60dbbca87196b616), // 5^71 + (0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd), // 5^72 + (0xb51d13aea4a488dd, 0x6babab6398bdbe41), // 5^73 + (0xe264589a4dcdab14, 0xc696963c7eed2dd1), // 5^74 + (0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2), // 5^75 + (0xb0de65388cc8ada8, 0x3b25a55f43294bcb), // 5^76 + (0xdd15fe86affad912, 0x49ef0eb713f39ebe), // 5^77 + (0x8a2dbf142dfcc7ab, 0x6e3569326c784337), // 5^78 + (0xacb92ed9397bf996, 0x49c2c37f07965404), // 5^79 + (0xd7e77a8f87daf7fb, 0xdc33745ec97be906), // 5^80 + (0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3), // 5^81 + (0xa8acd7c0222311bc, 0xc40832ea0d68ce0c), // 5^82 + (0xd2d80db02aabd62b, 0xf50a3fa490c30190), // 5^83 + (0x83c7088e1aab65db, 0x792667c6da79e0fa), // 5^84 + (0xa4b8cab1a1563f52, 0x577001b891185938), // 5^85 + (0xcde6fd5e09abcf26, 0xed4c0226b55e6f86), // 5^86 + (0x80b05e5ac60b6178, 0x544f8158315b05b4), // 5^87 + (0xa0dc75f1778e39d6, 0x696361ae3db1c721), // 5^88 + (0xc913936dd571c84c, 0x3bc3a19cd1e38e9), // 5^89 + (0xfb5878494ace3a5f, 0x4ab48a04065c723), // 5^90 + (0x9d174b2dcec0e47b, 0x62eb0d64283f9c76), // 5^91 + (0xc45d1df942711d9a, 0x3ba5d0bd324f8394), // 5^92 + (0xf5746577930d6500, 0xca8f44ec7ee36479), // 5^93 + (0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb), // 5^94 + (0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e), // 5^95 + (0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e), // 5^96 + (0x95d04aee3b80ece5, 0xbba1f1d158724a12), // 5^97 + (0xbb445da9ca61281f, 0x2a8a6e45ae8edc97), // 5^98 + (0xea1575143cf97226, 0xf52d09d71a3293bd), // 5^99 + (0x924d692ca61be758, 0x593c2626705f9c56), // 5^100 + (0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c), // 5^101 + (0xe498f455c38b997a, 0xb6dfb9c0f956447), // 5^102 + (0x8edf98b59a373fec, 0x4724bd4189bd5eac), // 5^103 + (0xb2977ee300c50fe7, 0x58edec91ec2cb657), // 5^104 + (0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed), // 5^105 + (0x8b865b215899f46c, 0xbd79e0d20082ee74), // 5^106 + (0xae67f1e9aec07187, 0xecd8590680a3aa11), // 5^107 + (0xda01ee641a708de9, 0xe80e6f4820cc9495), // 5^108 + (0x884134fe908658b2, 0x3109058d147fdcdd), // 5^109 + (0xaa51823e34a7eede, 0xbd4b46f0599fd415), // 5^110 + (0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a), // 5^111 + (0x850fadc09923329e, 0x3e2cf6bc604ddb0), // 5^112 + (0xa6539930bf6bff45, 0x84db8346b786151c), // 5^113 + (0xcfe87f7cef46ff16, 0xe612641865679a63), // 5^114 + (0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e), // 5^115 + (0xa26da3999aef7749, 0xe3be5e330f38f09d), // 5^116 + (0xcb090c8001ab551c, 0x5cadf5bfd3072cc5), // 5^117 + (0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6), // 5^118 + (0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa), // 5^119 + (0xc646d63501a1511d, 0xb281e1fd541501b8), // 5^120 + (0xf7d88bc24209a565, 0x1f225a7ca91a4226), // 5^121 + (0x9ae757596946075f, 0x3375788de9b06958), // 5^122 + (0xc1a12d2fc3978937, 0x52d6b1641c83ae), // 5^123 + (0xf209787bb47d6b84, 0xc0678c5dbd23a49a), // 5^124 + (0x9745eb4d50ce6332, 0xf840b7ba963646e0), // 5^125 + (0xbd176620a501fbff, 0xb650e5a93bc3d898), // 5^126 + (0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe), // 5^127 + (0x93ba47c980e98cdf, 0xc66f336c36b10137), // 5^128 + (0xb8a8d9bbe123f017, 0xb80b0047445d4184), // 5^129 + (0xe6d3102ad96cec1d, 0xa60dc059157491e5), // 5^130 + (0x9043ea1ac7e41392, 0x87c89837ad68db2f), // 5^131 + (0xb454e4a179dd1877, 0x29babe4598c311fb), // 5^132 + (0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a), // 5^133 + (0x8ce2529e2734bb1d, 0x1899e4a65f58660c), // 5^134 + (0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f), // 5^135 + (0xdc21a1171d42645d, 0x76707543f4fa1f73), // 5^136 + (0x899504ae72497eba, 0x6a06494a791c53a8), // 5^137 + (0xabfa45da0edbde69, 0x487db9d17636892), // 5^138 + (0xd6f8d7509292d603, 0x45a9d2845d3c42b6), // 5^139 + (0x865b86925b9bc5c2, 0xb8a2392ba45a9b2), // 5^140 + (0xa7f26836f282b732, 0x8e6cac7768d7141e), // 5^141 + (0xd1ef0244af2364ff, 0x3207d795430cd926), // 5^142 + (0x8335616aed761f1f, 0x7f44e6bd49e807b8), // 5^143 + (0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6), // 5^144 + (0xcd036837130890a1, 0x36dba887c37a8c0f), // 5^145 + (0x802221226be55a64, 0xc2494954da2c9789), // 5^146 + (0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c), // 5^147 + (0xc83553c5c8965d3d, 0x6f92829494e5acc7), // 5^148 + (0xfa42a8b73abbf48c, 0xcb772339ba1f17f9), // 5^149 + (0x9c69a97284b578d7, 0xff2a760414536efb), // 5^150 + (0xc38413cf25e2d70d, 0xfef5138519684aba), // 5^151 + (0xf46518c2ef5b8cd1, 0x7eb258665fc25d69), // 5^152 + (0x98bf2f79d5993802, 0xef2f773ffbd97a61), // 5^153 + (0xbeeefb584aff8603, 0xaafb550ffacfd8fa), // 5^154 + (0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38), // 5^155 + (0x952ab45cfa97a0b2, 0xdd945a747bf26183), // 5^156 + (0xba756174393d88df, 0x94f971119aeef9e4), // 5^157 + (0xe912b9d1478ceb17, 0x7a37cd5601aab85d), // 5^158 + (0x91abb422ccb812ee, 0xac62e055c10ab33a), // 5^159 + (0xb616a12b7fe617aa, 0x577b986b314d6009), // 5^160 + (0xe39c49765fdf9d94, 0xed5a7e85fda0b80b), // 5^161 + (0x8e41ade9fbebc27d, 0x14588f13be847307), // 5^162 + (0xb1d219647ae6b31c, 0x596eb2d8ae258fc8), // 5^163 + (0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb), // 5^164 + (0x8aec23d680043bee, 0x25de7bb9480d5854), // 5^165 + (0xada72ccc20054ae9, 0xaf561aa79a10ae6a), // 5^166 + (0xd910f7ff28069da4, 0x1b2ba1518094da04), // 5^167 + (0x87aa9aff79042286, 0x90fb44d2f05d0842), // 5^168 + (0xa99541bf57452b28, 0x353a1607ac744a53), // 5^169 + (0xd3fa922f2d1675f2, 0x42889b8997915ce8), // 5^170 + (0x847c9b5d7c2e09b7, 0x69956135febada11), // 5^171 + (0xa59bc234db398c25, 0x43fab9837e699095), // 5^172 + (0xcf02b2c21207ef2e, 0x94f967e45e03f4bb), // 5^173 + (0x8161afb94b44f57d, 0x1d1be0eebac278f5), // 5^174 + (0xa1ba1ba79e1632dc, 0x6462d92a69731732), // 5^175 + (0xca28a291859bbf93, 0x7d7b8f7503cfdcfe), // 5^176 + (0xfcb2cb35e702af78, 0x5cda735244c3d43e), // 5^177 + (0x9defbf01b061adab, 0x3a0888136afa64a7), // 5^178 + (0xc56baec21c7a1916, 0x88aaa1845b8fdd0), // 5^179 + (0xf6c69a72a3989f5b, 0x8aad549e57273d45), // 5^180 + (0x9a3c2087a63f6399, 0x36ac54e2f678864b), // 5^181 + (0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd), // 5^182 + (0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5), // 5^183 + (0x969eb7c47859e743, 0x9f644ae5a4b1b325), // 5^184 + (0xbc4665b596706114, 0x873d5d9f0dde1fee), // 5^185 + (0xeb57ff22fc0c7959, 0xa90cb506d155a7ea), // 5^186 + (0x9316ff75dd87cbd8, 0x9a7f12442d588f2), // 5^187 + (0xb7dcbf5354e9bece, 0xc11ed6d538aeb2f), // 5^188 + (0xe5d3ef282a242e81, 0x8f1668c8a86da5fa), // 5^189 + (0x8fa475791a569d10, 0xf96e017d694487bc), // 5^190 + (0xb38d92d760ec4455, 0x37c981dcc395a9ac), // 5^191 + (0xe070f78d3927556a, 0x85bbe253f47b1417), // 5^192 + (0x8c469ab843b89562, 0x93956d7478ccec8e), // 5^193 + (0xaf58416654a6babb, 0x387ac8d1970027b2), // 5^194 + (0xdb2e51bfe9d0696a, 0x6997b05fcc0319e), // 5^195 + (0x88fcf317f22241e2, 0x441fece3bdf81f03), // 5^196 + (0xab3c2fddeeaad25a, 0xd527e81cad7626c3), // 5^197 + (0xd60b3bd56a5586f1, 0x8a71e223d8d3b074), // 5^198 + (0x85c7056562757456, 0xf6872d5667844e49), // 5^199 + (0xa738c6bebb12d16c, 0xb428f8ac016561db), // 5^200 + (0xd106f86e69d785c7, 0xe13336d701beba52), // 5^201 + (0x82a45b450226b39c, 0xecc0024661173473), // 5^202 + (0xa34d721642b06084, 0x27f002d7f95d0190), // 5^203 + (0xcc20ce9bd35c78a5, 0x31ec038df7b441f4), // 5^204 + (0xff290242c83396ce, 0x7e67047175a15271), // 5^205 + (0x9f79a169bd203e41, 0xf0062c6e984d386), // 5^206 + (0xc75809c42c684dd1, 0x52c07b78a3e60868), // 5^207 + (0xf92e0c3537826145, 0xa7709a56ccdf8a82), // 5^208 + (0x9bbcc7a142b17ccb, 0x88a66076400bb691), // 5^209 + (0xc2abf989935ddbfe, 0x6acff893d00ea435), // 5^210 + (0xf356f7ebf83552fe, 0x583f6b8c4124d43), // 5^211 + (0x98165af37b2153de, 0xc3727a337a8b704a), // 5^212 + (0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c), // 5^213 + (0xeda2ee1c7064130c, 0x1162def06f79df73), // 5^214 + (0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8), // 5^215 + (0xb9a74a0637ce2ee1, 0x6d953e2bd7173692), // 5^216 + (0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437), // 5^217 + (0x910ab1d4db9914a0, 0x1d9c9892400a22a2), // 5^218 + (0xb54d5e4a127f59c8, 0x2503beb6d00cab4b), // 5^219 + (0xe2a0b5dc971f303a, 0x2e44ae64840fd61d), // 5^220 + (0x8da471a9de737e24, 0x5ceaecfed289e5d2), // 5^221 + (0xb10d8e1456105dad, 0x7425a83e872c5f47), // 5^222 + (0xdd50f1996b947518, 0xd12f124e28f77719), // 5^223 + (0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f), // 5^224 + (0xace73cbfdc0bfb7b, 0x636cc64d1001550b), // 5^225 + (0xd8210befd30efa5a, 0x3c47f7e05401aa4e), // 5^226 + (0x8714a775e3e95c78, 0x65acfaec34810a71), // 5^227 + (0xa8d9d1535ce3b396, 0x7f1839a741a14d0d), // 5^228 + (0xd31045a8341ca07c, 0x1ede48111209a050), // 5^229 + (0x83ea2b892091e44d, 0x934aed0aab460432), // 5^230 + (0xa4e4b66b68b65d60, 0xf81da84d5617853f), // 5^231 + (0xce1de40642e3f4b9, 0x36251260ab9d668e), // 5^232 + (0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019), // 5^233 + (0xa1075a24e4421730, 0xb24cf65b8612f81f), // 5^234 + (0xc94930ae1d529cfc, 0xdee033f26797b627), // 5^235 + (0xfb9b7cd9a4a7443c, 0x169840ef017da3b1), // 5^236 + (0x9d412e0806e88aa5, 0x8e1f289560ee864e), // 5^237 + (0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2), // 5^238 + (0xf5b5d7ec8acb58a2, 0xae10af696774b1db), // 5^239 + (0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29), // 5^240 + (0xbff610b0cc6edd3f, 0x17fd090a58d32af3), // 5^241 + (0xeff394dcff8a948e, 0xddfc4b4cef07f5b0), // 5^242 + (0x95f83d0a1fb69cd9, 0x4abdaf101564f98e), // 5^243 + (0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1), // 5^244 + (0xea53df5fd18d5513, 0x84c86189216dc5ed), // 5^245 + (0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4), // 5^246 + (0xb7118682dbb66a77, 0x3fbc8c33221dc2a1), // 5^247 + (0xe4d5e82392a40515, 0xfabaf3feaa5334a), // 5^248 + (0x8f05b1163ba6832d, 0x29cb4d87f2a7400e), // 5^249 + (0xb2c71d5bca9023f8, 0x743e20e9ef511012), // 5^250 + (0xdf78e4b2bd342cf6, 0x914da9246b255416), // 5^251 + (0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e), // 5^252 + (0xae9672aba3d0c320, 0xa184ac2473b529b1), // 5^253 + (0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e), // 5^254 + (0x8865899617fb1871, 0x7e2fa67c7a658892), // 5^255 + (0xaa7eebfb9df9de8d, 0xddbb901b98feeab7), // 5^256 + (0xd51ea6fa85785631, 0x552a74227f3ea565), // 5^257 + (0x8533285c936b35de, 0xd53a88958f87275f), // 5^258 + (0xa67ff273b8460356, 0x8a892abaf368f137), // 5^259 + (0xd01fef10a657842c, 0x2d2b7569b0432d85), // 5^260 + (0x8213f56a67f6b29b, 0x9c3b29620e29fc73), // 5^261 + (0xa298f2c501f45f42, 0x8349f3ba91b47b8f), // 5^262 + (0xcb3f2f7642717713, 0x241c70a936219a73), // 5^263 + (0xfe0efb53d30dd4d7, 0xed238cd383aa0110), // 5^264 + (0x9ec95d1463e8a506, 0xf4363804324a40aa), // 5^265 + (0xc67bb4597ce2ce48, 0xb143c6053edcd0d5), // 5^266 + (0xf81aa16fdc1b81da, 0xdd94b7868e94050a), // 5^267 + (0x9b10a4e5e9913128, 0xca7cf2b4191c8326), // 5^268 + (0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0), // 5^269 + (0xf24a01a73cf2dccf, 0xbc633b39673c8cec), // 5^270 + (0x976e41088617ca01, 0xd5be0503e085d813), // 5^271 + (0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18), // 5^272 + (0xec9c459d51852ba2, 0xddf8e7d60ed1219e), // 5^273 + (0x93e1ab8252f33b45, 0xcabb90e5c942b503), // 5^274 + (0xb8da1662e7b00a17, 0x3d6a751f3b936243), // 5^275 + (0xe7109bfba19c0c9d, 0xcc512670a783ad4), // 5^276 + (0x906a617d450187e2, 0x27fb2b80668b24c5), // 5^277 + (0xb484f9dc9641e9da, 0xb1f9f660802dedf6), // 5^278 + (0xe1a63853bbd26451, 0x5e7873f8a0396973), // 5^279 + (0x8d07e33455637eb2, 0xdb0b487b6423e1e8), // 5^280 + (0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62), // 5^281 + (0xdc5c5301c56b75f7, 0x7641a140cc7810fb), // 5^282 + (0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d), // 5^283 + (0xac2820d9623bf429, 0x546345fa9fbdcd44), // 5^284 + (0xd732290fbacaf133, 0xa97c177947ad4095), // 5^285 + (0x867f59a9d4bed6c0, 0x49ed8eabcccc485d), // 5^286 + (0xa81f301449ee8c70, 0x5c68f256bfff5a74), // 5^287 + (0xd226fc195c6a2f8c, 0x73832eec6fff3111), // 5^288 + (0x83585d8fd9c25db7, 0xc831fd53c5ff7eab), // 5^289 + (0xa42e74f3d032f525, 0xba3e7ca8b77f5e55), // 5^290 + (0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb), // 5^291 + (0x80444b5e7aa7cf85, 0x7980d163cf5b81b3), // 5^292 + (0xa0555e361951c366, 0xd7e105bcc332621f), // 5^293 + (0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7), // 5^294 + (0xfa856334878fc150, 0xb14f98f6f0feb951), // 5^295 + (0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3), // 5^296 + (0xc3b8358109e84f07, 0xa862f80ec4700c8), // 5^297 + (0xf4a642e14c6262c8, 0xcd27bb612758c0fa), // 5^298 + (0x98e7e9cccfbd7dbd, 0x8038d51cb897789c), // 5^299 + (0xbf21e44003acdd2c, 0xe0470a63e6bd56c3), // 5^300 + (0xeeea5d5004981478, 0x1858ccfce06cac74), // 5^301 + (0x95527a5202df0ccb, 0xf37801e0c43ebc8), // 5^302 + (0xbaa718e68396cffd, 0xd30560258f54e6ba), // 5^303 + (0xe950df20247c83fd, 0x47c6b82ef32a2069), // 5^304 + (0x91d28b7416cdd27e, 0x4cdc331d57fa5441), // 5^305 + (0xb6472e511c81471d, 0xe0133fe4adf8e952), // 5^306 + (0xe3d8f9e563a198e5, 0x58180fddd97723a6), // 5^307 + (0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648), // 5^308 ]; diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index e2cc8faf85..cdeba9c079 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -74,26 +74,20 @@ pub struct ParseIntError { /// # Example /// /// ``` -/// #![feature(int_error_matching)] -/// /// # fn main() { /// if let Err(e) = i32::from_str_radix("a12", 10) { /// println!("Failed conversion to i32: {:?}", e.kind()); /// } /// # } /// ``` -#[unstable( - feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639" -)] +#[stable(feature = "int_error_matching", since = "1.55.0")] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { /// Value being parsed is empty. /// - /// Among other causes, this variant will be constructed when parsing an empty string. + /// This variant will be constructed when parsing an empty string. + #[stable(feature = "int_error_matching", since = "1.55.0")] Empty, /// Contains an invalid digit in its context. /// @@ -102,26 +96,25 @@ pub enum IntErrorKind { /// /// This variant is also constructed when a `+` or `-` is misplaced within a string /// either on its own or in the middle of a number. + #[stable(feature = "int_error_matching", since = "1.55.0")] InvalidDigit, /// Integer is too large to store in target integer type. + #[stable(feature = "int_error_matching", since = "1.55.0")] PosOverflow, /// Integer is too small to store in target integer type. + #[stable(feature = "int_error_matching", since = "1.55.0")] NegOverflow, /// Value was Zero /// /// This variant will be emitted when the parsing string has a value of zero, which /// would be illegal for non-zero types. + #[stable(feature = "int_error_matching", since = "1.55.0")] Zero, } impl ParseIntError { /// Outputs the detailed cause of parsing an integer failing. - #[unstable( - feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639" - )] + #[stable(feature = "int_error_matching", since = "1.55.0")] pub fn kind(&self) -> &IntErrorKind { &self.kind } diff --git a/library/core/src/num/flt2dec/decoder.rs b/library/core/src/num/flt2dec/decoder.rs index c43536c6fc..5763860540 100644 --- a/library/core/src/num/flt2dec/decoder.rs +++ b/library/core/src/num/flt2dec/decoder.rs @@ -1,6 +1,6 @@ //! Decodes a floating-point value into individual parts and error ranges. -use crate::num::dec2flt::rawfp::RawFloat; +use crate::num::dec2flt::float::RawFloat; use crate::num::FpCategory; /// Decoded unsigned finite value, such that: diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs index 93bdf5040e..1ff2e8c822 100644 --- a/library/core/src/num/flt2dec/mod.rs +++ b/library/core/src/num/flt2dec/mod.rs @@ -49,7 +49,7 @@ the supplied buffer and let the algorithm to return. # Implementation overview It is easy to get the floating point printing correct but slow (Russ Cox has -[demonstrated](http://research.swtch.com/ftoa) how it's easy), or incorrect but +[demonstrated](https://research.swtch.com/ftoa) how it's easy), or incorrect but fast (naïve division and modulo). But it is surprisingly hard to print floating point numbers correctly *and* efficiently. @@ -124,6 +124,7 @@ functions. pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded}; +use super::fmt::{Formatted, Part}; use crate::mem::MaybeUninit; pub mod decoder; @@ -170,107 +171,6 @@ pub fn round_up(d: &mut [u8]) -> Option { } } -/// Formatted parts. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Part<'a> { - /// Given number of zero digits. - Zero(usize), - /// A literal number up to 5 digits. - Num(u16), - /// A verbatim copy of given bytes. - Copy(&'a [u8]), -} - -impl<'a> Part<'a> { - /// Returns the exact byte length of given part. - pub fn len(&self) -> usize { - match *self { - Part::Zero(nzeroes) => nzeroes, - Part::Num(v) => { - if v < 1_000 { - if v < 10 { - 1 - } else if v < 100 { - 2 - } else { - 3 - } - } else { - if v < 10_000 { 4 } else { 5 } - } - } - Part::Copy(buf) => buf.len(), - } - } - - /// Writes a part into the supplied buffer. - /// Returns the number of written bytes, or `None` if the buffer is not enough. - /// (It may still leave partially written bytes in the buffer; do not rely on that.) - pub fn write(&self, out: &mut [u8]) -> Option { - let len = self.len(); - if out.len() >= len { - match *self { - Part::Zero(nzeroes) => { - for c in &mut out[..nzeroes] { - *c = b'0'; - } - } - Part::Num(mut v) => { - for c in out[..len].iter_mut().rev() { - *c = b'0' + (v % 10) as u8; - v /= 10; - } - } - Part::Copy(buf) => { - out[..buf.len()].copy_from_slice(buf); - } - } - Some(len) - } else { - None - } - } -} - -/// Formatted result containing one or more parts. -/// This can be written to the byte buffer or converted to the allocated string. -#[allow(missing_debug_implementations)] -#[derive(Clone)] -pub struct Formatted<'a> { - /// A byte slice representing a sign, either `""`, `"-"` or `"+"`. - pub sign: &'static str, - /// Formatted parts to be rendered after a sign and optional zero padding. - pub parts: &'a [Part<'a>], -} - -impl<'a> Formatted<'a> { - /// Returns the exact byte length of combined formatted result. - pub fn len(&self) -> usize { - let mut len = self.sign.len(); - for part in self.parts { - len += part.len(); - } - len - } - - /// Writes all formatted parts into the supplied buffer. - /// Returns the number of written bytes, or `None` if the buffer is not enough. - /// (It may still leave partially written bytes in the buffer; do not rely on that.) - pub fn write(&self, out: &mut [u8]) -> Option { - if out.len() < self.sign.len() { - return None; - } - out[..self.sign.len()].copy_from_slice(self.sign.as_bytes()); - - let mut written = self.sign.len(); - for part in self.parts { - let len = part.write(&mut out[written..])?; - written += len; - } - Some(written) - } -} - /// Formats given decimal digits `0.<...buf...> * 10^exp` into the decimal form /// with at least given number of fractional digits. The result is stored to /// the supplied parts array and a slice of written parts is returned. diff --git a/library/core/src/num/fmt.rs b/library/core/src/num/fmt.rs new file mode 100644 index 0000000000..578288bda2 --- /dev/null +++ b/library/core/src/num/fmt.rs @@ -0,0 +1,108 @@ +//! Shared utilties used by both float and integer formatting. +#![doc(hidden)] +#![unstable( + feature = "numfmt", + reason = "internal routines only exposed for testing", + issue = "none" +)] + +/// Formatted parts. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Part<'a> { + /// Given number of zero digits. + Zero(usize), + /// A literal number up to 5 digits. + Num(u16), + /// A verbatim copy of given bytes. + Copy(&'a [u8]), +} + +impl<'a> Part<'a> { + /// Returns the exact byte length of given part. + pub fn len(&self) -> usize { + match *self { + Part::Zero(nzeroes) => nzeroes, + Part::Num(v) => { + if v < 1_000 { + if v < 10 { + 1 + } else if v < 100 { + 2 + } else { + 3 + } + } else { + if v < 10_000 { 4 } else { 5 } + } + } + Part::Copy(buf) => buf.len(), + } + } + + /// Writes a part into the supplied buffer. + /// Returns the number of written bytes, or `None` if the buffer is not enough. + /// (It may still leave partially written bytes in the buffer; do not rely on that.) + pub fn write(&self, out: &mut [u8]) -> Option { + let len = self.len(); + if out.len() >= len { + match *self { + Part::Zero(nzeroes) => { + for c in &mut out[..nzeroes] { + *c = b'0'; + } + } + Part::Num(mut v) => { + for c in out[..len].iter_mut().rev() { + *c = b'0' + (v % 10) as u8; + v /= 10; + } + } + Part::Copy(buf) => { + out[..buf.len()].copy_from_slice(buf); + } + } + Some(len) + } else { + None + } + } +} + +/// Formatted result containing one or more parts. +/// This can be written to the byte buffer or converted to the allocated string. +#[allow(missing_debug_implementations)] +#[derive(Clone)] +pub struct Formatted<'a> { + /// A byte slice representing a sign, either `""`, `"-"` or `"+"`. + pub sign: &'static str, + /// Formatted parts to be rendered after a sign and optional zero padding. + pub parts: &'a [Part<'a>], +} + +impl<'a> Formatted<'a> { + /// Returns the exact byte length of combined formatted result. + pub fn len(&self) -> usize { + let mut len = self.sign.len(); + for part in self.parts { + len += part.len(); + } + len + } + + /// Writes all formatted parts into the supplied buffer. + /// Returns the number of written bytes, or `None` if the buffer is not enough. + /// (It may still leave partially written bytes in the buffer; do not rely on that.) + pub fn write(&self, out: &mut [u8]) -> Option { + if out.len() < self.sign.len() { + return None; + } + out[..self.sign.len()].copy_from_slice(self.sign.as_bytes()); + + let mut written = self.sign.len(); + for part in self.parts { + let len = part.write(&mut out[written..])?; + written += len; + } + Some(written) + } +} diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs new file mode 100644 index 0000000000..a23ca51ef8 --- /dev/null +++ b/library/core/src/num/int_log10.rs @@ -0,0 +1,134 @@ +mod unchecked { + // 0 < val <= u8::MAX + pub const fn u8(val: u8) -> u32 { + if val >= 100 { + 2 + } else if val >= 10 { + 1 + } else { + 0 + } + } + + // 0 < val <= u16::MAX + pub const fn u16(val: u16) -> u32 { + if val >= 10_000 { + 4 + } else if val >= 1000 { + 3 + } else if val >= 100 { + 2 + } else if val >= 10 { + 1 + } else { + 0 + } + } + + // 0 < val < 100_000_000 + const fn less_than_8(mut val: u32) -> u32 { + let mut log = 0; + if val >= 10_000 { + val /= 10_000; + log += 4; + } + log + if val >= 1000 { + 3 + } else if val >= 100 { + 2 + } else if val >= 10 { + 1 + } else { + 0 + } + } + + // 0 < val <= u32::MAX + pub const fn u32(mut val: u32) -> u32 { + let mut log = 0; + if val >= 100_000_000 { + val /= 100_000_000; + log += 8; + } + log + less_than_8(val) + } + + // 0 < val < 10_000_000_000_000_000 + const fn less_than_16(mut val: u64) -> u32 { + let mut log = 0; + if val >= 100_000_000 { + val /= 100_000_000; + log += 8; + } + log + less_than_8(val as u32) + } + + // 0 < val <= u64::MAX + pub const fn u64(mut val: u64) -> u32 { + let mut log = 0; + if val >= 10_000_000_000_000_000 { + val /= 10_000_000_000_000_000; + log += 16; + } + log + less_than_16(val) + } + + // 0 < val <= u128::MAX + pub const fn u128(mut val: u128) -> u32 { + let mut log = 0; + if val >= 100_000_000_000_000_000_000_000_000_000_000 { + val /= 100_000_000_000_000_000_000_000_000_000_000; + log += 32; + return log + less_than_8(val as u32); + } + if val >= 10_000_000_000_000_000 { + val /= 10_000_000_000_000_000; + log += 16; + } + log + less_than_16(val as u64) + } + + // 0 < val <= i8::MAX + pub const fn i8(val: i8) -> u32 { + u8(val as u8) + } + + // 0 < val <= i16::MAX + pub const fn i16(val: i16) -> u32 { + u16(val as u16) + } + + // 0 < val <= i32::MAX + pub const fn i32(val: i32) -> u32 { + u32(val as u32) + } + + // 0 < val <= i64::MAX + pub const fn i64(val: i64) -> u32 { + u64(val as u64) + } + + // 0 < val <= i128::MAX + pub const fn i128(val: i128) -> u32 { + u128(val as u128) + } +} + +macro_rules! impl_checked { + ($T:ident) => { + pub const fn $T(val: $T) -> Option<$T> { + if val > 0 { Some(unchecked::$T(val) as $T) } else { None } + } + }; +} + +impl_checked! { u8 } +impl_checked! { u16 } +impl_checked! { u32 } +impl_checked! { u64 } +impl_checked! { u128 } +impl_checked! { i8 } +impl_checked! { i16 } +impl_checked! { i32 } +impl_checked! { i64 } +impl_checked! { i128 } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index a0efe68128..982729388c 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1744,6 +1744,197 @@ macro_rules! int_impl { } } + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// This method may not be optimized owing to implementation details; + /// `log2` can produce results more efficiently for base 2, and `log10` + /// can produce results more efficiently for base 10. + /// + /// # Panics + /// + /// When the number is zero, or if the base is not at least 2; it + /// panics in debug mode and the return value is wrapped to 0 in release + /// mode (the only situation in which the method can return 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + #[allow(arithmetic_overflow)] + pub const fn log(self, base: Self) -> Self { + match self.checked_log(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 + }, + } + } + + /// Returns the base 2 logarithm of the number. + /// + /// # Panics + /// + /// When the number is zero it panics in debug mode and the return value + /// is wrapped to 0 in release mode (the only situation in which the + /// method can return 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + #[allow(arithmetic_overflow)] + pub const fn log2(self) -> Self { + match self.checked_log2() { + 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 + }, + } + } + + /// Returns the base 10 logarithm of the number. + /// + /// # Panics + /// + /// When the number is zero it panics in debug mode and the return value + /// is wrapped to 0 in release mode (the only situation in which the + /// method can return 0). + /// + /// # Example + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + #[allow(arithmetic_overflow)] + pub const fn log10(self) -> Self { + match self.checked_log10() { + 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 + }, + } + } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// Returns `None` if the number is negative or zero, or if the base is not at least 2. + /// + /// This method may not be optimized owing to implementation details; + /// `checked_log2` can produce results more efficiently for base 2, and + /// `checked_log10` can produce results more efficiently for base 10. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_log(self, base: Self) -> Option { + if self <= 0 || base <= 1 { + None + } else { + let mut n = 0; + let mut r = self; + + // Optimization for 128 bit wide integers. + if Self::BITS == 128 { + let b = Self::log2(self) / (Self::log2(base) + 1); + n += b; + r /= base.pow(b as u32); + } + + while r >= base { + r /= base; + n += 1; + } + Some(n) + } + } + + /// Returns the base 2 logarithm of the number. + /// + /// Returns `None` if the number is negative or zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_log2(self) -> Option { + if self <= 0 { + None + } else { + // SAFETY: We just checked that this number is positive + let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) }; + Some(log) + } + } + + /// Returns the base 10 logarithm of the number. + /// + /// Returns `None` if the number is negative or zero. + /// + /// # Example + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_log10(self) -> Option { + match int_log10::$ActualT(self as $ActualT) { + Some(s) => Some(s as Self), + None => None, + } + } + /// Computes the absolute value of `self`. /// /// # Overflow behavior @@ -1772,9 +1963,9 @@ macro_rules! int_impl { #[inline] #[rustc_inherit_overflow_checks] pub const fn abs(self) -> Self { - // Note that the #[inline] above means that the overflow - // semantics of the subtraction depend on the crate we're being - // inlined into. + // Note that the #[rustc_inherit_overflow_checks] and #[inline] + // above mean that the overflow semantics of the subtraction + // depend on the crate we're being called from. if self.is_negative() { -self } else { diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 6032dc9a2d..26d84a6070 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -25,10 +25,15 @@ macro_rules! unlikely { } // All these modules are technically private and only exposed for coretests: +#[cfg(not(no_fp_fmt_parse))] pub mod bignum; +#[cfg(not(no_fp_fmt_parse))] pub mod dec2flt; +#[cfg(not(no_fp_fmt_parse))] pub mod diy_float; +#[cfg(not(no_fp_fmt_parse))] pub mod flt2dec; +pub mod fmt; #[macro_use] mod int_macros; // import int_impl! @@ -36,6 +41,7 @@ mod int_macros; // import int_impl! mod uint_macros; // import uint_impl! mod error; +mod int_log10; mod nonzero; mod wrapping; @@ -43,6 +49,7 @@ mod wrapping; pub use wrapping::Wrapping; #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(no_fp_fmt_parse))] pub use dec2flt::ParseFloatError; #[stable(feature = "rust1", since = "1.0.0")] @@ -57,12 +64,7 @@ pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, No #[stable(feature = "try_from", since = "1.34.0")] pub use error::TryFromIntError; -#[unstable( - feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639" -)] +#[stable(feature = "int_error_matching", since = "1.55.0")] pub use error::IntErrorKind; macro_rules! usize_isize_to_xe_bytes_doc { @@ -595,8 +597,8 @@ impl u8 { /// before using this function. /// /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace - /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 - /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 + /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 + /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 /// /// # Examples /// diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6b9b435d47..dd9b9330ae 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -42,7 +42,8 @@ macro_rules! nonzero_integers { pub struct $Ty($Int); impl $Ty { - /// Creates a non-zero without checking the value. + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behaviour if the value is zero. /// /// # Safety /// @@ -285,6 +286,576 @@ nonzero_integers_div! { NonZeroUsize(usize); } +// A bunch of methods for unsigned nonzero types only. +macro_rules! nonzero_unsigned_operations { + ( $( $Ty: ident($Int: ty); )+ ) => { + $( + impl $Ty { + /// Add an unsigned integer to a non-zero value. + /// Check for overflow and return [`None`] on overflow + /// As a consequence, the result cannot wrap to zero. + /// + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), one.checked_add(1)); + /// assert_eq!(None, max.checked_add(1)); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn checked_add(self, other: $Int) -> Option<$Ty> { + if let Some(result) = self.get().checked_add(other) { + // SAFETY: $Int::checked_add returns None on overflow + // so the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } + + /// Add an unsigned integer to a non-zero value. + #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(two, one.saturating_add(1)); + /// assert_eq!(max, max.saturating_add(1)); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn saturating_add(self, other: $Int) -> $Ty { + // SAFETY: $Int::saturating_add returns $Int::MAX on overflow + // so the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } + } + + /// Add an unsigned integer to a non-zero value, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + /// + /// assert_eq!(two, unsafe { one.unchecked_add(1) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub unsafe fn unchecked_add(self, other: $Int) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } + } + + /// Returns the smallest power of two greater than or equal to n. + /// Check for overflow and return [`None`] + /// if the next power of two is greater than the type’s maximum value. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), two.checked_next_power_of_two() ); + /// assert_eq!(Some(four), three.checked_next_power_of_two() ); + /// assert_eq!(None, max.checked_next_power_of_two() ); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn checked_next_power_of_two(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_next_power_of_two() { + // SAFETY: The next power of two is positive + // and overflow is checked. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None + } + } + } + )+ + } +} + +nonzero_unsigned_operations! { + NonZeroU8(u8); + NonZeroU16(u16); + NonZeroU32(u32); + NonZeroU64(u64); + NonZeroU128(u128); + NonZeroUsize(usize); +} + +// A bunch of methods for signed nonzero types only. +macro_rules! nonzero_signed_operations { + ( $( $Ty: ident($Int: ty) -> $Uty: ident($Uint: ty); )+ ) => { + $( + impl $Ty { + /// Computes the absolute value of self. + #[doc = concat!("See [`", stringify!($Int), "::abs`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + /// + /// assert_eq!(pos, pos.abs()); + /// assert_eq!(pos, neg.abs()); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn abs(self) -> $Ty { + // SAFETY: This cannot overflow to zero. + unsafe { $Ty::new_unchecked(self.get().abs()) } + } + + /// Checked absolute value. + /// Check for overflow and returns [`None`] if + #[doc = concat!("`self == ", stringify!($Int), "::MIN`.")] + /// The result cannot be zero. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(Some(pos), neg.checked_abs()); + /// assert_eq!(None, min.checked_abs()); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn checked_abs(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_abs() { + // SAFETY: absolute value of nonzero cannot yield zero values. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None + } + } + + /// Computes the absolute value of self, + /// with overflow information, see + #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!((pos, false), pos.overflowing_abs()); + /// assert_eq!((pos, false), neg.overflowing_abs()); + /// assert_eq!((min, true), min.overflowing_abs()); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn overflowing_abs(self) -> ($Ty, bool) { + let (nz, flag) = self.get().overflowing_abs(); + ( + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(nz) }, + flag, + ) + } + + /// Saturating absolute value, see + #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.saturating_abs()); + /// assert_eq!(pos, neg.saturating_abs()); + /// assert_eq!(max, min.saturating_abs()); + /// assert_eq!(max, min_plus.saturating_abs()); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn saturating_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } + } + + /// Wrapping absolute value, see + #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.wrapping_abs()); + /// assert_eq!(pos, neg.wrapping_abs()); + /// assert_eq!(min, min.wrapping_abs()); + /// # // FIXME: add once Neg is implemented? + /// # // assert_eq!(max, (-max).wrapping_abs()); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn wrapping_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } + } + + /// Computes the absolute value of self + /// without any wrapping or panicking. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("# use std::num::", stringify!($Uty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] + #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", + stringify!($Uint), "::MAX / 2 + 1)?;")] + /// + /// assert_eq!(u_pos, i_pos.unsigned_abs()); + /// assert_eq!(u_pos, i_neg.unsigned_abs()); + /// assert_eq!(u_max, i_min.unsigned_abs()); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn unsigned_abs(self) -> $Uty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } + } + } + )+ + } +} + +nonzero_signed_operations! { + NonZeroI8(i8) -> NonZeroU8(u8); + NonZeroI16(i16) -> NonZeroU16(u16); + NonZeroI32(i32) -> NonZeroU32(u32); + NonZeroI64(i64) -> NonZeroU64(u64); + NonZeroI128(i128) -> NonZeroU128(u128); + NonZeroIsize(isize) -> NonZeroUsize(usize); +} + +// A bunch of methods for both signed and unsigned nonzero types. +macro_rules! nonzero_unsigned_signed_operations { + ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => { + $( + impl $Ty { + /// Multiply two non-zero integers together. + /// Check for overflow and return [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(four), two.checked_mul(two)); + /// assert_eq!(None, max.checked_mul(two)); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { + if let Some(result) = self.get().checked_mul(other.get()) { + // SAFETY: checked_mul returns None on overflow + // and `other` is also non-null + // so the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } + + /// Multiply two non-zero integers together. + #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(four, two.saturating_mul(two)); + /// assert_eq!(max, four.saturating_mul(max)); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn saturating_mul(self, other: $Ty) -> $Ty { + // SAFETY: saturating_mul returns u*::MAX on overflow + // and `other` is also non-null + // so the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } + } + + /// Multiply two non-zero integers together, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", + "or `self * rhs < ", stringify!($Int), "::MIN`.") + } + if unsigned { + concat!("`self * rhs > ", stringify!($Int), "::MAX`.") + } + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } + } + + /// Raise non-zero value to an integer power. + /// Check for overflow and return [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX / 2)?;")] + /// + /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); + /// assert_eq!(None, half_max.checked_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn checked_pow(self, other: u32) -> Option<$Ty> { + if let Some(result) = self.get().checked_pow(other) { + // SAFETY: checked_pow returns None on overflow + // so the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } + + /// Raise non-zero value to an integer power. + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("Return [`", stringify!($Int), "::MIN`] ", + "or [`", stringify!($Int), "::MAX`] on overflow.") + } + if unsigned { + concat!("Return [`", stringify!($Int), "::MAX`] on overflow.") + } + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(twenty_seven, three.saturating_pow(3)); + /// assert_eq!(max, max.saturating_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[inline] + pub const fn saturating_pow(self, other: u32) -> $Ty { + // SAFETY: saturating_pow returns u*::MAX on overflow + // so the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } + } + } + )+ + } +} + +// Use this when the generated code should differ between signed and unsigned types. +macro_rules! sign_dependent_expr { + (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { + $signed_case + }; + (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { + $unsigned_case + }; +} + +nonzero_unsigned_signed_operations! { + unsigned NonZeroU8(u8); + unsigned NonZeroU16(u16); + unsigned NonZeroU32(u32); + unsigned NonZeroU64(u64); + unsigned NonZeroU128(u128); + unsigned NonZeroUsize(usize); + signed NonZeroI8(i8); + signed NonZeroI16(i16); + signed NonZeroI32(i32); + signed NonZeroI64(i64); + signed NonZeroI128(i128); + signed NonZeroIsize(isize); +} + macro_rules! nonzero_unsigned_is_power_of_two { ( $( $Ty: ident )+ ) => { $( diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index e512d90ef3..ca1b05fdfb 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1,5 +1,5 @@ macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, + ($SelfT:ty, $ActualT:ident, $BITS:expr, $MaxV:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr, $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { @@ -634,6 +634,197 @@ macro_rules! uint_impl { } } + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// This method may not be optimized owing to implementation details; + /// `log2` can produce results more efficiently for base 2, and `log10` + /// can produce results more efficiently for base 10. + /// + /// # Panics + /// + /// When the number is negative, zero, or if the base is not at least 2; + /// it panics in debug mode and the return value is wrapped to 0 in + /// release mode (the only situation in which the method can return 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + #[allow(arithmetic_overflow)] + pub const fn log(self, base: Self) -> Self { + match self.checked_log(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 + }, + } + } + + /// Returns the base 2 logarithm of the number. + /// + /// # Panics + /// + /// When the number is negative or zero it panics in debug mode and + /// the return value is wrapped to 0 in release mode (the only situation in + /// which the method can return 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + #[allow(arithmetic_overflow)] + pub const fn log2(self) -> Self { + match self.checked_log2() { + 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 + }, + } + } + + /// Returns the base 10 logarithm of the number. + /// + /// # Panics + /// + /// When the number is negative or zero it panics in debug mode and the + /// return value is wrapped to 0 in release mode (the only situation in + /// which the method can return 0). + /// + /// # Example + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + #[track_caller] + #[rustc_inherit_overflow_checks] + #[allow(arithmetic_overflow)] + pub const fn log10(self) -> Self { + match self.checked_log10() { + 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 + }, + } + } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// Returns `None` if the number is zero, or if the base is not at least 2. + /// + /// This method may not be optimized owing to implementation details; + /// `checked_log2` can produce results more efficiently for base 2, and + /// `checked_log10` can produce results more efficiently for base 10. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_log(self, base: Self) -> Option { + if self <= 0 || base <= 1 { + None + } else { + let mut n = 0; + let mut r = self; + + // Optimization for 128 bit wide integers. + if Self::BITS == 128 { + let b = Self::log2(self) / (Self::log2(base) + 1); + n += b; + r /= base.pow(b as u32); + } + + while r >= base { + r /= base; + n += 1; + } + Some(n) + } + } + + /// Returns the base 2 logarithm of the number. + /// + /// Returns `None` if the number is zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_log2(self) -> Option { + if self <= 0 { + None + } else { + // SAFETY: We just checked that this number is positive + let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) }; + Some(log) + } + } + + /// Returns the base 10 logarithm of the number. + /// + /// Returns `None` if the number is zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_log10(self) -> Option { + match int_log10::$ActualT(self as $ActualT) { + Some(s) => Some(s as Self), + None => None, + } + } + /// Checked negation. Computes `-self`, returning `None` unless `self == /// 0`. /// diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 9d9398fb56..c2270c864d 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -11,7 +11,6 @@ use crate::{convert, ops}; /// /// Early-exiting from [`Iterator::try_for_each`]: /// ``` -/// #![feature(control_flow_enum)] /// use std::ops::ControlFlow; /// /// let r = (2..100).try_for_each(|x| { @@ -26,7 +25,6 @@ use crate::{convert, ops}; /// /// A basic tree traversal: /// ```no_run -/// #![feature(control_flow_enum)] /// use std::ops::ControlFlow; /// /// pub struct TreeNode { @@ -48,42 +46,22 @@ use crate::{convert, ops}; /// } /// } /// ``` -#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] +#[stable(feature = "control_flow_enum_type", since = "1.55.0")] #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow { /// Move on to the next phase of the operation as normal. - #[cfg_attr(not(bootstrap), lang = "Continue")] + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] + #[lang = "Continue"] Continue(C), /// Exit the operation without running subsequent phases. - #[cfg_attr(not(bootstrap), lang = "Break")] + #[stable(feature = "control_flow_enum_type", since = "1.55.0")] + #[lang = "Break"] Break(B), // Yes, the order of the variants doesn't match the type parameters. // They're in this order so that `ControlFlow` <-> `Result` // is a no-op conversion in the `Try` implementation. } -#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] -#[cfg(bootstrap)] -impl ops::TryV1 for ControlFlow { - type Output = C; - type Error = B; - #[inline] - fn into_result(self) -> Result { - match self { - ControlFlow::Continue(y) => Ok(y), - ControlFlow::Break(x) => Err(x), - } - } - #[inline] - fn from_error(v: Self::Error) -> Self { - ControlFlow::Break(v) - } - #[inline] - fn from_ok(v: Self::Output) -> Self { - ControlFlow::Continue(v) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl ops::TryV2 for ControlFlow { type Output = C; @@ -184,31 +162,9 @@ impl ControlFlow { } } -#[cfg(bootstrap)] -impl ControlFlow { - /// Create a `ControlFlow` from any type implementing `Try`. - #[inline] - pub(crate) fn from_try(r: R) -> Self { - match R::into_result(r) { - Ok(v) => ControlFlow::Continue(v), - Err(v) => ControlFlow::Break(R::from_error(v)), - } - } - - /// Convert a `ControlFlow` into any type implementing `Try`; - #[inline] - pub(crate) fn into_try(self) -> R { - match self { - ControlFlow::Continue(v) => R::from_ok(v), - ControlFlow::Break(v) => v, - } - } -} - /// These are used only as part of implementing the iterator adapters. /// They have mediocre names and non-obvious semantics, so aren't /// currently on a path to potential stabilization. -#[cfg(not(bootstrap))] impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[inline] diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index f4b1ec377d..aa654aa557 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -11,7 +11,7 @@ /// This destructor consists of two components: /// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type. /// - The automatically generated "drop glue" which recursively calls the destructors -/// of the all fields of this value. +/// of all the fields of this value. /// /// As Rust automatically calls the destructors of all contained fields, /// you don't have to implement `Drop` in most cases. But there are some cases where diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 139a8c0eec..85e04740d9 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -147,8 +147,6 @@ mod function; mod generator; mod index; mod range; -#[cfg(bootstrap)] -mod r#try; mod try_trait; mod unsize; @@ -183,19 +181,10 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[stable(feature = "inclusive_range", since = "1.26.0")] pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; -#[unstable(feature = "try_trait", issue = "42327")] -#[cfg(bootstrap)] -pub use self::r#try::Try; - -#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] -#[cfg(bootstrap)] -pub(crate) use self::r#try::Try as TryV1; - #[unstable(feature = "try_trait_v2", issue = "84277")] pub use self::try_trait::FromResidual; #[unstable(feature = "try_trait_v2", issue = "84277")] -#[cfg(not(bootstrap))] pub use self::try_trait::Try; #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index bb948376bc..9bf0382312 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -737,14 +737,13 @@ impl Bound<&T> { /// # Examples /// /// ``` - /// #![feature(bound_cloned)] /// use std::ops::Bound::*; /// use std::ops::RangeBounds; /// /// assert_eq!((1..12).start_bound(), Included(&1)); /// assert_eq!((1..12).start_bound().cloned(), Included(1)); /// ``` - #[unstable(feature = "bound_cloned", issue = "61356")] + #[stable(feature = "bound_cloned", since = "1.55.0")] pub fn cloned(self) -> Bound { match self { Bound::Unbounded => Bound::Unbounded, diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs deleted file mode 100644 index 9d659e78d3..0000000000 --- a/library/core/src/ops/try.rs +++ /dev/null @@ -1,61 +0,0 @@ -/// A trait for customizing the behavior of the `?` operator. -/// -/// A type implementing `Try` is one that has a canonical way to view it -/// in terms of a success/failure dichotomy. This trait allows both -/// extracting those success or failure values from an existing instance and -/// creating a new instance from a success or failure value. -#[unstable(feature = "try_trait", issue = "42327")] -#[rustc_on_unimplemented( - on( - all( - any(from_method = "from_error", from_method = "from_ok"), - from_desugaring = "QuestionMark" - ), - message = "the `?` operator can only be used in {ItemContext} \ - that returns `Result` or `Option` \ - (or another type that implements `{Try}`)", - label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", - enclosing_scope = "this function should return `Result` or `Option` to accept `?`" - ), - on( - all(from_method = "into_result", from_desugaring = "QuestionMark"), - message = "the `?` operator can only be applied to values \ - that implement `{Try}`", - label = "the `?` operator cannot be applied to type `{Self}`" - ) -)] -#[doc(alias = "?")] -#[cfg_attr(bootstrap, lang = "try")] -pub trait Try { - /// The type of this value when viewed as successful. - #[unstable(feature = "try_trait", issue = "42327")] - type Output; // This no longer follows its RFC, but is only used in bootstrap. - /// The type of this value when viewed as failed. - #[unstable(feature = "try_trait", issue = "42327")] - type Error; - - /// Applies the "?" operator. A return of `Ok(t)` means that the - /// execution should continue normally, and the result of `?` is the - /// value `t`. A return of `Err(e)` means that execution should branch - /// to the innermost enclosing `catch`, or return from the function. - /// - /// If an `Err(e)` result is returned, the value `e` will be "wrapped" - /// in the return type of the enclosing scope (which must itself implement - /// `Try`). Specifically, the value `X::from_error(From::from(e))` - /// is returned, where `X` is the return type of the enclosing function. - #[cfg_attr(bootstrap, lang = "into_result")] - #[unstable(feature = "try_trait", issue = "42327")] - fn into_result(self) -> Result; - - /// Wrap an error value to construct the composite result. For example, - /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. - #[cfg_attr(bootstrap, lang = "from_error")] - #[unstable(feature = "try_trait", issue = "42327")] - fn from_error(v: Self::Error) -> Self; - - /// Wrap an OK value to construct the composite result. For example, - /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. - #[cfg_attr(bootstrap, lang = "from_ok")] - #[unstable(feature = "try_trait", issue = "42327")] - fn from_ok(v: Self::Output) -> Self; -} diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 1d9bc45261..bd46fb6f2c 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -55,7 +55,6 @@ use crate::ops::ControlFlow; /// into the return type using [`Try::from_output`]: /// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(control_flow_enum)] /// # use std::ops::{ControlFlow, Try}; /// fn simple_try_fold_2>( /// iter: impl Iterator, @@ -79,7 +78,6 @@ use crate::ops::ControlFlow; /// recreated from their corresponding residual, so we'll just call it: /// ``` /// # #![feature(try_trait_v2)] -/// # #![feature(control_flow_enum)] /// # use std::ops::{ControlFlow, Try}; /// pub fn simple_try_fold_3>( /// iter: impl Iterator, @@ -130,7 +128,7 @@ use crate::ops::ControlFlow; ) )] #[doc(alias = "?")] -#[cfg_attr(not(bootstrap), lang = "Try")] +#[lang = "Try"] pub trait Try: FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277")] @@ -170,7 +168,6 @@ pub trait Try: FromResidual { /// /// ``` /// #![feature(try_trait_v2)] - /// #![feature(control_flow_enum)] /// use std::ops::Try; /// /// assert_eq!( as Try>::from_output(3), Ok(3)); @@ -189,7 +186,7 @@ pub trait Try: FromResidual { /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() }); /// assert_eq!(r, Some(4)); /// ``` - #[cfg_attr(not(bootstrap), lang = "from_output")] + #[lang = "from_output"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_output(output: Self::Output) -> Self; @@ -202,7 +199,6 @@ pub trait Try: FromResidual { /// /// ``` /// #![feature(try_trait_v2)] - /// #![feature(control_flow_enum)] /// use std::ops::{ControlFlow, Try}; /// /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); @@ -217,7 +213,7 @@ pub trait Try: FromResidual { /// ControlFlow::Break(ControlFlow::Break(3)), /// ); /// ``` - #[cfg_attr(not(bootstrap), lang = "branch")] + #[lang = "branch"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn branch(self) -> ControlFlow; } @@ -329,7 +325,6 @@ pub trait FromResidual::Residual> { /// /// ``` /// #![feature(try_trait_v2)] - /// #![feature(control_flow_enum)] /// use std::ops::{ControlFlow, FromResidual}; /// /// assert_eq!(Result::::from_residual(Err(3_u8)), Err(3)); @@ -339,7 +334,7 @@ pub trait FromResidual::Residual> { /// ControlFlow::Break(5), /// ); /// ``` - #[cfg_attr(not(bootstrap), lang = "from_residual")] + #[lang = "from_residual"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_residual(residual: R) -> Self; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 4e7afca6a4..8057ff0759 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -49,9 +49,11 @@ //! no "null" references. Instead, Rust has *optional* pointers, like //! the optional owned box, [`Option`]`<`[`Box`]`>`. //! +//! [`Box`]: ../../std/boxed/struct.Box.html +//! //! The following example uses [`Option`] to create an optional box of -//! [`i32`]. Notice that in order to use the inner [`i32`] value first, the -//! `check_optional` function needs to use pattern matching to +//! [`i32`]. Notice that in order to use the inner [`i32`] value, the +//! `check_optional` function first needs to use pattern matching to //! determine whether the box has a value (i.e., it is [`Some(...)`][`Some`]) or //! not ([`None`]). //! @@ -83,6 +85,10 @@ //! * [`ptr::NonNull`] //! * `#[repr(transparent)]` struct around one of the types in this list. //! +//! [`Box`]: ../../std/boxed/struct.Box.html +//! [`num::NonZero*`]: crate::num +//! [`ptr::NonNull`]: crate::ptr::NonNull +//! //! This is called the "null pointer optimization" or NPO. //! //! It is further guaranteed that, for the cases above, one can @@ -90,6 +96,339 @@ //! from `Some::(_)` to `T` (but transmuting `None::` to `T` //! is undefined behaviour). //! +//! # Method overview +//! +//! In addition to working with pattern matching, [`Option`] provides a wide +//! variety of different methods. +//! +//! ## Querying the variant +//! +//! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`] +//! is [`Some`] or [`None`], respectively. +//! +//! [`is_none`]: Option::is_none +//! [`is_some`]: Option::is_some +//! +//! ## Adapters for working with references +//! +//! * [`as_ref`] converts from `&Option` to `Option<&T>` +//! * [`as_mut`] converts from `&mut Option` to `Option<&mut T>` +//! * [`as_deref`] converts from `&Option` to `Option<&T::Target>` +//! * [`as_deref_mut`] converts from `&mut Option` to +//! `Option<&mut T::Target>` +//! * [`as_pin_ref`] converts from [`Pin`]`<&Option>` to +//! `Option<`[`Pin`]`<&T>>` +//! * [`as_pin_mut`] converts from [`Pin`]`<&mut Option>` to +//! `Option<`[`Pin`]`<&mut T>>` +//! +//! [`as_deref`]: Option::as_deref +//! [`as_deref_mut`]: Option::as_deref_mut +//! [`as_mut`]: Option::as_mut +//! [`as_pin_mut`]: Option::as_pin_mut +//! [`as_pin_ref`]: Option::as_pin_ref +//! [`as_ref`]: Option::as_ref +//! +//! ## Extracting the contained value +//! +//! These methods extract the contained value in an [`Option`] when it +//! is the [`Some`] variant. If the [`Option`] is [`None`]: +//! +//! * [`expect`] panics with a provided custom message +//! * [`unwrap`] panics with a generic message +//! * [`unwrap_or`] returns the provided default value +//! * [`unwrap_or_default`] returns the default value of the type `T` +//! (which must implement the [`Default`] trait) +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function +//! +//! [`expect`]: Option::expect +//! [`unwrap`]: Option::unwrap +//! [`unwrap_or`]: Option::unwrap_or +//! [`unwrap_or_default`]: Option::unwrap_or_default +//! [`unwrap_or_else`]: Option::unwrap_or_else +//! +//! ## Transforming contained values +//! +//! These methods transform [`Option`] to [`Result`]: +//! +//! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! [`Err(err)`] using the provided default `err` value +//! * [`ok_or_else`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! a value of [`Err`] using the provided function +//! * [`transpose`] transposes an [`Option`] of a [`Result`] into a +//! [`Result`] of an [`Option`] +//! +//! [`Err(err)`]: Err +//! [`Ok(v)`]: Ok +//! [`Some(v)`]: Some +//! [`ok_or`]: Option::ok_or +//! [`ok_or_else`]: Option::ok_or_else +//! [`transpose`]: Option::transpose +//! +//! These methods transform the [`Some`] variant: +//! +//! * [`filter`] calls the provided predicate function on the contained +//! value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`] +//! if the function returns `true`; otherwise, returns [`None`] +//! * [`flatten`] removes one level of nesting from an +//! [`Option>`] +//! * [`map`] transforms [`Option`] to [`Option`] by applying the +//! provided function to the contained value of [`Some`] and leaving +//! [`None`] values unchanged +//! +//! [`Some(t)`]: Some +//! [`filter`]: Option::filter +//! [`flatten`]: Option::flatten +//! [`map`]: Option::map +//! +//! These methods transform [`Option`] to a value of a possibly +//! different type `U`: +//! +//! * [`map_or`] applies the provided function to the contained value of +//! [`Some`], or returns the provided default value if the [`Option`] is +//! [`None`] +//! * [`map_or_else`] applies the provided function to the contained value +//! of [`Some`], or returns the result of evaluating the provided +//! fallback function if the [`Option`] is [`None`] +//! +//! [`map_or`]: Option::map_or +//! [`map_or_else`]: Option::map_or_else +//! +//! These methods combine the [`Some`] variants of two [`Option`] values: +//! +//! * [`zip`] returns [`Some((s, o))`] if `self` is [`Some(s)`] and the +//! provided [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] +//! * [`zip_with`] calls the provided function `f` and returns +//! [`Some(f(s, o))`] if `self` is [`Some(s)`] and the provided +//! [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] +//! +//! [`Some(f(s, o))`]: Some +//! [`Some(o)`]: Some +//! [`Some(s)`]: Some +//! [`Some((s, o))`]: Some +//! [`zip`]: Option::zip +//! [`zip_with`]: Option::zip_with +//! +//! ## Boolean operators +//! +//! These methods treat the [`Option`] as a boolean value, where [`Some`] +//! acts like [`true`] and [`None`] acts like [`false`]. There are two +//! categories of these methods: ones that take an [`Option`] as input, and +//! ones that take a function as input (to be lazily evaluated). +//! +//! The [`and`], [`or`], and [`xor`] methods take another [`Option`] as +//! input, and produce an [`Option`] as output. Only the [`and`] method can +//! produce an [`Option`] value having a different inner type `U` than +//! [`Option`]. +//! +//! | method | self | input | output | +//! |---------|-----------|-----------|-----------| +//! | [`and`] | `None` | (ignored) | `None` | +//! | [`and`] | `Some(x)` | `None` | `None` | +//! | [`and`] | `Some(x)` | `Some(y)` | `Some(y)` | +//! | [`or`] | `None` | `None` | `None` | +//! | [`or`] | `None` | `Some(y)` | `Some(y)` | +//! | [`or`] | `Some(x)` | (ignored) | `Some(x)` | +//! | [`xor`] | `None` | `None` | `None` | +//! | [`xor`] | `None` | `Some(y)` | `Some(y)` | +//! | [`xor`] | `Some(x)` | `None` | `Some(x)` | +//! | [`xor`] | `Some(x)` | `Some(y)` | `None` | +//! +//! [`and`]: Option::and +//! [`or`]: Option::or +//! [`xor`]: Option::xor +//! +//! The [`and_then`] and [`or_else`] methods take a function as input, and +//! only evaluate the function when they need to produce a new value. Only +//! the [`and_then`] method can produce an [`Option`] value having a +//! different inner type `U` than [`Option`]. +//! +//! | method | self | function input | function result | output | +//! |--------------|-----------|----------------|-----------------|-----------| +//! | [`and_then`] | `None` | (not provided) | (not evaluated) | `None` | +//! | [`and_then`] | `Some(x)` | `x` | `None` | `None` | +//! | [`and_then`] | `Some(x)` | `x` | `Some(y)` | `Some(y)` | +//! | [`or_else`] | `None` | (not provided) | `None` | `None` | +//! | [`or_else`] | `None` | (not provided) | `Some(y)` | `Some(y)` | +//! | [`or_else`] | `Some(x)` | (not provided) | (not evaluated) | `Some(x)` | +//! +//! [`and_then`]: Option::and_then +//! [`or_else`]: Option::or_else +//! +//! This is an example of using methods like [`and_then`] and [`or`] in a +//! pipeline of method calls. Early stages of the pipeline pass failure +//! values ([`None`]) through unchanged, and continue processing on +//! success values ([`Some`]). Toward the end, [`or`] substitutes an error +//! message if it receives [`None`]. +//! +//! ``` +//! # use std::collections::BTreeMap; +//! let mut bt = BTreeMap::new(); +//! bt.insert(20u8, "foo"); +//! bt.insert(42u8, "bar"); +//! let res = vec![0u8, 1, 11, 200, 22] +//! .into_iter() +//! .map(|x| { +//! // `checked_sub()` returns `None` on error +//! x.checked_sub(1) +//! // same with `checked_mul()` +//! .and_then(|x| x.checked_mul(2)) +//! // `BTreeMap::get` returns `None` on error +//! .and_then(|x| bt.get(&x)) +//! // Substitute an error message if we have `None` so far +//! .or(Some(&"error!")) +//! .copied() +//! // Won't panic because we unconditionally used `Some` above +//! .unwrap() +//! }) +//! .collect::>(); +//! assert_eq!(res, ["error!", "error!", "foo", "error!", "bar"]); +//! ``` +//! +//! ## Iterating over `Option` +//! +//! An [`Option`] can be iterated over. This can be helpful if you need an +//! iterator that is conditionally empty. The iterator will either produce +//! a single value (when the [`Option`] is [`Some`]), or produce no values +//! (when the [`Option`] is [`None`]). For example, [`into_iter`] acts like +//! [`once(v)`] if the [`Option`] is [`Some(v)`], and like [`empty()`] if +//! the [`Option`] is [`None`]. +//! +//! [`Some(v)`]: Some +//! [`empty()`]: crate::iter::empty +//! [`once(v)`]: crate::iter::once +//! +//! Iterators over [`Option`] come in three types: +//! +//! * [`into_iter`] consumes the [`Option`] and produces the contained +//! value +//! * [`iter`] produces an immutable reference of type `&T` to the +//! contained value +//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the +//! contained value +//! +//! [`into_iter`]: Option::into_iter +//! [`iter`]: Option::iter +//! [`iter_mut`]: Option::iter_mut +//! +//! An iterator over [`Option`] can be useful when chaining iterators, for +//! example, to conditionally insert items. (It's not always necessary to +//! explicitly call an iterator constructor: many [`Iterator`] methods that +//! accept other iterators will also accept iterable types that implement +//! [`IntoIterator`], which includes [`Option`].) +//! +//! ``` +//! let yep = Some(42); +//! let nope = None; +//! // chain() already calls into_iter(), so we don't have to do so +//! let nums: Vec = (0..4).chain(yep).chain(4..8).collect(); +//! assert_eq!(nums, [0, 1, 2, 3, 42, 4, 5, 6, 7]); +//! let nums: Vec = (0..4).chain(nope).chain(4..8).collect(); +//! assert_eq!(nums, [0, 1, 2, 3, 4, 5, 6, 7]); +//! ``` +//! +//! One reason to chain iterators in this way is that a function returning +//! `impl Iterator` must have all possible return values be of the same +//! concrete type. Chaining an iterated [`Option`] can help with that. +//! +//! ``` +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types matching +//! match do_insert { +//! true => return (0..4).chain(Some(42)).chain(4..8), +//! false => return (0..4).chain(None).chain(4..8), +//! } +//! } +//! println!("{:?}", make_iter(true).collect::>()); +//! println!("{:?}", make_iter(false).collect::>()); +//! ``` +//! +//! If we try to do the same thing, but using [`once()`] and [`empty()`], +//! we can't return `impl Iterator` anymore because the concrete types of +//! the return values differ. +//! +//! [`empty()`]: crate::iter::empty +//! [`once()`]: crate::iter::once +//! +//! ```compile_fail,E0308 +//! # use std::iter::{empty, once}; +//! // This won't compile because all possible returns from the function +//! // must have the same concrete type. +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types not matching +//! match do_insert { +//! true => return (0..4).chain(once(42)).chain(4..8), +//! false => return (0..4).chain(empty()).chain(4..8), +//! } +//! } +//! ``` +//! +//! ## Collecting into `Option` +//! +//! [`Option`] implements the [`FromIterator`][impl-FromIterator] trait, +//! which allows an iterator over [`Option`] values to be collected into an +//! [`Option`] of a collection of each contained value of the original +//! [`Option`] values, or [`None`] if any of the elements was [`None`]. +//! +//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E +//! +//! ``` +//! let v = vec![Some(2), Some(4), None, Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, None); +//! let v = vec![Some(2), Some(4), Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, Some(vec![2, 4, 8])); +//! ``` +//! +//! [`Option`] also implements the [`Product`][impl-Product] and +//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Option`] values +//! to provide the [`product`][Iterator::product] and +//! [`sum`][Iterator::sum] methods. +//! +//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E +//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E +//! +//! ``` +//! let v = vec![None, Some(1), Some(2), Some(3)]; +//! let res: Option = v.into_iter().sum(); +//! assert_eq!(res, None); +//! let v = vec![Some(1), Some(2), Some(21)]; +//! let res: Option = v.into_iter().product(); +//! assert_eq!(res, Some(42)); +//! ``` +//! +//! ## Modifying an [`Option`] in-place +//! +//! These methods return a mutable reference to the contained value of an +//! [`Option`]: +//! +//! * [`insert`] inserts a value, dropping any old contents +//! * [`get_or_insert`] gets the current value, inserting a provided +//! default value if it is [`None`] +//! * [`get_or_insert_default`] gets the current value, inserting the +//! default value of type `T` (which must implement [`Default`]) if it is +//! [`None`] +//! * [`get_or_insert_with`] gets the current value, inserting a default +//! computed by the provided function if it is [`None`] +//! +//! [`get_or_insert`]: Option::get_or_insert +//! [`get_or_insert_default`]: Option::get_or_insert_default +//! [`get_or_insert_with`]: Option::get_or_insert_with +//! [`insert`]: Option::insert +//! +//! These methods transfer ownership of the contained value of an +//! [`Option`]: +//! +//! * [`take`] takes ownership of the contained value of an [`Option`], if +//! any, replacing the [`Option`] with [`None`] +//! * [`replace`] takes ownership of the contained value of an [`Option`], +//! if any, replacing the [`Option`] with a [`Some`] containing the +//! provided value +//! +//! [`replace`]: Option::replace +//! [`take`]: Option::take +//! //! # Examples //! //! Basic pattern matching on [`Option`]: @@ -141,11 +480,6 @@ //! None => println!("there are no animals :("), //! } //! ``` -//! -//! [`Box`]: ../../std/boxed/struct.Box.html -//! [`Box`]: ../../std/boxed/struct.Box.html -//! [`num::NonZero*`]: crate::num -//! [`ptr::NonNull`]: crate::ptr::NonNull #![stable(feature = "rust1", since = "1.0.0")] @@ -845,6 +1179,7 @@ impl Option { /// *val = 3; /// assert_eq!(opt.unwrap(), 3); /// ``` + #[must_use = "if you intended to set a value, consider assignment instead"] #[inline] #[stable(feature = "option_insert", since = "1.53.0")] pub fn insert(&mut self, value: T) -> &mut T { @@ -1350,7 +1685,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. /// The [`map`] method takes the `self` argument by value, consuming the original, - /// so this technique uses `as_ref` to first take an `Option` to a reference + /// so this technique uses `from` to first take an `Option` to a reference /// to the value inside the original. /// /// [`map`]: Option::map @@ -1636,38 +1971,6 @@ impl> FromIterator> for Option { } } -/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish -/// to allow `x?` (where `x` is an `Option`) to be converted into your error type, you can -/// implement `impl From` for `YourErrorType`. In that case, `x?` within a function that -/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result. -#[rustc_diagnostic_item = "none_error"] -#[unstable(feature = "try_trait", issue = "42327")] -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -#[cfg(bootstrap)] -pub struct NoneError; - -#[unstable(feature = "try_trait", issue = "42327")] -#[cfg(bootstrap)] -impl ops::TryV1 for Option { - type Output = T; - type Error = NoneError; - - #[inline] - fn into_result(self) -> Result { - self.ok_or(NoneError) - } - - #[inline] - fn from_ok(v: T) -> Self { - Some(v) - } - - #[inline] - fn from_error(_: NoneError) -> Self { - None - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl ops::TryV2 for Option { type Output = T; diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index 79753c1fb6..ccd36a428e 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -11,9 +11,9 @@ pub mod v1; /// The 2015 version of the core prelude. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2015", issue = "85684")] +#[stable(feature = "prelude_2015", since = "1.55.0")] pub mod rust_2015 { - #[unstable(feature = "prelude_2015", issue = "85684")] + #[stable(feature = "prelude_2015", since = "1.55.0")] #[doc(no_inline)] pub use super::v1::*; } @@ -21,9 +21,9 @@ pub mod rust_2015 { /// The 2018 version of the core prelude. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2018", issue = "85684")] +#[stable(feature = "prelude_2018", since = "1.55.0")] pub mod rust_2018 { - #[unstable(feature = "prelude_2018", issue = "85684")] + #[stable(feature = "prelude_2018", since = "1.55.0")] #[doc(no_inline)] pub use super::v1::*; } @@ -31,17 +31,17 @@ pub mod rust_2018 { /// The 2021 version of the core prelude. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2021", issue = "85684")] +#[stable(feature = "prelude_2021", since = "1.55.0")] pub mod rust_2021 { - #[unstable(feature = "prelude_2021", issue = "85684")] + #[stable(feature = "prelude_2021", since = "1.55.0")] #[doc(no_inline)] pub use super::v1::*; - #[unstable(feature = "prelude_2021", issue = "85684")] + #[stable(feature = "prelude_2021", since = "1.55.0")] #[doc(no_inline)] pub use crate::iter::FromIterator; - #[unstable(feature = "prelude_2021", issue = "85684")] + #[stable(feature = "prelude_2021", since = "1.55.0")] #[doc(no_inline)] pub use crate::convert::{TryFrom, TryInto}; } diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index c89fe57cb0..6b51ef5b01 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -55,11 +55,27 @@ pub use crate::hash::macros::Hash; #[allow(deprecated)] #[doc(no_inline)] pub use crate::{ - asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, - format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax, - module_path, option_env, stringify, trace_macros, + assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, + format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, module_path, + option_env, stringify, trace_macros, }; +#[unstable( + feature = "asm", + issue = "72016", + reason = "inline assembly is not stable enough for use and is subject to change" +)] +#[doc(no_inline)] +pub use crate::arch::asm; + +#[unstable( + feature = "global_asm", + issue = "35119", + reason = "`global_asm!` is not stable enough for use and is subject to change" +)] +#[doc(no_inline)] +pub use crate::arch::global_asm; + #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated, deprecated_in_future)] #[doc(no_inline)] diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 7c7dce0ce7..287ae69acd 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -101,7 +101,7 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { /// /// This function is safe but the returned pointer is not necessarily safe to dereference. /// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements. -/// For trait objects, the metadata must come from a pointer to the same underlying ereased type. +/// For trait objects, the metadata must come from a pointer to the same underlying erased type. /// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6a6cee0911..4b81c39ea1 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -430,7 +430,8 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { } #[inline] -pub(crate) unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { +#[rustc_const_unstable(feature = "const_swap", issue = "83163")] +pub(crate) const unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary // reinterpretation of values as (chunkable) byte arrays, and the loop in the // block optimization in `swap_nonoverlapping_bytes` is hard to rewrite back @@ -563,7 +564,8 @@ const unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn replace(dst: *mut T, mut src: T) -> T { +#[rustc_const_unstable(feature = "const_replace", issue = "83164")] +pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be // cast to a mutable reference (valid for writes, aligned, initialized), // and cannot overlap `src` since `dst` must point to a distinct @@ -869,10 +871,12 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn write(dst: *mut T, src: T) { +#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +pub const unsafe fn write(dst: *mut T, src: T) { // We are calling the intrinsics directly to avoid function calls in the generated code // as `intrinsics::copy_nonoverlapping` is a wrapper function. extern "rust-intrinsic" { + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } @@ -964,7 +968,7 @@ pub unsafe fn write(dst: *mut T, src: T) { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")] +#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] pub const unsafe fn write_unaligned(dst: *mut T, src: T) { // SAFETY: the caller must guarantee that `dst` is valid for writes. // `dst` cannot overlap `src` because the caller has mutable access diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index a642404154..93ee74719f 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1002,8 +1002,9 @@ impl *mut T { /// /// [`ptr::write`]: crate::ptr::write() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline(always)] - pub unsafe fn write(self, val: T) + pub const unsafe fn write(self, val: T) where T: Sized, { @@ -1056,7 +1057,7 @@ impl *mut T { /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "none")] + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline(always)] pub const unsafe fn write_unaligned(self, val: T) where diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 1c65518af0..3ab40f1faa 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -194,7 +194,7 @@ impl NonNull { } } - /// Decompose a (possibly wide) pointer into is address and metadata components. + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`]. #[unstable(feature = "ptr_metadata", issue = "81513")] diff --git a/library/core/src/raw.rs b/library/core/src/raw.rs deleted file mode 100644 index 6d1e28f4cd..0000000000 --- a/library/core/src/raw.rs +++ /dev/null @@ -1,90 +0,0 @@ -#![allow(missing_docs)] -#![unstable(feature = "raw", issue = "27751")] -#![rustc_deprecated( - since = "1.53.0", - reason = "use pointer metadata APIs instead https://github.com/rust-lang/rust/issues/81513" -)] - -//! Contains struct definitions for the layout of compiler built-in types. -//! -//! They can be used as targets of transmutes in unsafe code for manipulating -//! the raw representations directly. -//! -//! Their definition should always match the ABI defined in -//! `rustc_middle::ty::layout`. - -/// The representation of a trait object like `&dyn SomeTrait`. -/// -/// This struct has the same layout as types like `&dyn SomeTrait` and -/// `Box`. -/// -/// `TraitObject` is guaranteed to match layouts, but it is not the -/// type of trait objects (e.g., the fields are not directly accessible -/// on a `&dyn SomeTrait`) nor does it control that layout (changing the -/// definition will not change the layout of a `&dyn SomeTrait`). It is -/// only designed to be used by unsafe code that needs to manipulate -/// the low-level details. -/// -/// There is no way to refer to all trait objects generically, so the only -/// way to create values of this type is with functions like -/// [`std::mem::transmute`][transmute]. Similarly, the only way to create a true -/// trait object from a `TraitObject` value is with `transmute`. -/// -/// [transmute]: crate::intrinsics::transmute -/// -/// Synthesizing a trait object with mismatched types—one where the -/// vtable does not correspond to the type of the value to which the -/// data pointer points—is highly likely to lead to undefined -/// behavior. -/// -/// # Examples -/// -/// ``` -/// #![feature(raw)] -/// -/// use std::{mem, raw}; -/// -/// // an example trait -/// trait Foo { -/// fn bar(&self) -> i32; -/// } -/// -/// impl Foo for i32 { -/// fn bar(&self) -> i32 { -/// *self + 1 -/// } -/// } -/// -/// let value: i32 = 123; -/// -/// // let the compiler make a trait object -/// let object: &dyn Foo = &value; -/// -/// // look at the raw representation -/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) }; -/// -/// // the data pointer is the address of `value` -/// assert_eq!(raw_object.data as *const i32, &value as *const _); -/// -/// let other_value: i32 = 456; -/// -/// // construct a new object, pointing to a different `i32`, being -/// // careful to use the `i32` vtable from `object` -/// let synthesized: &dyn Foo = unsafe { -/// mem::transmute(raw::TraitObject { -/// data: &other_value as *const _ as *mut (), -/// vtable: raw_object.vtable, -/// }) -/// }; -/// -/// // it should work just as if we had constructed a trait object out of -/// // `other_value` directly -/// assert_eq!(synthesized.bar(), 457); -/// ``` -#[repr(C)] -#[derive(Copy, Clone)] -#[allow(missing_debug_implementations)] -pub struct TraitObject { - pub data: *mut (), - pub vtable: *mut (), -} diff --git a/library/core/src/result.rs b/library/core/src/result.rs index babd0a0b55..53aaa5219b 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -224,6 +224,250 @@ //! [`Ok(T)`]: Ok //! [`Err(E)`]: Err //! [`io::Error`]: ../../std/io/struct.Error.html +//! +//! # Method overview +//! +//! In addition to working with pattern matching, [`Result`] provides a +//! wide variety of different methods. +//! +//! ## Querying the variant +//! +//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] +//! is [`Ok`] or [`Err`], respectively. +//! +//! [`is_err`]: Result::is_err +//! [`is_ok`]: Result::is_ok +//! +//! ## Adapters for working with references +//! +//! * [`as_ref`] converts from `&Result` to `Result<&T, &E>` +//! * [`as_mut`] converts from `&mut Result` to `Result<&mut T, &mut E>` +//! * [`as_deref`] converts from `&Result` to `Result<&T::Target, &E>` +//! * [`as_deref_mut`] converts from `&mut Result` to +//! `Result<&mut T::Target, &mut E>` +//! +//! [`as_deref`]: Result::as_deref +//! [`as_deref_mut`]: Result::as_deref_mut +//! [`as_mut`]: Result::as_mut +//! [`as_ref`]: Result::as_ref +//! +//! ## Extracting contained values +//! +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Ok`] variant. If the [`Result`] is [`Err`]: +//! +//! * [`expect`] panics with a provided custom message +//! * [`unwrap`] panics with a generic message +//! * [`unwrap_or`] returns the provided default value +//! * [`unwrap_or_default`] returns the default value of the type `T` +//! (which must implement the [`Default`] trait) +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function +//! +//! The panicking methods [`expect`] and [`unwrap`] require `E` to +//! implement the [`Debug`] trait. +//! +//! [`Debug`]: crate::fmt::Debug +//! [`expect`]: Result::expect +//! [`unwrap`]: Result::unwrap +//! [`unwrap_or`]: Result::unwrap_or +//! [`unwrap_or_default`]: Result::unwrap_or_default +//! [`unwrap_or_else`]: Result::unwrap_or_else +//! +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Err`] variant. They require `T` to implement the [`Debug`] +//! trait. If the [`Result`] is [`Ok`]: +//! +//! * [`expect_err`] panics with a provided custom message +//! * [`unwrap_err`] panics with a generic message +//! +//! [`Debug`]: crate::fmt::Debug +//! [`expect_err`]: Result::expect_err +//! [`unwrap_err`]: Result::unwrap_err +//! +//! ## Transforming contained values +//! +//! These methods transform [`Result`] to [`Option`]: +//! +//! * [`err`][Result::err] transforms [`Result`] into [`Option`], +//! mapping [`Err(e)`] to [`Some(e)`] and [`Ok(v)`] to [`None`] +//! * [`ok`][Result::ok] transforms [`Result`] into [`Option`], +//! mapping [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`] +//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an +//! [`Option`] of a [`Result`] +//! +// Do NOT add link reference definitions for `err` or `ok`, because they +// will generate numerous incorrect URLs for `Err` and `Ok` elsewhere, due +// to case folding. +//! +//! [`Err(e)`]: Err +//! [`Ok(v)`]: Ok +//! [`Some(e)`]: Option::Some +//! [`Some(v)`]: Option::Some +//! [`transpose`]: Result::transpose +//! +//! This method transforms the contained value of the [`Ok`] variant: +//! +//! * [`map`] transforms [`Result`] into [`Result`] by applying +//! the provided function to the contained value of [`Ok`] and leaving +//! [`Err`] values unchanged +//! +//! [`map`]: Result::map +//! +//! This method transforms the contained value of the [`Err`] variant: +//! +//! * [`map_err`] transforms [`Result`] into [`Result`] by +//! applying the provided function to the contained value of [`Err`] and +//! leaving [`Ok`] values unchanged +//! +//! [`map_err`]: Result::map_err +//! +//! These methods transform a [`Result`] into a value of a possibly +//! different type `U`: +//! +//! * [`map_or`] applies the provided function to the contained value of +//! [`Ok`], or returns the provided default value if the [`Result`] is +//! [`Err`] +//! * [`map_or_else`] applies the provided function to the contained value +//! of [`Ok`], or applies the provided fallback function to the contained +//! value of [`Err`] +//! +//! [`map_or`]: Result::map_or +//! [`map_or_else`]: Result::map_or_else +//! +//! ## Boolean operators +//! +//! These methods treat the [`Result`] as a boolean value, where [`Ok`] +//! acts like [`true`] and [`Err`] acts like [`false`]. There are two +//! categories of these methods: ones that take a [`Result`] as input, and +//! ones that take a function as input (to be lazily evaluated). +//! +//! The [`and`] and [`or`] methods take another [`Result`] as input, and +//! produce a [`Result`] as output. The [`and`] method can produce a +//! [`Result`] value having a different inner type `U` than +//! [`Result`]. The [`or`] method can produce a [`Result`] +//! value having a different error type `F` than [`Result`]. +//! +//! | method | self | input | output | +//! |---------|----------|-----------|----------| +//! | [`and`] | `Err(e)` | (ignored) | `Err(e)` | +//! | [`and`] | `Ok(x)` | `Err(d)` | `Err(d)` | +//! | [`and`] | `Ok(x)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Err(e)` | `Err(d)` | `Err(d)` | +//! | [`or`] | `Err(e)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Ok(x)` | (ignored) | `Ok(x)` | +//! +//! [`and`]: Result::and +//! [`or`]: Result::or +//! +//! The [`and_then`] and [`or_else`] methods take a function as input, and +//! only evaluate the function when they need to produce a new value. The +//! [`and_then`] method can produce a [`Result`] value having a +//! different inner type `U` than [`Result`]. The [`or_else`] method +//! can produce a [`Result`] value having a different error type `F` +//! than [`Result`]. +//! +//! | method | self | function input | function result | output | +//! |--------------|----------|----------------|-----------------|----------| +//! | [`and_then`] | `Err(e)` | (not provided) | (not evaluated) | `Err(e)` | +//! | [`and_then`] | `Ok(x)` | `x` | `Err(d)` | `Err(d)` | +//! | [`and_then`] | `Ok(x)` | `x` | `Ok(y)` | `Ok(y)` | +//! | [`or_else`] | `Err(e)` | `e` | `Err(d)` | `Err(d)` | +//! | [`or_else`] | `Err(e)` | `e` | `Ok(y)` | `Ok(y)` | +//! | [`or_else`] | `Ok(x)` | (not provided) | (not evaluated) | `Ok(x)` | +//! +//! [`and_then`]: Result::and_then +//! [`or_else`]: Result::or_else +//! +//! ## Iterating over `Result` +//! +//! A [`Result`] can be iterated over. This can be helpful if you need an +//! iterator that is conditionally empty. The iterator will either produce +//! a single value (when the [`Result`] is [`Ok`]), or produce no values +//! (when the [`Result`] is [`Err`]). For example, [`into_iter`] acts like +//! [`once(v)`] if the [`Result`] is [`Ok(v)`], and like [`empty()`] if the +//! [`Result`] is [`Err`]. +//! +//! [`Ok(v)`]: Ok +//! [`empty()`]: crate::iter::empty +//! [`once(v)`]: crate::iter::once +//! +//! Iterators over [`Result`] come in three types: +//! +//! * [`into_iter`] consumes the [`Result`] and produces the contained +//! value +//! * [`iter`] produces an immutable reference of type `&T` to the +//! contained value +//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the +//! contained value +//! +//! See [Iterating over `Option`] for examples of how this can be useful. +//! +//! [Iterating over `Option`]: crate::option#iterating-over-option +//! [`into_iter`]: Result::into_iter +//! [`iter`]: Result::iter +//! [`iter_mut`]: Result::iter_mut +//! +//! You might want to use an iterator chain to do multiple instances of an +//! operation that can fail, but would like to ignore failures while +//! continuing to process the successful results. In this example, we take +//! advantage of the iterable nature of [`Result`] to select only the +//! [`Ok`] values using [`flatten`][Iterator::flatten]. +//! +//! ``` +//! # use std::str::FromStr; +//! let mut results = vec![]; +//! let mut errs = vec![]; +//! let nums: Vec<_> = vec!["17", "not a number", "99", "-27", "768"] +//! .into_iter() +//! .map(u8::from_str) +//! // Save clones of the raw `Result` values to inspect +//! .inspect(|x| results.push(x.clone())) +//! // Challenge: explain how this captures only the `Err` values +//! .inspect(|x| errs.extend(x.clone().err())) +//! .flatten() +//! .collect(); +//! assert_eq!(errs.len(), 3); +//! assert_eq!(nums, [17, 99]); +//! println!("results {:?}", results); +//! println!("errs {:?}", errs); +//! println!("nums {:?}", nums); +//! ``` +//! +//! ## Collecting into `Result` +//! +//! [`Result`] implements the [`FromIterator`][impl-FromIterator] trait, +//! which allows an iterator over [`Result`] values to be collected into a +//! [`Result`] of a collection of each contained value of the original +//! [`Result`] values, or [`Err`] if any of the elements was [`Err`]. +//! +//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E +//! +//! ``` +//! let v = vec![Ok(2), Ok(4), Err("err!"), Ok(8)]; +//! let res: Result, &str> = v.into_iter().collect(); +//! assert_eq!(res, Err("err!")); +//! let v = vec![Ok(2), Ok(4), Ok(8)]; +//! let res: Result, &str> = v.into_iter().collect(); +//! assert_eq!(res, Ok(vec![2, 4, 8])); +//! ``` +//! +//! [`Result`] also implements the [`Product`][impl-Product] and +//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Result`] values +//! to provide the [`product`][Iterator::product] and +//! [`sum`][Iterator::sum] methods. +//! +//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E +//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E +//! +//! ``` +//! let v = vec![Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")]; +//! let res: Result = v.into_iter().sum(); +//! assert_eq!(res, Err("error!")); +//! let v: Vec> = vec![Ok(1), Ok(2), Ok(21)]; +//! let res: Result = v.into_iter().product(); +//! assert_eq!(res, Ok(42)); +//! ``` #![stable(feature = "rust1", since = "1.0.0")] @@ -1626,28 +1870,6 @@ impl> FromIterator> for Result { } } -#[unstable(feature = "try_trait", issue = "42327")] -#[cfg(bootstrap)] -impl ops::TryV1 for Result { - type Output = T; - type Error = E; - - #[inline] - fn into_result(self) -> Self { - self - } - - #[inline] - fn from_ok(v: T) -> Self { - Ok(v) - } - - #[inline] - fn from_error(v: E) -> Self { - Err(v) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl ops::TryV2 for Result { type Output = T; diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 1ee662c6c8..5cbc6343e3 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1418,18 +1418,17 @@ impl<'a, T> Iterator for Chunks<'a, T> { #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { let start = idx * self.chunk_size; - let end = match start.checked_add(self.chunk_size) { - None => self.v.len(), - Some(end) => cmp::min(end, self.v.len()), - }; // SAFETY: the caller guarantees that `i` is in bounds, // which means that `start` must be in bounds of the - // underlying `self.v` slice, and we made sure that `end` + // underlying `self.v` slice, and we made sure that `len` // is also in bounds of `self.v`. Thus, `start` cannot overflow // an `isize`, and the slice constructed by `from_raw_parts` // is a subslice of `self.v` which is guaranteed to be valid // for the lifetime `'a` of `self.v`. - unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) } + unsafe { + let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size); + from_raw_parts(self.v.as_ptr().add(start), len) + } } } @@ -1457,7 +1456,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } else { let start = (len - 1 - n) * self.chunk_size; let end = match start.checked_add(self.chunk_size) { - Some(res) => cmp::min(res, self.v.len()), + Some(res) => cmp::min(self.v.len(), res), None => self.v.len(), }; let nth_back = &self.v[start..end]; @@ -1579,17 +1578,16 @@ impl<'a, T> Iterator for ChunksMut<'a, T> { #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { let start = idx * self.chunk_size; - let end = match start.checked_add(self.chunk_size) { - None => self.v.len(), - Some(end) => cmp::min(end, self.v.len()), - }; // SAFETY: see comments for `Chunks::__iterator_get_unchecked`. // // Also note that the caller also guarantees that we're never called // with the same index again, and that no other methods that will // access this subslice are called, so it is valid for the returned // slice to be mutable. - unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) } + unsafe { + let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size); + from_raw_parts_mut(self.v.as_mut_ptr().add(start), len) + } } } @@ -1619,7 +1617,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { } else { let start = (len - 1 - n) * self.chunk_size; let end = match start.checked_add(self.chunk_size) { - Some(res) => cmp::min(res, self.v.len()), + Some(res) => cmp::min(self.v.len(), res), None => self.v.len(), }; let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); @@ -2148,6 +2146,7 @@ impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { self.iter.last() } + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a [T; N] { // SAFETY: The safety guarantees of `__iterator_get_unchecked` are // transferred to the caller. @@ -2260,6 +2259,7 @@ impl<'a, T, const N: usize> Iterator for ArrayChunksMut<'a, T, N> { self.iter.last() } + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a mut [T; N] { // SAFETY: The safety guarantees of `__iterator_get_unchecked` are transferred to // the caller. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 0e5c5ee726..de25c984ab 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -95,7 +95,7 @@ impl [T] { /// let a = [1, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` - #[doc(alias = "length")] + #[cfg_attr(not(bootstrap), lang = "slice_len_fn")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")] #[inline] @@ -3468,27 +3468,7 @@ impl [T] { where P: FnMut(&T) -> bool, { - let mut left = 0; - let mut right = self.len(); - - while left != right { - let mid = left + (right - left) / 2; - // SAFETY: When `left < right`, `left <= mid < right`. - // Therefore `left` always increases and `right` always decreases, - // and either of them is selected. In both cases `left <= right` is - // satisfied. Therefore if `left < right` in a step, `left <= right` - // is satisfied in the next step. Therefore as long as `left != right`, - // `0 <= left < right <= len` is satisfied and if this case - // `0 <= mid < len` is satisfied too. - let value = unsafe { self.get_unchecked(mid) }; - if pred(value) { - left = mid + 1; - } else { - right = mid; - } - } - - left + self.binary_search_by(|x| if pred(x) { Less } else { Greater }).unwrap_or_else(|i| i) } } diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs index a89596b15e..7528927ef3 100644 --- a/library/core/src/slice/rotate.rs +++ b/library/core/src/slice/rotate.rs @@ -1,5 +1,3 @@ -// ignore-tidy-undocumented-unsafe - use crate::cmp; use crate::mem::{self, MaybeUninit}; use crate::ptr; @@ -79,8 +77,10 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) // the way until about `left + right == 32`, but the worst case performance breaks even // around 16. 24 was chosen as middle ground. If the size of `T` is larger than 4 // `usize`s, this algorithm also outperforms other algorithms. + // SAFETY: callers must ensure `mid - left` is valid for reading and writing. let x = unsafe { mid.sub(left) }; // beginning of first round + // SAFETY: see previous comment. let mut tmp: T = unsafe { x.read() }; let mut i = right; // `gcd` can be found before hand by calculating `gcd(left + right, right)`, @@ -92,6 +92,21 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) // the very end. This is possibly due to the fact that swapping or replacing temporaries // uses only one memory address in the loop instead of needing to manage two. loop { + // [long-safety-expl] + // SAFETY: callers must ensure `[left, left+mid+right)` are all valid for reading and + // writing. + // + // - `i` start with `right` so `mid-left <= x+i = x+right = mid-left+right < mid+right` + // - `i <= left+right-1` is always true + // - if `i < left`, `right` is added so `i < left+right` and on the next + // iteration `left` is removed from `i` so it doesn't go further + // - if `i >= left`, `left` is removed immediately and so it doesn't go further. + // - overflows cannot happen for `i` since the function's safety contract ask for + // `mid+right-1 = x+left+right` to be valid for writing + // - underflows cannot happen because `i` must be bigger or equal to `left` for + // a substraction of `left` to happen. + // + // So `x+i` is valid for reading and writing if the caller respected the contract tmp = unsafe { x.add(i).replace(tmp) }; // instead of incrementing `i` and then checking if it is outside the bounds, we // check if `i` will go outside the bounds on the next increment. This prevents @@ -100,6 +115,8 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) i -= left; if i == 0 { // end of first round + // SAFETY: tmp has been read from a valid source and x is valid for writing + // according to the caller. unsafe { x.write(tmp) }; break; } @@ -113,13 +130,24 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) } // finish the chunk with more rounds for start in 1..gcd { + // SAFETY: `gcd` is at most equal to `right` so all values in `1..gcd` are valid for + // reading and writing as per the function's safety contract, see [long-safety-expl] + // above tmp = unsafe { x.add(start).read() }; + // [safety-expl-addition] + // + // Here `start < gcd` so `start < right` so `i < right+right`: `right` being the + // greatest common divisor of `(left+right, right)` means that `left = right` so + // `i < left+right` so `x+i = mid-left+i` is always valid for reading and writing + // according to the function's safety contract. i = start + right; loop { + // SAFETY: see [long-safety-expl] and [safety-expl-addition] tmp = unsafe { x.add(i).replace(tmp) }; if i >= left { i -= left; if i == start { + // SAFETY: see [long-safety-expl] and [safety-expl-addition] unsafe { x.add(start).write(tmp) }; break; } @@ -135,14 +163,30 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) // The `[T; 0]` here is to ensure this is appropriately aligned for T let mut rawarray = MaybeUninit::<(BufType, [T; 0])>::uninit(); let buf = rawarray.as_mut_ptr() as *mut T; + // SAFETY: `mid-left <= mid-left+right < mid+right` let dim = unsafe { mid.sub(left).add(right) }; if left <= right { + // SAFETY: + // + // 1) The `else if` condition about the sizes ensures `[mid-left; left]` will fit in + // `buf` without overflow and `buf` was created just above and so cannot be + // overlapped with any value of `[mid-left; left]` + // 2) [mid-left, mid+right) are all valid for reading and writing and we don't care + // about overlaps here. + // 3) The `if` condition about `left <= right` ensures writing `left` elements to + // `dim = mid-left+right` is valid because: + // - `buf` is valid and `left` elements were written in it in 1) + // - `dim+left = mid-left+right+left = mid+right` and we write `[dim, dim+left)` unsafe { + // 1) ptr::copy_nonoverlapping(mid.sub(left), buf, left); + // 2) ptr::copy(mid, mid.sub(left), right); + // 3) ptr::copy_nonoverlapping(buf, dim, left); } } else { + // SAFETY: same reasoning as above but with `left` and `right` reversed unsafe { ptr::copy_nonoverlapping(mid, buf, right); ptr::copy(mid.sub(left), dim, left); @@ -156,6 +200,10 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) // of this algorithm would be, and swapping using that last chunk instead of swapping // adjacent chunks like this algorithm is doing, but this way is still faster. loop { + // SAFETY: + // `left >= right` so `[mid-right, mid+right)` is valid for reading and writing + // Substracting `right` from `mid` each turn is counterbalanced by the addition and + // check after it. unsafe { ptr::swap_nonoverlapping(mid.sub(right), mid, right); mid = mid.sub(right); @@ -168,6 +216,10 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) } else { // Algorithm 3, `left < right` loop { + // SAFETY: `[mid-left, mid+left)` is valid for reading and writing because + // `left < right` so `mid+left < mid+right`. + // Adding `left` to `mid` each turn is counterbalanced by the substraction and check + // after it. unsafe { ptr::swap_nonoverlapping(mid.sub(left), mid, left); mid = mid.add(left); diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 2a7693d27e..36c2c4abdb 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -227,7 +227,7 @@ where /// Partitioning is performed block-by-block in order to minimize the cost of branching operations. /// This idea is presented in the [BlockQuicksort][pdf] paper. /// -/// [pdf]: http://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf +/// [pdf]: https://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize where F: FnMut(&T, &T) -> bool, diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 05ff7bb120..a51d142074 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -156,7 +156,7 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")] +#[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")] #[rustc_allow_const_fn_unstable(const_fn_transmute)] pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8. diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index ccf7b20285..aa735a14cb 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -118,10 +118,9 @@ impl fmt::Display for Utf8Error { /// /// [`from_str`]: super::FromStr::from_str #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] #[stable(feature = "rust1", since = "1.0.0")] -pub struct ParseBoolError { - pub(super) _priv: (), -} +pub struct ParseBoolError; #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for ParseBoolError { diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 6ec6b70b57..a577476457 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -295,6 +295,7 @@ impl Iterator for Bytes<'_> { } #[inline] + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 { // SAFETY: the caller must uphold the safety contract // for `Iterator::__iterator_get_unchecked`. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 065acd3f38..7ca95a02dd 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -138,7 +138,6 @@ impl str { /// assert_eq!("ƒoo".len(), 4); // fancy f! /// assert_eq!("ƒoo".chars().count(), 3); /// ``` - #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")] #[inline] diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 0a2743b1c3..12d79a56a5 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -585,7 +585,7 @@ impl FromStr for bool { match s { "true" => Ok(true), "false" => Ok(false), - _ => Err(ParseBoolError { _priv: () }), + _ => Err(ParseBoolError), } } } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index f1a115563f..b673b36c10 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2648,7 +2648,11 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// /// pub fn lock(&self) { /// // Wait until the old value is `false`. -/// while self.flag.compare_and_swap(false, true, Ordering::Relaxed) != false {} +/// while self +/// .flag +/// .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed) +/// .is_err() +/// {} /// // This fence synchronizes-with store in `unlock`. /// fence(Ordering::Acquire); /// } @@ -2710,7 +2714,7 @@ pub fn fence(order: Ordering) { /// Without `compiler_fence`, the `assert_eq!` in following code /// is *not* guaranteed to succeed, despite everything happening in a single thread. /// To see why, remember that the compiler is free to swap the stores to -/// `IMPORTANT_VARIABLE` and `IS_READ` since they are both +/// `IMPORTANT_VARIABLE` and `IS_READY` since they are both /// `Ordering::Relaxed`. If it does, and the signal handler is invoked right /// after `IS_READY` is updated, then the signal handler will see /// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`. diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 9cf89623d8..fc0a4e7479 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -26,7 +26,21 @@ pub enum Poll { } impl Poll { - /// Changes the ready value of this `Poll` with the closure provided. + /// Maps a `Poll` to `Poll` by applying a function to a contained value. + /// + /// # Examples + /// + /// Converts a `Poll<`[`String`]`>` into an `Poll<`[`usize`]`>`, consuming the original: + /// + /// [`String`]: ../../std/string/struct.String.html + /// ``` + /// # use core::task::Poll; + /// let poll_some_string = Poll::Ready(String::from("Hello, World!")); + /// // `Poll::map` takes self *by value*, consuming `poll_some_string` + /// let poll_some_len = poll_some_string.map(|s| s.len()); + /// + /// assert_eq!(poll_some_len, Poll::Ready(13)); + /// ``` #[stable(feature = "futures_api", since = "1.36.0")] pub fn map(self, f: F) -> Poll where @@ -38,7 +52,18 @@ impl Poll { } } - /// Returns `true` if this is `Poll::Ready` + /// Returns `true` if the poll is a [`Poll::Ready`] value. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let x: Poll = Poll::Ready(2); + /// assert_eq!(x.is_ready(), true); + /// + /// let x: Poll = Poll::Pending; + /// assert_eq!(x.is_ready(), false); + /// ``` #[inline] #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] @@ -46,7 +71,20 @@ impl Poll { matches!(*self, Poll::Ready(_)) } - /// Returns `true` if this is `Poll::Pending` + /// Returns `true` if the poll is a [`Pending`] value. + /// + /// [`Pending`]: Poll::Pending + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let x: Poll = Poll::Ready(2); + /// assert_eq!(x.is_pending(), false); + /// + /// let x: Poll = Poll::Pending; + /// assert_eq!(x.is_pending(), true); + /// ``` #[inline] #[rustc_const_stable(feature = "const_poll", since = "1.49.0")] #[stable(feature = "futures_api", since = "1.36.0")] @@ -56,7 +94,20 @@ impl Poll { } impl Poll> { - /// Changes the success value of this `Poll` with the closure provided. + /// Maps a `Poll>` to `Poll>` by applying a + /// function to a contained `Poll::Ready(Ok)` value, leaving all other + /// variants untouched. + /// + /// This function can be used to compose the results of two functions. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll> = Poll::Ready("12".parse()); + /// let squared = res.map_ok(|n| n * n); + /// assert_eq!(squared, Poll::Ready(Ok(144))); + /// ``` #[stable(feature = "futures_api", since = "1.36.0")] pub fn map_ok(self, f: F) -> Poll> where @@ -69,7 +120,21 @@ impl Poll> { } } - /// Changes the error value of this `Poll` with the closure provided. + /// Maps a `Poll::Ready>` to `Poll::Ready>` by + /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other + /// variants untouched. + /// + /// This function can be used to pass through a successful result while handling + /// an error. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll> = Poll::Ready("oops".parse()); + /// let res = res.map_err(|_| 0_u8); + /// assert_eq!(res, Poll::Ready(Err(0))); + /// ``` #[stable(feature = "futures_api", since = "1.36.0")] pub fn map_err(self, f: F) -> Poll> where @@ -84,7 +149,20 @@ impl Poll> { } impl Poll>> { - /// Changes the success value of this `Poll` with the closure provided. + /// Maps a `Poll>>` to `Poll>>` by + /// applying a function to a contained `Poll::Ready(Some(Ok))` value, + /// leaving all other variants untouched. + /// + /// This function can be used to compose the results of two functions. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll>> = Poll::Ready(Some("12".parse())); + /// let squared = res.map_ok(|n| n * n); + /// assert_eq!(squared, Poll::Ready(Some(Ok(144)))); + /// ``` #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_ok(self, f: F) -> Poll>> where @@ -98,7 +176,22 @@ impl Poll>> { } } - /// Changes the error value of this `Poll` with the closure provided. + /// Maps a `Poll::Ready>>` to + /// `Poll::Ready>>` by applying a function to a + /// contained `Poll::Ready(Some(Err))` value, leaving all other variants + /// untouched. + /// + /// This function can be used to pass through a successful result while handling + /// an error. + /// + /// # Examples + /// + /// ``` + /// # use core::task::Poll; + /// let res: Poll>> = Poll::Ready(Some("oops".parse())); + /// let res = res.map_err(|_| 0_u8); + /// assert_eq!(res, Poll::Ready(Some(Err(0)))); + /// ``` #[stable(feature = "poll_map", since = "1.51.0")] pub fn map_err(self, f: F) -> Poll>> where @@ -128,32 +221,6 @@ impl From for Poll { } } -#[stable(feature = "futures_api", since = "1.36.0")] -#[cfg(bootstrap)] -impl ops::TryV1 for Poll> { - type Output = Poll; - type Error = E; - - #[inline] - fn into_result(self) -> Result { - match self { - Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)), - Poll::Ready(Err(e)) => Err(e), - Poll::Pending => Ok(Poll::Pending), - } - } - - #[inline] - fn from_error(e: Self::Error) -> Self { - Poll::Ready(Err(e)) - } - - #[inline] - fn from_ok(x: Self::Output) -> Self { - x.map(Ok) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl ops::TryV2 for Poll> { type Output = Poll; @@ -184,33 +251,6 @@ impl> ops::FromResidual> for Pol } } -#[stable(feature = "futures_api", since = "1.36.0")] -#[cfg(bootstrap)] -impl ops::TryV1 for Poll>> { - type Output = Poll>; - type Error = E; - - #[inline] - fn into_result(self) -> Result { - match self { - Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))), - Poll::Ready(Some(Err(e))) => Err(e), - Poll::Ready(None) => Ok(Poll::Ready(None)), - Poll::Pending => Ok(Poll::Pending), - } - } - - #[inline] - fn from_error(e: Self::Error) -> Self { - Poll::Ready(Some(Err(e))) - } - - #[inline] - fn from_ok(x: Self::Output) -> Self { - x.map(|x| x.map(Ok)) - } -} - #[unstable(feature = "try_trait_v2", issue = "84277")] impl ops::TryV2 for Poll>> { type Output = Poll>; diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 489b722440..2d8a1cb1ab 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -61,6 +61,7 @@ const MICROS_PER_SEC: u64 = 1_000_000; /// crate to do so. #[stable(feature = "duration", since = "1.3.0")] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[cfg_attr(not(test), rustc_diagnostic_item = "Duration")] pub struct Duration { secs: u64, nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC @@ -687,21 +688,47 @@ impl Duration { #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn from_secs_f64(secs: f64) -> Duration { + match Duration::try_from_secs_f64(secs) { + Ok(v) => v, + Err(e) => crate::panicking::panic(e.description()), + } + } + + /// The checked version of [`from_secs_f64`]. + /// + /// [`from_secs_f64`]: Duration::from_secs_f64 + /// + /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_checked_float)] + /// + /// use std::time::Duration; + /// + /// let dur = Duration::try_from_secs_f64(2.7); + /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000))); + /// + /// let negative = Duration::try_from_secs_f64(-5.0); + /// assert!(negative.is_err()); + /// ``` + #[unstable(feature = "duration_checked_float", issue = "83400")] + #[inline] + pub const fn try_from_secs_f64(secs: f64) -> Result { const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64; let nanos = secs * (NANOS_PER_SEC as f64); if !nanos.is_finite() { - panic!("got non-finite value when converting float to duration"); - } - if nanos >= MAX_NANOS_F64 { - panic!("overflow when converting float to duration"); - } - if nanos < 0.0 { - panic!("underflow when converting float to duration"); - } - let nanos = nanos as u128; - Duration { - secs: (nanos / (NANOS_PER_SEC as u128)) as u64, - nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, + Err(FromSecsError { kind: FromSecsErrorKind::NonFinite }) + } else if nanos >= MAX_NANOS_F64 { + Err(FromSecsError { kind: FromSecsErrorKind::Overflow }) + } else if nanos < 0.0 { + Err(FromSecsError { kind: FromSecsErrorKind::Underflow }) + } else { + let nanos = nanos as u128; + Ok(Duration { + secs: (nanos / (NANOS_PER_SEC as u128)) as u64, + nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, + }) } } @@ -722,21 +749,47 @@ impl Duration { #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn from_secs_f32(secs: f32) -> Duration { + match Duration::try_from_secs_f32(secs) { + Ok(v) => v, + Err(e) => crate::panicking::panic(e.description()), + } + } + + /// The checked version of [`from_secs_f32`]. + /// + /// [`from_secs_f32`]: Duration::from_secs_f32 + /// + /// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`. + /// + /// # Examples + /// ``` + /// #![feature(duration_checked_float)] + /// + /// use std::time::Duration; + /// + /// let dur = Duration::try_from_secs_f32(2.7); + /// assert_eq!(dur, Ok(Duration::new(2, 700_000_000))); + /// + /// let negative = Duration::try_from_secs_f32(-5.0); + /// assert!(negative.is_err()); + /// ``` + #[unstable(feature = "duration_checked_float", issue = "83400")] + #[inline] + pub const fn try_from_secs_f32(secs: f32) -> Result { const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32; let nanos = secs * (NANOS_PER_SEC as f32); if !nanos.is_finite() { - panic!("got non-finite value when converting float to duration"); - } - if nanos >= MAX_NANOS_F32 { - panic!("overflow when converting float to duration"); - } - if nanos < 0.0 { - panic!("underflow when converting float to duration"); - } - let nanos = nanos as u128; - Duration { - secs: (nanos / (NANOS_PER_SEC as u128)) as u64, - nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, + Err(FromSecsError { kind: FromSecsErrorKind::NonFinite }) + } else if nanos >= MAX_NANOS_F32 { + Err(FromSecsError { kind: FromSecsErrorKind::Overflow }) + } else if nanos < 0.0 { + Err(FromSecsError { kind: FromSecsErrorKind::Underflow }) + } else { + let nanos = nanos as u128; + Ok(Duration { + secs: (nanos / (NANOS_PER_SEC as u128)) as u64, + nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, + }) } } @@ -1099,3 +1152,55 @@ impl fmt::Debug for Duration { } } } + +/// An error which can be returned when converting a floating-point value of seconds +/// into a [`Duration`]. +/// +/// This error is used as the error type for [`Duration::try_from_secs_f32`] and +/// [`Duration::try_from_secs_f64`]. +/// +/// # Example +/// +/// ``` +/// #![feature(duration_checked_float)] +/// +/// use std::time::Duration; +/// +/// if let Err(e) = Duration::try_from_secs_f32(-1.0) { +/// println!("Failed conversion to Duration: {}", e); +/// } +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] +#[unstable(feature = "duration_checked_float", issue = "83400")] +pub struct FromSecsError { + kind: FromSecsErrorKind, +} + +impl FromSecsError { + const fn description(&self) -> &'static str { + match self.kind { + FromSecsErrorKind::NonFinite => { + "got non-finite value when converting float to duration" + } + FromSecsErrorKind::Overflow => "overflow when converting float to duration", + FromSecsErrorKind::Underflow => "underflow when converting float to duration", + } + } +} + +#[unstable(feature = "duration_checked_float", issue = "83400")] +impl fmt::Display for FromSecsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.description(), f) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum FromSecsErrorKind { + // Value is not a finite value (either infinity or NaN). + NonFinite, + // Value is too large to store in a `Duration`. + Overflow, + // Value is less than `0.0`. + Underflow, +} diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 37ca0a0779..72fa059b78 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -4,7 +4,7 @@ pub(crate) mod printable; mod unicode_data; -/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of +/// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of /// `char` and `str` methods are based on. /// /// New versions of Unicode are released regularly and subsequently all methods diff --git a/library/core/src/unicode/printable.py b/library/core/src/unicode/printable.py index 91db6381c9..c42850d232 100755 --- a/library/core/src/unicode/printable.py +++ b/library/core/src/unicode/printable.py @@ -130,7 +130,7 @@ def print_normal(normal, normalname): print("];") def main(): - file = get_file("http://www.unicode.org/Public/UNIDATA/UnicodeData.txt") + file = get_file("https://www.unicode.org/Public/UNIDATA/UnicodeData.txt") codepoints = get_codepoints(file) diff --git a/library/core/tests/const_ptr.rs b/library/core/tests/const_ptr.rs index 4acd059ab0..152fed803e 100644 --- a/library/core/tests/const_ptr.rs +++ b/library/core/tests/const_ptr.rs @@ -49,3 +49,53 @@ fn mut_ptr_read() { const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() }; assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45])); } + +#[test] +fn write() { + use core::ptr; + + const fn write_aligned() -> i32 { + let mut res = 0; + unsafe { + ptr::write(&mut res as *mut _, 42); + } + res + } + const ALIGNED: i32 = write_aligned(); + assert_eq!(ALIGNED, 42); + + const fn write_unaligned() -> [u16; 2] { + let mut two_aligned = [0u16; 2]; + unsafe { + let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16; + ptr::write_unaligned(unaligned_ptr, u16::from_ne_bytes([0x23, 0x45])); + } + two_aligned + } + const UNALIGNED: [u16; 2] = write_unaligned(); + assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]); +} + +#[test] +fn mut_ptr_write() { + const fn aligned() -> i32 { + let mut res = 0; + unsafe { + (&mut res as *mut i32).write(42); + } + res + } + const ALIGNED: i32 = aligned(); + assert_eq!(ALIGNED, 42); + + const fn write_unaligned() -> [u16; 2] { + let mut two_aligned = [0u16; 2]; + unsafe { + let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16; + unaligned_ptr.write_unaligned(u16::from_ne_bytes([0x23, 0x45])); + } + two_aligned + } + const UNALIGNED: [u16; 2] = write_unaligned(); + assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]); +} diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 1566d35749..72ccdd4848 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -1,7 +1,7 @@ mod sip; use std::default::Default; -use std::hash::{Hash, Hasher}; +use std::hash::{BuildHasher, Hash, Hasher}; use std::rc::Rc; struct MyHasher { @@ -139,3 +139,10 @@ fn test_indirect_hasher() { } assert_eq!(hasher.hash, 5); } + +#[test] +fn test_build_hasher_object_safe() { + use std::collections::hash_map::{DefaultHasher, RandomState}; + + let _: &dyn BuildHasher = &RandomState::new(); +} diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index 4bbae6947b..aaac39c297 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -1,4 +1,5 @@ use super::*; +use core::array; use core::iter::*; #[test] @@ -109,3 +110,42 @@ fn test_double_ended_flatten() { assert_eq!(it.next(), None); assert_eq!(it.next_back(), None); } + +#[test] +fn test_trusted_len_flatten() { + fn assert_trusted_len(_: &T) {} + let mut iter = array::IntoIter::new([[0; 3]; 4]).flatten(); + assert_trusted_len(&iter); + + assert_eq!(iter.size_hint(), (12, Some(12))); + iter.next(); + assert_eq!(iter.size_hint(), (11, Some(11))); + iter.next_back(); + assert_eq!(iter.size_hint(), (10, Some(10))); + + let iter = array::IntoIter::new([[(); usize::MAX]; 1]).flatten(); + assert_eq!(iter.size_hint(), (usize::MAX, Some(usize::MAX))); + + let iter = array::IntoIter::new([[(); usize::MAX]; 2]).flatten(); + assert_eq!(iter.size_hint(), (usize::MAX, None)); + + let mut a = [(); 10]; + let mut b = [(); 10]; + + let iter = array::IntoIter::new([&mut a, &mut b]).flatten(); + assert_trusted_len(&iter); + assert_eq!(iter.size_hint(), (20, Some(20))); + core::mem::drop(iter); + + let iter = array::IntoIter::new([&a, &b]).flatten(); + assert_trusted_len(&iter); + assert_eq!(iter.size_hint(), (20, Some(20))); + + let iter = [(), (), ()].iter().flat_map(|_| [(); 1000]); + assert_trusted_len(&iter); + assert_eq!(iter.size_hint(), (3000, Some(3000))); + + let iter = [(), ()].iter().flat_map(|_| &a); + assert_trusted_len(&iter); + assert_eq!(iter.size_hint(), (20, Some(20))); +} diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs index 797bfd957f..585cfbb90e 100644 --- a/library/core/tests/iter/adapters/zip.rs +++ b/library/core/tests/iter/adapters/zip.rs @@ -232,6 +232,33 @@ fn test_zip_trusted_random_access_composition() { assert_eq!(z2.next().unwrap(), ((1, 1), 1)); } +#[test] +#[cfg(panic = "unwind")] +fn test_zip_trusted_random_access_next_back_drop() { + use std::panic::catch_unwind; + use std::panic::AssertUnwindSafe; + + let mut counter = 0; + + let it = [42].iter().map(|e| { + let c = counter; + counter += 1; + if c == 0 { + panic!("bomb"); + } + + e + }); + let it2 = [(); 0].iter(); + let mut zip = it.zip(it2); + catch_unwind(AssertUnwindSafe(|| { + zip.next_back(); + })) + .unwrap_err(); + assert!(zip.next().is_none()); + assert_eq!(counter, 1); +} + #[test] fn test_double_ended_zip() { let xs = [1, 2, 3, 4, 5, 6]; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 16051b3bc3..c7756a503c 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,10 +1,8 @@ #![feature(alloc_layout_extra)] #![feature(array_chunks)] #![feature(array_methods)] -#![feature(array_map)] #![feature(array_windows)] #![feature(bool_to_option)] -#![feature(bound_cloned)] #![feature(box_syntax)] #![feature(cell_update)] #![feature(cfg_panic)] @@ -15,7 +13,6 @@ #![feature(const_ptr_read)] #![feature(const_ptr_write)] #![feature(const_ptr_offset)] -#![feature(control_flow_enum)] #![feature(core_intrinsics)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] @@ -31,7 +28,6 @@ #![feature(try_find)] #![feature(is_sorted)] #![feature(pattern)] -#![feature(raw)] #![feature(sort_internals)] #![feature(slice_partition_at_index)] #![feature(maybe_uninit_uninit_array)] @@ -39,6 +35,7 @@ #![feature(maybe_uninit_extra)] #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] +#![feature(numfmt)] #![feature(step_trait)] #![feature(str_internals)] #![feature(test)] @@ -46,7 +43,7 @@ #![feature(try_trait_v2)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] -#![feature(int_error_matching)] +#![feature(int_log)] #![feature(iter_advance_by)] #![feature(iter_partition_in_place)] #![feature(iter_intersperse)] diff --git a/library/core/tests/manually_drop.rs b/library/core/tests/manually_drop.rs index 77a338daf7..9eac279733 100644 --- a/library/core/tests/manually_drop.rs +++ b/library/core/tests/manually_drop.rs @@ -2,6 +2,7 @@ use core::mem::ManuallyDrop; #[test] fn smoke() { + #[derive(Clone)] struct TypeWithDrop; impl Drop for TypeWithDrop { fn drop(&mut self) { @@ -16,4 +17,11 @@ fn smoke() { let x: Box> = Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop])); drop(x); + + // test clone and clone_from implementations + let mut x = ManuallyDrop::new(TypeWithDrop); + let y = x.clone(); + x.clone_from(&y); + drop(x); + drop(y); } diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index dfdbc9305d..c780bb32ca 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -97,28 +97,6 @@ fn test_transmute_copy() { assert_eq!(1, unsafe { transmute_copy(&1) }); } -// Remove this test when `std::raw` is removed. -// The replacement pointer metadata APIs are tested in library/core/tests/ptr.rs -#[allow(deprecated)] -#[test] -fn test_transmute() { - trait Foo { - fn dummy(&self) {} - } - impl Foo for isize {} - - let a = box 100isize as Box; - unsafe { - let x: ::core::raw::TraitObject = transmute(a); - assert!(*(x.data as *const isize) == 100); - let _x: Box = transmute(x); - } - - unsafe { - assert_eq!(transmute::<_, Vec>("L".to_string()), [76]); - } -} - #[test] #[allow(dead_code)] fn test_discriminant_send_sync() { diff --git a/library/core/tests/num/dec2flt/float.rs b/library/core/tests/num/dec2flt/float.rs new file mode 100644 index 0000000000..7a9587a18d --- /dev/null +++ b/library/core/tests/num/dec2flt/float.rs @@ -0,0 +1,33 @@ +use core::num::dec2flt::float::RawFloat; + +#[test] +fn test_f32_integer_decode() { + assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1)); + assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1)); + assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1)); + assert_eq!(0f32.integer_decode(), (0, -150, 1)); + assert_eq!((-0f32).integer_decode(), (0, -150, -1)); + assert_eq!(f32::INFINITY.integer_decode(), (8388608, 105, 1)); + assert_eq!(f32::NEG_INFINITY.integer_decode(), (8388608, 105, -1)); + + // Ignore the "sign" (quiet / signalling flag) of NAN. + // It can vary between runtime operations and LLVM folding. + let (nan_m, nan_e, _nan_s) = f32::NAN.integer_decode(); + assert_eq!((nan_m, nan_e), (12582912, 105)); +} + +#[test] +fn test_f64_integer_decode() { + assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1)); + assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1)); + assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1)); + assert_eq!(0f64.integer_decode(), (0, -1075, 1)); + assert_eq!((-0f64).integer_decode(), (0, -1075, -1)); + assert_eq!(f64::INFINITY.integer_decode(), (4503599627370496, 972, 1)); + assert_eq!(f64::NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1)); + + // Ignore the "sign" (quiet / signalling flag) of NAN. + // It can vary between runtime operations and LLVM folding. + let (nan_m, nan_e, _nan_s) = f64::NAN.integer_decode(); + assert_eq!((nan_m, nan_e), (6755399441055744, 972)); +} diff --git a/library/core/tests/num/dec2flt/lemire.rs b/library/core/tests/num/dec2flt/lemire.rs new file mode 100644 index 0000000000..f71bbb7c7a --- /dev/null +++ b/library/core/tests/num/dec2flt/lemire.rs @@ -0,0 +1,53 @@ +use core::num::dec2flt::lemire::compute_float; + +fn compute_float32(q: i64, w: u64) -> (i32, u64) { + let fp = compute_float::(q, w); + (fp.e, fp.f) +} + +fn compute_float64(q: i64, w: u64) -> (i32, u64) { + let fp = compute_float::(q, w); + (fp.e, fp.f) +} + +#[test] +fn compute_float_f32_rounding() { + // These test near-halfway cases for single-precision floats. + assert_eq!(compute_float32(0, 16777216), (151, 0)); + assert_eq!(compute_float32(0, 16777217), (151, 0)); + assert_eq!(compute_float32(0, 16777218), (151, 1)); + assert_eq!(compute_float32(0, 16777219), (151, 2)); + assert_eq!(compute_float32(0, 16777220), (151, 2)); + + // These are examples of the above tests, with + // digits from the exponent shifted to the mantissa. + assert_eq!(compute_float32(-10, 167772160000000000), (151, 0)); + assert_eq!(compute_float32(-10, 167772170000000000), (151, 0)); + assert_eq!(compute_float32(-10, 167772180000000000), (151, 1)); + // Let's check the lines to see if anything is different in table... + assert_eq!(compute_float32(-10, 167772190000000000), (151, 2)); + assert_eq!(compute_float32(-10, 167772200000000000), (151, 2)); +} + +#[test] +fn compute_float_f64_rounding() { + // These test near-halfway cases for double-precision floats. + assert_eq!(compute_float64(0, 9007199254740992), (1076, 0)); + assert_eq!(compute_float64(0, 9007199254740993), (1076, 0)); + assert_eq!(compute_float64(0, 9007199254740994), (1076, 1)); + assert_eq!(compute_float64(0, 9007199254740995), (1076, 2)); + assert_eq!(compute_float64(0, 9007199254740996), (1076, 2)); + assert_eq!(compute_float64(0, 18014398509481984), (1077, 0)); + assert_eq!(compute_float64(0, 18014398509481986), (1077, 0)); + assert_eq!(compute_float64(0, 18014398509481988), (1077, 1)); + assert_eq!(compute_float64(0, 18014398509481990), (1077, 2)); + assert_eq!(compute_float64(0, 18014398509481992), (1077, 2)); + + // These are examples of the above tests, with + // digits from the exponent shifted to the mantissa. + assert_eq!(compute_float64(-3, 9007199254740992000), (1076, 0)); + assert_eq!(compute_float64(-3, 9007199254740993000), (1076, 0)); + assert_eq!(compute_float64(-3, 9007199254740994000), (1076, 1)); + assert_eq!(compute_float64(-3, 9007199254740995000), (1076, 2)); + assert_eq!(compute_float64(-3, 9007199254740996000), (1076, 2)); +} diff --git a/library/core/tests/num/dec2flt/mod.rs b/library/core/tests/num/dec2flt/mod.rs index 32f05d1def..4990d4a083 100644 --- a/library/core/tests/num/dec2flt/mod.rs +++ b/library/core/tests/num/dec2flt/mod.rs @@ -1,7 +1,8 @@ #![allow(overflowing_literals)] +mod float; +mod lemire; mod parse; -mod rawfp; // Take a float literal, turn it into a string in various ways (that are all trusted // to be correct) and see if those strings are parsed back to the value of the literal. @@ -28,12 +29,6 @@ fn ordinary() { test_literal!(0.1); test_literal!(12345.); test_literal!(0.9999999); - - if cfg!(miri) { - // Miri is too slow - return; - } - test_literal!(2.2250738585072014e-308); } @@ -54,7 +49,6 @@ fn large() { } #[test] -#[cfg_attr(miri, ignore)] // Miri is too slow fn subnormals() { test_literal!(5e-324); test_literal!(91e-324); @@ -66,7 +60,6 @@ fn subnormals() { } #[test] -#[cfg_attr(miri, ignore)] // Miri is too slow fn infinity() { test_literal!(1e400); test_literal!(1e309); @@ -78,12 +71,6 @@ fn infinity() { fn zero() { test_literal!(0.0); test_literal!(1e-325); - - if cfg!(miri) { - // Miri is too slow - return; - } - test_literal!(1e-326); test_literal!(1e-500); } diff --git a/library/core/tests/num/dec2flt/parse.rs b/library/core/tests/num/dec2flt/parse.rs index bb7e51d300..473feacc91 100644 --- a/library/core/tests/num/dec2flt/parse.rs +++ b/library/core/tests/num/dec2flt/parse.rs @@ -1,17 +1,23 @@ -use core::num::dec2flt::parse::ParseResult::{Invalid, Valid}; -use core::num::dec2flt::parse::{parse_decimal, Decimal}; +use core::num::dec2flt::number::Number; +use core::num::dec2flt::parse::parse_number; +use core::num::dec2flt::{dec2flt, pfe_invalid}; + +fn new_number(e: i64, m: u64) -> Number { + Number { exponent: e, mantissa: m, negative: false, many_digits: false } +} #[test] fn missing_pieces() { let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"]; for &s in permutations { - assert_eq!(parse_decimal(s), Invalid); + assert_eq!(dec2flt::(s), Err(pfe_invalid())); } } #[test] fn invalid_chars() { let invalid = "r,?(&input) == error, "did not reject invalid {:?}", input); } } } } +fn parse_positive(s: &[u8]) -> Option { + parse_number(s, false) +} + #[test] fn valid() { - assert_eq!(parse_decimal("123.456e789"), Valid(Decimal::new(b"123", b"456", 789))); - assert_eq!(parse_decimal("123.456e+789"), Valid(Decimal::new(b"123", b"456", 789))); - assert_eq!(parse_decimal("123.456e-789"), Valid(Decimal::new(b"123", b"456", -789))); - assert_eq!(parse_decimal(".050"), Valid(Decimal::new(b"", b"050", 0))); - assert_eq!(parse_decimal("999"), Valid(Decimal::new(b"999", b"", 0))); - assert_eq!(parse_decimal("1.e300"), Valid(Decimal::new(b"1", b"", 300))); - assert_eq!(parse_decimal(".1e300"), Valid(Decimal::new(b"", b"1", 300))); - assert_eq!(parse_decimal("101e-33"), Valid(Decimal::new(b"101", b"", -33))); + assert_eq!(parse_positive(b"123.456e789"), Some(new_number(786, 123456))); + assert_eq!(parse_positive(b"123.456e+789"), Some(new_number(786, 123456))); + assert_eq!(parse_positive(b"123.456e-789"), Some(new_number(-792, 123456))); + assert_eq!(parse_positive(b".050"), Some(new_number(-3, 50))); + assert_eq!(parse_positive(b"999"), Some(new_number(0, 999))); + assert_eq!(parse_positive(b"1.e300"), Some(new_number(300, 1))); + assert_eq!(parse_positive(b".1e300"), Some(new_number(299, 1))); + assert_eq!(parse_positive(b"101e-33"), Some(new_number(-33, 101))); let zeros = "0".repeat(25); let s = format!("1.5e{}", zeros); - assert_eq!(parse_decimal(&s), Valid(Decimal::new(b"1", b"5", 0))); + assert_eq!(parse_positive(s.as_bytes()), Some(new_number(-1, 15))); +} + +macro_rules! assert_float_result_bits_eq { + ($bits:literal, $ty:ty, $str:literal) => {{ + let p = dec2flt::<$ty>($str); + assert_eq!(p.map(|x| x.to_bits()), Ok($bits)); + }}; +} + +#[test] +fn issue31109() { + // Regression test for #31109. + // Ensure the test produces a valid float with the expected bit pattern. + assert_float_result_bits_eq!( + 0x3fd5555555555555, + f64, + "0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333" + ); +} + +#[test] +fn issue31407() { + // Regression test for #31407. + // Ensure the test produces a valid float with the expected bit pattern. + assert_float_result_bits_eq!( + 0x1752a64e34ba0d3, + f64, + "1234567890123456789012345678901234567890e-340" + ); + assert_float_result_bits_eq!( + 0xfffffffffffff, + f64, + "2.225073858507201136057409796709131975934819546351645648023426109724822222021076945516529523908135087914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012981122451451889849057222307285255133155755015914397476397983411801999323962548289017107081850690630666655994938275772572015763062690663332647565300009245888316433037779791869612049497390377829704905051080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621572289880258182545180325707018860872113128079512233426288368622321503775666622503982534335974568884423900265498198385487948292206894721689831099698365846814022854243330660339850886445804001034933970427567186443383770486037861622771738545623065874679014086723327636718749999999999999999999999999999999999999e-308" + ); + assert_float_result_bits_eq!( + 0x10000000000000, + f64, + "2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901298112245145188984905722230728525513315575501591439747639798341180199932396254828901710708185069063066665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462157228988025818254518032570701886087211312807951223342628836862232150377566662250398253433597456888442390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042756718644338377048603786162277173854562306587467901408672332763671875e-308" + ); + assert_float_result_bits_eq!( + 0x10000000000000, + f64, + "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000222507385850720138309023271733240406421921598046233183055332741688720443481391819585428315901251102056406733973103581100515243416155346010885601238537771882113077799353200233047961014744258363607192156504694250373420837525080665061665815894872049117996859163964850063590877011830487479978088775374994945158045160505091539985658247081864511353793580499211598108576605199243335211435239014879569960959128889160299264151106346631339366347758651302937176204732563178148566435087212282863764204484681140761391147706280168985324411002416144742161856716615054015428508471675290190316132277889672970737312333408698898317506783884692609277397797285865965494109136909540613646756870239867831529068098461721092462539672851562500000000000000001" + ); + assert_float_result_bits_eq!( + 0x7fefffffffffffff, + f64, + "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999999999999999999999999999999999999999999999999999999999999" + ); + assert_float_result_bits_eq!(0x0, f64, "2.47032822920623272e-324"); + assert_float_result_bits_eq!( + 0x8000000, + f64, + "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316" + ); + assert_float_result_bits_eq!( + 0x10000, + f64, + "3.237883913302901289588352412501532174863037669423108059901297049552301970670676565786835742587799557860615776559838283435514391084153169252689190564396459577394618038928365305143463955100356696665629202017331344031730044369360205258345803431471660032699580731300954848363975548690010751530018881758184174569652173110473696022749934638425380623369774736560008997404060967498028389191878963968575439222206416981462690113342524002724385941651051293552601421155333430225237291523843322331326138431477823591142408800030775170625915670728657003151953664260769822494937951845801530895238439819708403389937873241463484205608000027270531106827387907791444918534771598750162812548862768493201518991668028251730299953143924168545708663913273994694463908672332763671875E-319" + ); + assert_float_result_bits_eq!( + 0x800000000100, + f64, + "6.953355807847677105972805215521891690222119817145950754416205607980030131549636688806115726399441880065386399864028691275539539414652831584795668560082999889551357784961446896042113198284213107935110217162654939802416034676213829409720583759540476786936413816541621287843248433202369209916612249676005573022703244799714622116542188837770376022371172079559125853382801396219552418839469770514904192657627060319372847562301074140442660237844114174497210955449896389180395827191602886654488182452409583981389442783377001505462015745017848754574668342161759496661766020028752888783387074850773192997102997936619876226688096314989645766000479009083731736585750335262099860150896718774401964796827166283225641992040747894382698751809812609536720628966577351093292236328125E-310" + ); + assert_float_result_bits_eq!( + 0x10800, + f64, + "3.339068557571188581835713701280943911923401916998521771655656997328440314559615318168849149074662609099998113009465566426808170378434065722991659642619467706034884424989741080790766778456332168200464651593995817371782125010668346652995912233993254584461125868481633343674905074271064409763090708017856584019776878812425312008812326260363035474811532236853359905334625575404216060622858633280744301892470300555678734689978476870369853549413277156622170245846166991655321535529623870646888786637528995592800436177901746286272273374471701452991433047257863864601424252024791567368195056077320885329384322332391564645264143400798619665040608077549162173963649264049738362290606875883456826586710961041737908872035803481241600376705491726170293986797332763671875E-319" + ); + assert_float_result_bits_eq!( + 0x0, + f64, + "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999e-324" + ); + assert_float_result_bits_eq!( + 0x0, + f64, + "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324" + ); + assert_float_result_bits_eq!( + 0x1, + f64, + "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125001e-324" + ); + assert_float_result_bits_eq!( + 0x1, + f64, + "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324" + ); + assert_float_result_bits_eq!( + 0x2, + f64, + "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324" + ); + assert_float_result_bits_eq!( + 0x2, + f64, + "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324" + ); + assert_float_result_bits_eq!( + 0x6c9a143590c14, + f64, + "94393431193180696942841837085033647913224148539854e-358" + ); + assert_float_result_bits_eq!( + 0x7802665fd9600, + f64, + "104308485241983990666713401708072175773165034278685682646111762292409330928739751702404658197872319129036519947435319418387839758990478549477777586673075945844895981012024387992135617064532141489278815239849108105951619997829153633535314849999674266169258928940692239684771590065027025835804863585454872499320500023126142553932654370362024104462255244034053203998964360882487378334860197725139151265590832887433736189468858614521708567646743455601905935595381852723723645799866672558576993978025033590728687206296379801363024094048327273913079612469982585674824156000783167963081616214710691759864332339239688734656548790656486646106983450809073750535624894296242072010195710276073042036425579852459556183541199012652571123898996574563824424330960027873516082763671875e-1075" + ); +} + +#[test] +fn many_digits() { + // Check large numbers of digits to ensure we have cases where significant + // digits (above Decimal::MAX_DIGITS) occurs. + assert_float_result_bits_eq!( + 0x7ffffe, + f32, + "1.175494140627517859246175898662808184331245864732796240031385942718174675986064769972472277004271745681762695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-38" + ); + assert_float_result_bits_eq!( + 0x7ffffe, + f32, + "1.175494140627517859246175898662808184331245864732796240031385942718174675986064769972472277004271745681762695312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-38" + ); } diff --git a/library/core/tests/num/dec2flt/rawfp.rs b/library/core/tests/num/dec2flt/rawfp.rs deleted file mode 100644 index 34a37209d9..0000000000 --- a/library/core/tests/num/dec2flt/rawfp.rs +++ /dev/null @@ -1,172 +0,0 @@ -use core::num::dec2flt::rawfp::RawFloat; -use core::num::dec2flt::rawfp::{fp_to_float, next_float, prev_float, round_normal}; -use core::num::diy_float::Fp; - -fn integer_decode(f: f64) -> (u64, i16, i8) { - RawFloat::integer_decode(f) -} - -#[test] -fn fp_to_float_half_to_even() { - fn is_normalized(sig: u64) -> bool { - // intentionally written without {min,max}_sig() as a sanity check - sig >> 52 == 1 && sig >> 53 == 0 - } - - fn conv(sig: u64) -> u64 { - // The significands are perfectly in range, so the exponent should not matter - let (m1, e1, _) = integer_decode(fp_to_float::(Fp { f: sig, e: 0 })); - assert_eq!(e1, 0 + 64 - 53); - let (m2, e2, _) = integer_decode(fp_to_float::(Fp { f: sig, e: 55 })); - assert_eq!(e2, 55 + 64 - 53); - assert_eq!(m2, m1); - let (m3, e3, _) = integer_decode(fp_to_float::(Fp { f: sig, e: -78 })); - assert_eq!(e3, -78 + 64 - 53); - assert_eq!(m3, m2); - m3 - } - - let odd = 0x1F_EDCB_A012_345F; - let even = odd - 1; - assert!(is_normalized(odd)); - assert!(is_normalized(even)); - assert_eq!(conv(odd << 11), odd); - assert_eq!(conv(even << 11), even); - assert_eq!(conv(odd << 11 | 1 << 10), odd + 1); - assert_eq!(conv(even << 11 | 1 << 10), even); - assert_eq!(conv(even << 11 | 1 << 10 | 1), even + 1); - assert_eq!(conv(odd << 11 | 1 << 9), odd); - assert_eq!(conv(even << 11 | 1 << 9), even); - assert_eq!(conv(odd << 11 | 0x7FF), odd + 1); - assert_eq!(conv(even << 11 | 0x7FF), even + 1); - assert_eq!(conv(odd << 11 | 0x3FF), odd); - assert_eq!(conv(even << 11 | 0x3FF), even); -} - -#[test] -fn integers_to_f64() { - assert_eq!(fp_to_float::(Fp { f: 1, e: 0 }), 1.0); - assert_eq!(fp_to_float::(Fp { f: 42, e: 7 }), (42 << 7) as f64); - assert_eq!(fp_to_float::(Fp { f: 1 << 20, e: 30 }), (1u64 << 50) as f64); - assert_eq!(fp_to_float::(Fp { f: 4, e: -3 }), 0.5); -} - -const SOME_FLOATS: [f64; 9] = [ - 0.1f64, - 33.568, - 42.1e-5, - 777.0e9, - 1.1111, - 0.347997, - 9843579834.35892, - 12456.0e-150, - 54389573.0e-150, -]; - -#[test] -fn human_f64_roundtrip() { - for &x in &SOME_FLOATS { - let (f, e, _) = integer_decode(x); - let fp = Fp { f: f, e: e }; - assert_eq!(fp_to_float::(fp), x); - } -} - -#[test] -fn rounding_overflow() { - let x = Fp { f: 0xFF_FF_FF_FF_FF_FF_FF_00u64, e: 42 }; - let rounded = round_normal::(x); - let adjusted_k = x.e + 64 - 53; - assert_eq!(rounded.sig, 1 << 52); - assert_eq!(rounded.k, adjusted_k + 1); -} - -#[test] -fn prev_float_monotonic() { - let mut x = 1.0; - for _ in 0..100 { - let x1 = prev_float(x); - assert!(x1 < x); - assert!(x - x1 < 1e-15); - x = x1; - } -} - -const MIN_SUBNORMAL: f64 = 5e-324; - -#[test] -fn next_float_zero() { - let tiny = next_float(0.0); - assert_eq!(tiny, MIN_SUBNORMAL); - assert!(tiny != 0.0); -} - -#[test] -fn next_float_subnormal() { - let second = next_float(MIN_SUBNORMAL); - // For subnormals, MIN_SUBNORMAL is the ULP - assert!(second != MIN_SUBNORMAL); - assert!(second > 0.0); - assert_eq!(second - MIN_SUBNORMAL, MIN_SUBNORMAL); -} - -#[test] -fn next_float_inf() { - assert_eq!(next_float(f64::MAX), f64::INFINITY); - assert_eq!(next_float(f64::INFINITY), f64::INFINITY); -} - -#[test] -fn next_prev_identity() { - for &x in &SOME_FLOATS { - assert_eq!(prev_float(next_float(x)), x); - assert_eq!(prev_float(prev_float(next_float(next_float(x)))), x); - assert_eq!(next_float(prev_float(x)), x); - assert_eq!(next_float(next_float(prev_float(prev_float(x)))), x); - } -} - -#[test] -fn next_float_monotonic() { - let mut x = 0.49999999999999; - assert!(x < 0.5); - for _ in 0..200 { - let x1 = next_float(x); - assert!(x1 > x); - assert!(x1 - x < 1e-15, "next_float_monotonic: delta = {:?}", x1 - x); - x = x1; - } - assert!(x > 0.5); -} - -#[test] -fn test_f32_integer_decode() { - assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1)); - assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1)); - assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1)); - assert_eq!(0f32.integer_decode(), (0, -150, 1)); - assert_eq!((-0f32).integer_decode(), (0, -150, -1)); - assert_eq!(f32::INFINITY.integer_decode(), (8388608, 105, 1)); - assert_eq!(f32::NEG_INFINITY.integer_decode(), (8388608, 105, -1)); - - // Ignore the "sign" (quiet / signalling flag) of NAN. - // It can vary between runtime operations and LLVM folding. - let (nan_m, nan_e, _nan_s) = f32::NAN.integer_decode(); - assert_eq!((nan_m, nan_e), (12582912, 105)); -} - -#[test] -fn test_f64_integer_decode() { - assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1)); - assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1)); - assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1)); - assert_eq!(0f64.integer_decode(), (0, -1075, 1)); - assert_eq!((-0f64).integer_decode(), (0, -1075, -1)); - assert_eq!(f64::INFINITY.integer_decode(), (4503599627370496, 972, 1)); - assert_eq!(f64::NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1)); - - // Ignore the "sign" (quiet / signalling flag) of NAN. - // It can vary between runtime operations and LLVM folding. - let (nan_m, nan_e, _nan_s) = f64::NAN.integer_decode(); - assert_eq!((nan_m, nan_e), (6755399441055744, 972)); -} diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs index 960a7ca5ff..4874e8ec09 100644 --- a/library/core/tests/num/flt2dec/mod.rs +++ b/library/core/tests/num/flt2dec/mod.rs @@ -2,10 +2,11 @@ use std::mem::MaybeUninit; use std::{fmt, str}; use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded}; -use core::num::flt2dec::{round_up, Formatted, Part, Sign, MAX_SIG_DIGITS}; +use core::num::flt2dec::{round_up, Sign, MAX_SIG_DIGITS}; use core::num::flt2dec::{ to_exact_exp_str, to_exact_fixed_str, to_shortest_exp_str, to_shortest_str, }; +use core::num::fmt::{Formatted, Part}; pub use test::Bencher; diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs new file mode 100644 index 0000000000..51122c11ce --- /dev/null +++ b/library/core/tests/num/int_log.rs @@ -0,0 +1,153 @@ +//! This tests the `Integer::{log,log2,log10}` methods. These tests are in a +//! separate file because there's both a large number of them, and not all tests +//! can be run on Android. This is because in Android `log2` uses an imprecise +//! approximation:https://github.com/rust-lang/rust/blob/4825e12fc9c79954aa0fe18f5521efa6c19c7539/src/libstd/sys/unix/android.rs#L27-L53 + +#[test] +fn checked_log() { + assert_eq!(999u32.checked_log(10), Some(2)); + assert_eq!(1000u32.checked_log(10), Some(3)); + assert_eq!(555u32.checked_log(13), Some(2)); + assert_eq!(63u32.checked_log(4), Some(2)); + assert_eq!(64u32.checked_log(4), Some(3)); + assert_eq!(10460353203u64.checked_log(3), Some(21)); + assert_eq!(10460353202u64.checked_log(3), Some(20)); + assert_eq!(147808829414345923316083210206383297601u128.checked_log(3), Some(80)); + assert_eq!(147808829414345923316083210206383297600u128.checked_log(3), Some(79)); + assert_eq!(22528399544939174411840147874772641u128.checked_log(19683), Some(8)); + assert_eq!(22528399544939174411840147874772631i128.checked_log(19683), Some(7)); + + assert_eq!(0u8.checked_log(4), None); + assert_eq!(0u16.checked_log(4), None); + assert_eq!(0i8.checked_log(4), None); + assert_eq!(0i16.checked_log(4), None); + + for i in i16::MIN..=0 { + assert_eq!(i.checked_log(4), None); + } + for i in 1..=i16::MAX { + assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16)); + } + for i in 1..=u16::MAX { + assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16)); + } +} + +#[test] +fn checked_log2() { + assert_eq!(5u32.checked_log2(), Some(2)); + assert_eq!(0u64.checked_log2(), None); + assert_eq!(128i32.checked_log2(), Some(7)); + assert_eq!((-55i16).checked_log2(), None); + + assert_eq!(0u8.checked_log2(), None); + assert_eq!(0u16.checked_log2(), None); + assert_eq!(0i8.checked_log2(), None); + assert_eq!(0i16.checked_log2(), None); + + for i in 1..=u8::MAX { + assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8)); + } + for i in 1..=u16::MAX { + // Guard against Android's imprecise f32::log2 implementation. + if i != 8192 && i != 32768 { + assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16)); + } + } + for i in i8::MIN..=0 { + assert_eq!(i.checked_log2(), None); + } + for i in 1..=i8::MAX { + assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8)); + } + for i in i16::MIN..=0 { + assert_eq!(i.checked_log2(), None); + } + for i in 1..=i16::MAX { + // Guard against Android's imprecise f32::log2 implementation. + if i != 8192 { + assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16)); + } + } +} + +// Validate cases that fail on Android's imprecise float log2 implementation. +#[test] +#[cfg(not(target_os = "android"))] +fn checked_log2_not_android() { + assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16)); + assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16)); + assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16)); +} + +#[test] +fn checked_log10() { + assert_eq!(0u8.checked_log10(), None); + assert_eq!(0u16.checked_log10(), None); + assert_eq!(0i8.checked_log10(), None); + assert_eq!(0i16.checked_log10(), None); + + for i in i16::MIN..=0 { + assert_eq!(i.checked_log10(), None); + } + for i in 1..=i16::MAX { + assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16)); + } + for i in 1..=u16::MAX { + assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16)); + } +} + +macro_rules! log10_loop { + ($T:ty, $log10_max:expr) => { + assert_eq!(<$T>::MAX.log10(), $log10_max); + for i in 0..=$log10_max { + let p = (10 as $T).pow(i as u32); + if p >= 10 { + assert_eq!((p - 9).log10(), i - 1); + assert_eq!((p - 1).log10(), i - 1); + } + assert_eq!(p.log10(), i); + assert_eq!((p + 1).log10(), i); + if p >= 10 { + assert_eq!((p + 9).log10(), i); + } + + // also check `x.log(10)` + if p >= 10 { + assert_eq!((p - 9).log(10), i - 1); + assert_eq!((p - 1).log(10), i - 1); + } + assert_eq!(p.log(10), i); + assert_eq!((p + 1).log(10), i); + if p >= 10 { + assert_eq!((p + 9).log(10), i); + } + } + }; +} + +#[test] +fn log10_u8() { + log10_loop! { u8, 2 } +} + +#[test] +fn log10_u16() { + log10_loop! { u16, 4 } +} + +#[test] +fn log10_u32() { + log10_loop! { u32, 9 } +} + +#[test] +fn log10_u64() { + log10_loop! { u64, 19 } +} + +#[test] +fn log10_u128() { + log10_loop! { u128, 38 } +} diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index bbb67667df..76e838cf6b 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -29,6 +29,7 @@ mod u8; mod bignum; mod dec2flt; mod flt2dec; +mod int_log; mod ops; mod wrapping; diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index f4e5e7751b..612f083a5c 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -391,7 +391,6 @@ fn result_opt_conversions() { } #[test] -#[cfg(not(bootstrap))] // Needs the V2 trait fn result_try_trait_v2_branch() { use core::num::NonZeroU32; use core::ops::{ControlFlow::*, Try}; diff --git a/library/panic_unwind/src/dwarf/eh.rs b/library/panic_unwind/src/dwarf/eh.rs index 6dbf7c11b4..7394feab82 100644 --- a/library/panic_unwind/src/dwarf/eh.rs +++ b/library/panic_unwind/src/dwarf/eh.rs @@ -1,9 +1,9 @@ //! Parsing of GCC-style Language-Specific Data Area (LSDA) //! For details see: -//! * -//! * -//! * -//! * +//! * +//! * +//! * +//! * //! //! A reference implementation may be found in the GCC source tree //! (`/libgcc/unwind-c.c` as of this writing). diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 14f49bbf48..9d6ede73e3 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -5,8 +5,8 @@ //! documents linked from it. //! These are also good reads: //! * -//! * -//! * +//! * +//! * //! //! ## A brief summary //! @@ -94,7 +94,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class { // and TargetLowering::getExceptionSelectorRegister() for each architecture, // then mapped to DWARF register numbers via register definition tables // (typically RegisterInfo.td, search for "DwarfRegNum"). -// See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register. +// See also https://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register. #[cfg(target_arch = "x86")] const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX @@ -130,7 +130,7 @@ const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 cfg_if::cfg_if! { if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "netbsd")))] { // ARM EHABI personality routine. - // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf + // https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf // // iOS uses the default routine instead since it uses SjLj unwinding. #[lang = "eh_personality"] diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index d32a3f1f83..3622bc8294 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -23,7 +23,6 @@ #![feature(unwind_attributes)] #![feature(abi_thiscall)] #![feature(rustc_attrs)] -#![feature(raw)] #![panic_runtime] #![feature(panic_runtime)] // `real_imp` is unused with Miri, so silence warnings. diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 58028d4057..754dbb77af 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -42,7 +42,7 @@ //! of the `try` intrinsic. //! //! [win64]: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64 -//! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions +//! [llvm]: https://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions #![allow(nonstandard_style)] @@ -100,7 +100,7 @@ struct Exception { // In any case, these structures are all constructed in a similar manner, and // it's just somewhat verbose for us. // -// [1]: http://www.geoffchappell.com/studies/msvc/language/predefined/ +// [1]: https://www.geoffchappell.com/studies/msvc/language/predefined/ #[cfg(target_arch = "x86")] #[macro_use] diff --git a/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs index 717201aef1..d82669d3e2 100644 --- a/library/proc_macro/src/bridge/buffer.rs +++ b/library/proc_macro/src/bridge/buffer.rs @@ -5,35 +5,6 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::slice; -#[repr(C)] -struct Slice<'a, T> { - data: &'a [T; 0], - len: usize, -} - -unsafe impl<'a, T: Sync> Sync for Slice<'a, T> {} -unsafe impl<'a, T: Sync> Send for Slice<'a, T> {} - -impl Copy for Slice<'a, T> {} -impl Clone for Slice<'a, T> { - fn clone(&self) -> Self { - *self - } -} - -impl From<&'a [T]> for Slice<'a, T> { - fn from(xs: &'a [T]) -> Self { - Slice { data: unsafe { &*(xs.as_ptr() as *const [T; 0]) }, len: xs.len() } - } -} - -impl Deref for Slice<'a, T> { - type Target = [T]; - fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } - } -} - #[repr(C)] pub struct Buffer { data: *mut T, diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index a2953b6856..b968d44fe4 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -55,6 +55,7 @@ macro_rules! with_api { FreeFunctions { fn drop($self: $S::FreeFunctions); fn track_env_var(var: &str, value: Option<&str>); + fn track_path(path: &str); }, TokenStream { fn drop($self: $S::TokenStream); diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 588e6ded0f..42432563fa 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -246,7 +246,7 @@ impl DecodeMut<'_, '_, S> for String { } } -/// Simplied version of panic payloads, ignoring +/// Simplified version of panic payloads, ignoring /// types other than `&'static str` and `String`. pub enum PanicMessage { StaticStr(&'static str), diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 26fbf50e2d..53fd58a29d 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -31,7 +31,6 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(min_specialization)] -#![feature(bound_cloned)] #![recursion_limit = "256"] #[unstable(feature = "proc_macro_internals", issue = "27812")] @@ -85,14 +84,13 @@ impl !Sync for TokenStream {} /// Error returned from `TokenStream::from_str`. #[stable(feature = "proc_macro_lib", since = "1.15.0")] +#[non_exhaustive] #[derive(Debug)] -pub struct LexError { - _inner: (), -} +pub struct LexError; impl LexError { fn new() -> Self { - LexError { _inner: () } + LexError } } @@ -708,7 +706,7 @@ impl Group { /// pub fn span_open(&self) -> Span { /// ^ /// ``` - #[unstable(feature = "proc_macro_span", issue = "54725")] + #[stable(feature = "proc_macro_group_span", since = "1.55.0")] pub fn span_open(&self) -> Span { Span(self.0.span_open()) } @@ -719,7 +717,7 @@ impl Group { /// pub fn span_close(&self) -> Span { /// ^ /// ``` - #[unstable(feature = "proc_macro_span", issue = "54725")] + #[stable(feature = "proc_macro_group_span", since = "1.55.0")] pub fn span_close(&self) -> Span { Span(self.0.span_close()) } @@ -766,7 +764,7 @@ impl fmt::Debug for Group { } } -/// An `Punct` is an single punctuation character like `+`, `-` or `#`. +/// A `Punct` is a single punctuation character such as `+`, `-` or `#`. /// /// Multi-character operators like `+=` are represented as two instances of `Punct` with different /// forms of `Spacing` returned. @@ -779,16 +777,19 @@ impl !Send for Punct {} #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl !Sync for Punct {} -/// Whether an `Punct` is followed immediately by another `Punct` or -/// followed by another token or whitespace. +/// Describes whether a `Punct` is followed immediately by another `Punct` ([`Spacing::Joint`]) or +/// by a different token or whitespace ([`Spacing::Alone`]). #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub enum Spacing { - /// e.g., `+` is `Alone` in `+ =`, `+ident` or `+()`. + /// A `Punct` is not immediately followed by another `Punct`. + /// E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] Alone, - /// e.g., `+` is `Joint` in `+=` or `'#`. - /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`. + /// A `Punct` is immediately followed by another `Punct`. + /// E.g. `+` is `Joint` in `+=` and `++`. + /// + /// Additionally, single quote `'` can join with identifiers to form lifetimes: `'ident`. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] Joint, } @@ -1233,3 +1234,17 @@ pub mod tracked_env { value } } + +/// Tracked access to additional files. +#[unstable(feature = "track_path", issue = "73921")] +pub mod tracked_path { + + /// Track a file explicitly. + /// + /// Commonly used for tracking asset preprocessing. + #[unstable(feature = "track_path", issue = "73921")] + pub fn path>(path: P) { + let path: &str = path.as_ref(); + crate::bridge::client::FreeFunctions::track_path(path); + } +} diff --git a/library/profiler_builtins/Cargo.toml b/library/profiler_builtins/Cargo.toml index 7b7ca8029b..b7ab4f19f0 100644 --- a/library/profiler_builtins/Cargo.toml +++ b/library/profiler_builtins/Cargo.toml @@ -14,4 +14,4 @@ core = { path = "../core" } compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] } [build-dependencies] -cc = "1.0.68" +cc = "1.0.69" diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 0aae4674b2..f8884523cf 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -399,12 +399,11 @@ impl fmt::Display for Backtrace { let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path); f.add_context()?; for frame in frames { - let mut f = f.frame(); if frame.symbols.is_empty() { - f.print_raw(frame.frame.ip(), None, None, None)?; + f.frame().print_raw(frame.frame.ip(), None, None, None)?; } else { for symbol in frame.symbols.iter() { - f.print_raw_with_column( + f.frame().print_raw_with_column( frame.frame.ip(), symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)), symbol.filename.as_ref().map(|b| match b { diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index a1f52a9c2e..4a5efab905 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -454,7 +454,6 @@ impl HashMap { /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` - #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.base.len() @@ -893,7 +892,6 @@ where /// assert_eq!(map.remove(&1), Some("a")); /// assert_eq!(map.remove(&1), None); /// ``` - #[doc(alias = "delete")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, k: &Q) -> Option @@ -936,6 +934,7 @@ where /// Retains only the elements specified by the predicate. /// /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. + /// The elements are visited in unsorted (and unspecified) order. /// /// # Examples /// @@ -1831,6 +1830,7 @@ impl Debug for RawEntryBuilder<'_, K, V, S> { /// /// [`entry`]: HashMap::entry #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "HashMapEntry")] pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied entry. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 5220c8ad70..1a2a8afac8 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -202,7 +202,6 @@ impl HashSet { /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` - #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { @@ -875,7 +874,6 @@ where /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` - #[doc(alias = "delete")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, value: &Q) -> bool @@ -914,6 +912,7 @@ where /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// The elements are visited in unsorted (and unspecified) order. /// /// # Examples /// diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 4403280efc..64f88c1aba 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -305,7 +305,7 @@ impl Error for VarError { /// /// Discussion of this unsafety on Unix may be found in: /// -/// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188) +/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188) /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) /// /// # Panics @@ -344,7 +344,7 @@ fn _set_var(key: &OsStr, value: &OsStr) { /// /// Discussion of this unsafety on Unix may be found in: /// -/// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188) +/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188) /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) /// /// # Panics diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 14c2f961d3..ec9f012295 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -597,6 +597,9 @@ impl Error for char::ParseCharError { #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] impl Error for alloc::collections::TryReserveError {} +#[unstable(feature = "duration_checked_float", issue = "83400")] +impl Error for core::time::FromSecsError {} + // Copied from `any.rs`. impl dyn Error + 'static { /// Returns `true` if the boxed type is the same as `T` diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index c16d27fa1f..e0cc6ad1d4 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -324,18 +324,20 @@ impl f32 { /// Returns the square root of a number. /// - /// Returns NaN if `self` is a negative number. + /// Returns NaN if `self` is a negative number other than `-0.0`. /// /// # Examples /// /// ``` /// let positive = 4.0_f32; /// let negative = -4.0_f32; + /// let negative_zero = -0.0_f32; /// /// let abs_difference = (positive.sqrt() - 2.0).abs(); /// /// assert!(abs_difference <= f32::EPSILON); /// assert!(negative.sqrt().is_nan()); + /// assert!(negative_zero.sqrt() == negative_zero); /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -876,4 +878,40 @@ impl f32 { pub fn atanh(self) -> f32 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } + + /// Linear interpolation between `start` and `end`. + /// + /// This enables linear interpolation between `start` and `end`, where start is represented by + /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all + /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0 + /// at a given rate, the result will change from `start` to `end` at a similar rate. + /// + /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the + /// range from `start` to `end`. This also is useful for transition functions which might + /// move slightly past the end or start for a desired effect. Mathematically, the values + /// returned are equivalent to `start + self * (end - start)`, although we make a few specific + /// guarantees that are useful specifically to linear interpolation. + /// + /// These guarantees are: + /// + /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the + /// value at 1.0 is always `end`. (exactness) + /// * If `start` and `end` are [finite], the values will always move in the direction from + /// `start` to `end` (monotonicity) + /// * If `self` is [finite] and `start == end`, the value at any point will always be + /// `start == end`. (consistency) + /// + /// [finite]: #method.is_finite + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_interpolation", issue = "86269")] + pub fn lerp(self, start: f32, end: f32) -> f32 { + // consistent + if start == end { + start + + // exact/monotonic + } else { + self.mul_add(end, (-self).mul_add(start, start)) + } + } } diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 0d4b865f33..fe66a73afd 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -757,3 +757,66 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } + +#[test] +fn test_lerp_exact() { + // simple values + assert_eq!(f32::lerp(0.0, 2.0, 4.0), 2.0); + assert_eq!(f32::lerp(1.0, 2.0, 4.0), 4.0); + + // boundary values + assert_eq!(f32::lerp(0.0, f32::MIN, f32::MAX), f32::MIN); + assert_eq!(f32::lerp(1.0, f32::MIN, f32::MAX), f32::MAX); +} + +#[test] +fn test_lerp_consistent() { + assert_eq!(f32::lerp(f32::MAX, f32::MIN, f32::MIN), f32::MIN); + assert_eq!(f32::lerp(f32::MIN, f32::MAX, f32::MAX), f32::MAX); + + // as long as t is finite, a/b can be infinite + assert_eq!(f32::lerp(f32::MAX, f32::NEG_INFINITY, f32::NEG_INFINITY), f32::NEG_INFINITY); + assert_eq!(f32::lerp(f32::MIN, f32::INFINITY, f32::INFINITY), f32::INFINITY); +} + +#[test] +fn test_lerp_nan_infinite() { + // non-finite t is not NaN if a/b different + assert!(!f32::lerp(f32::INFINITY, f32::MIN, f32::MAX).is_nan()); + assert!(!f32::lerp(f32::NEG_INFINITY, f32::MIN, f32::MAX).is_nan()); +} + +#[test] +fn test_lerp_values() { + // just a few basic values + assert_eq!(f32::lerp(0.25, 1.0, 2.0), 1.25); + assert_eq!(f32::lerp(0.50, 1.0, 2.0), 1.50); + assert_eq!(f32::lerp(0.75, 1.0, 2.0), 1.75); +} + +#[test] +fn test_lerp_monotonic() { + // near 0 + let below_zero = f32::lerp(-f32::EPSILON, f32::MIN, f32::MAX); + let zero = f32::lerp(0.0, f32::MIN, f32::MAX); + let above_zero = f32::lerp(f32::EPSILON, f32::MIN, f32::MAX); + assert!(below_zero <= zero); + assert!(zero <= above_zero); + assert!(below_zero <= above_zero); + + // near 0.5 + let below_half = f32::lerp(0.5 - f32::EPSILON, f32::MIN, f32::MAX); + let half = f32::lerp(0.5, f32::MIN, f32::MAX); + let above_half = f32::lerp(0.5 + f32::EPSILON, f32::MIN, f32::MAX); + assert!(below_half <= half); + assert!(half <= above_half); + assert!(below_half <= above_half); + + // near 1 + let below_one = f32::lerp(1.0 - f32::EPSILON, f32::MIN, f32::MAX); + let one = f32::lerp(1.0, f32::MIN, f32::MAX); + let above_one = f32::lerp(1.0 + f32::EPSILON, f32::MIN, f32::MAX); + assert!(below_one <= one); + assert!(one <= above_one); + assert!(below_one <= above_one); +} diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 4c95df5ffe..7ed65b7daf 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -324,18 +324,20 @@ impl f64 { /// Returns the square root of a number. /// - /// Returns NaN if `self` is a negative number. + /// Returns NaN if `self` is a negative number other than `-0.0`. /// /// # Examples /// /// ``` /// let positive = 4.0_f64; /// let negative = -4.0_f64; + /// let negative_zero = -0.0_f64; /// /// let abs_difference = (positive.sqrt() - 2.0).abs(); /// /// assert!(abs_difference < 1e-10); /// assert!(negative.sqrt().is_nan()); + /// assert!(negative_zero.sqrt() == negative_zero); /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -879,6 +881,42 @@ impl f64 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } + /// Linear interpolation between `start` and `end`. + /// + /// This enables linear interpolation between `start` and `end`, where start is represented by + /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all + /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0 + /// at a given rate, the result will change from `start` to `end` at a similar rate. + /// + /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the + /// range from `start` to `end`. This also is useful for transition functions which might + /// move slightly past the end or start for a desired effect. Mathematically, the values + /// returned are equivalent to `start + self * (end - start)`, although we make a few specific + /// guarantees that are useful specifically to linear interpolation. + /// + /// These guarantees are: + /// + /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the + /// value at 1.0 is always `end`. (exactness) + /// * If `start` and `end` are [finite], the values will always move in the direction from + /// `start` to `end` (monotonicity) + /// * If `self` is [finite] and `start == end`, the value at any point will always be + /// `start == end`. (consistency) + /// + /// [finite]: #method.is_finite + #[must_use = "method returns a new number and does not mutate the original value"] + #[unstable(feature = "float_interpolation", issue = "86269")] + pub fn lerp(self, start: f64, end: f64) -> f64 { + // consistent + if start == end { + start + + // exact/monotonic + } else { + self.mul_add(end, (-self).mul_add(start, start)) + } + } + // Solaris/Illumos requires a wrapper around log, log2, and log10 functions // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 5c163cfe90..04cb010926 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -753,3 +753,58 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } + +#[test] +fn test_lerp_exact() { + // simple values + assert_eq!(f64::lerp(0.0, 2.0, 4.0), 2.0); + assert_eq!(f64::lerp(1.0, 2.0, 4.0), 4.0); + + // boundary values + assert_eq!(f64::lerp(0.0, f64::MIN, f64::MAX), f64::MIN); + assert_eq!(f64::lerp(1.0, f64::MIN, f64::MAX), f64::MAX); +} + +#[test] +fn test_lerp_consistent() { + assert_eq!(f64::lerp(f64::MAX, f64::MIN, f64::MIN), f64::MIN); + assert_eq!(f64::lerp(f64::MIN, f64::MAX, f64::MAX), f64::MAX); + + // as long as t is finite, a/b can be infinite + assert_eq!(f64::lerp(f64::MAX, f64::NEG_INFINITY, f64::NEG_INFINITY), f64::NEG_INFINITY); + assert_eq!(f64::lerp(f64::MIN, f64::INFINITY, f64::INFINITY), f64::INFINITY); +} + +#[test] +fn test_lerp_nan_infinite() { + // non-finite t is not NaN if a/b different + assert!(!f64::lerp(f64::INFINITY, f64::MIN, f64::MAX).is_nan()); + assert!(!f64::lerp(f64::NEG_INFINITY, f64::MIN, f64::MAX).is_nan()); +} + +#[test] +fn test_lerp_values() { + // just a few basic values + assert_eq!(f64::lerp(0.25, 1.0, 2.0), 1.25); + assert_eq!(f64::lerp(0.50, 1.0, 2.0), 1.50); + assert_eq!(f64::lerp(0.75, 1.0, 2.0), 1.75); +} + +#[test] +fn test_lerp_monotonic() { + // near 0 + let below_zero = f64::lerp(-f64::EPSILON, f64::MIN, f64::MAX); + let zero = f64::lerp(0.0, f64::MIN, f64::MAX); + let above_zero = f64::lerp(f64::EPSILON, f64::MIN, f64::MAX); + assert!(below_zero <= zero); + assert!(zero <= above_zero); + assert!(below_zero <= above_zero); + + // near 1 + let below_one = f64::lerp(1.0 - f64::EPSILON, f64::MIN, f64::MAX); + let one = f64::lerp(1.0, f64::MIN, f64::MAX); + let above_one = f64::lerp(1.0 + f64::EPSILON, f64::MIN, f64::MAX); + assert!(below_one <= one); + assert!(one <= above_one); + assert!(below_one <= above_one); +} diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 0184495eec..0b7dc256db 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -124,8 +124,8 @@ //! method is an [`OsString`] which can be round-tripped to a Windows //! string losslessly. //! -//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value -//! [Unicode code point]: http://www.unicode.org/glossary/#code_point +//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +//! [Unicode code point]: https://www.unicode.org/glossary/#code_point //! [`env::set_var()`]: crate::env::set_var //! [`env::var_os()`]: crate::env::var_os //! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index ca391ffb3d..2a85f375ae 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -694,7 +694,6 @@ impl OsStr { /// let os_str = OsStr::new("foo"); /// assert_eq!(os_str.len(), 3); /// ``` - #[doc(alias = "length")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")] #[inline] pub fn len(&self) -> usize { diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index a1636e2f60..bbe1ab4053 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -88,6 +88,7 @@ use crate::time::SystemTime; /// [`BufReader`]: io::BufReader /// [`sync_all`]: File::sync_all #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "File")] pub struct File { inner: fs_imp::File, } @@ -183,12 +184,14 @@ pub struct Permissions(fs_imp::FilePermissions); /// It is returned by [`Metadata::file_type`] method. #[stable(feature = "file_type", since = "1.1.0")] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[cfg_attr(not(test), rustc_diagnostic_item = "FileType")] pub struct FileType(fs_imp::FileType); /// A builder used to create directories in various manners. /// /// This builder also supports platform-specific options. #[stable(feature = "dir_builder", since = "1.6.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "DirBuilder")] #[derive(Debug)] pub struct DirBuilder { inner: fs_imp::DirBuilder, @@ -880,8 +883,7 @@ impl OpenOptions { /// This function will return an error under a number of different /// circumstances. Some of these error conditions are listed here, together /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not - /// part of the compatibility contract of the function, especially the - /// [`Other`] kind might change to more specific kinds in the future. + /// part of the compatibility contract of the function. /// /// * [`NotFound`]: The specified file does not exist and neither `create` /// or `create_new` is set. @@ -895,9 +897,11 @@ impl OpenOptions { /// exists. /// * [`InvalidInput`]: Invalid combinations of open options (truncate /// without write access, no access mode set, etc.). - /// * [`Other`]: One of the directory components of the specified file path + /// + /// The following errors don't match any existing [`io::ErrorKind`] at the moment: + /// * One of the directory components of the specified file path /// was not, in fact, a directory. - /// * [`Other`]: Filesystem-level errors: full disk, write permission + /// * Filesystem-level errors: full disk, write permission /// requested on a read-only file system, exceeded disk quota, too many /// open files, too long filename, too many symbolic links in the /// specified path (Unix-like systems only), etc. @@ -913,7 +917,6 @@ impl OpenOptions { /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists /// [`InvalidInput`]: io::ErrorKind::InvalidInput /// [`NotFound`]: io::ErrorKind::NotFound - /// [`Other`]: io::ErrorKind::Other /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied #[stable(feature = "rust1", since = "1.0.0")] pub fn open>(&self, path: P) -> io::Result { @@ -1007,6 +1010,32 @@ impl Metadata { self.file_type().is_file() } + /// Returns `true` if this metadata is for a symbolic link. + /// + /// # Examples + /// + #[cfg_attr(unix, doc = "```no_run")] + #[cfg_attr(not(unix), doc = "```ignore")] + /// #![feature(is_symlink)] + /// use std::fs; + /// use std::path::Path; + /// use std::os::unix::fs::symlink; + /// + /// fn main() -> std::io::Result<()> { + /// let link_path = Path::new("link"); + /// symlink("/origin_does_not_exists/", link_path)?; + /// + /// let metadata = fs::symlink_metadata(link_path)?; + /// + /// assert!(metadata.is_symlink()); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "is_symlink", issue = "85748")] + pub fn is_symlink(&self) -> bool { + self.file_type().is_symlink() + } + /// Returns the size of the file, in bytes, this metadata is for. /// /// # Examples @@ -1525,7 +1554,6 @@ impl AsInner for DirEntry { /// Ok(()) /// } /// ``` -#[doc(alias = "delete")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file>(path: P) -> io::Result<()> { fs_imp::unlink(path.as_ref()) @@ -1711,8 +1739,11 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { /// /// # Platform-specific behavior /// -/// This function currently corresponds to the `linkat` function with no flags -/// on Unix and the `CreateHardLink` function on Windows. +/// This function currently corresponds the `CreateHardLink` function on Windows. +/// On most Unix systems, it corresponds to the `linkat` function with no flags. +/// On Android, VxWorks, and Redox, it instead corresponds to the `link` function. +/// On MacOS, it uses the `linkat` function if it is available, but on very old +/// systems where `linkat` is not available, `link` is selected at runtime instead. /// Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior @@ -1960,7 +1991,6 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { /// Ok(()) /// } /// ``` -#[doc(alias = "delete")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { fs_imp::rmdir(path.as_ref()) @@ -1998,7 +2028,6 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// Ok(()) /// } /// ``` -#[doc(alias = "delete")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir_all>(path: P) -> io::Result<()> { fs_imp::remove_dir_all(path.as_ref()) @@ -2190,7 +2219,7 @@ impl DirBuilder { Some(p) => self.create_dir_all(p)?, None => { return Err(io::Error::new_const( - io::ErrorKind::Other, + io::ErrorKind::Uncategorized, &"failed to create whole tree", )); } diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index ce8d3a56f7..080b4b5d87 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -19,6 +19,10 @@ use crate::os::unix::fs::symlink as symlink_junction; use crate::os::windows::fs::{symlink_dir, symlink_file}; #[cfg(windows)] use crate::sys::fs::symlink_junction; +#[cfg(target_os = "macos")] +use crate::sys::weak::weak; +#[cfg(target_os = "macos")] +use libc::{c_char, c_int}; macro_rules! check { ($e:expr) => { @@ -79,6 +83,17 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool { } } +#[cfg(target_os = "macos")] +fn able_to_not_follow_symlinks_while_hard_linking() -> bool { + weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int); + linkat.get().is_some() +} + +#[cfg(not(target_os = "macos"))] +fn able_to_not_follow_symlinks_while_hard_linking() -> bool { + return true; +} + #[test] fn file_test_io_smoke_test() { let message = "it's alright. have a good time"; @@ -1329,7 +1344,8 @@ fn metadata_access_times() { match (a.created(), b.created()) { (Ok(t1), Ok(t2)) => assert!(t1 <= t2), (Err(e1), Err(e2)) - if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other + if e1.kind() == ErrorKind::Uncategorized + && e2.kind() == ErrorKind::Uncategorized || e1.kind() == ErrorKind::Unsupported && e2.kind() == ErrorKind::Unsupported => {} (a, b) => { @@ -1346,6 +1362,9 @@ fn symlink_hard_link() { if !got_symlink_permission(&tmpdir) { return; }; + if !able_to_not_follow_symlinks_while_hard_linking() { + return; + } // Create "file", a file. check!(fs::File::create(tmpdir.join("file"))); diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index d8021d3e99..32d194d961 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -438,7 +438,13 @@ impl Seek for BufReader { } impl SizeHint for BufReader { + #[inline] fn lower_bound(&self) -> usize { - self.buffer().len() + SizeHint::lower_bound(self.get_ref()) + self.buffer().len() + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(self.get_ref()).and_then(|up| self.buffer().len().checked_add(up)) } } diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index ef2769d431..c98244132b 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -68,7 +68,7 @@ use crate::ptr; /// [`flush`]: BufWriter::flush #[stable(feature = "rust1", since = "1.0.0")] pub struct BufWriter { - inner: Option, + inner: W, // The buffer. Avoid using this like a normal `Vec` in common code paths. // That is, don't use `buf.push`, `buf.extend_from_slice`, or any other // methods that require bounds checking or the like. This makes an enormous @@ -112,7 +112,7 @@ impl BufWriter { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(capacity: usize, inner: W) -> BufWriter { - BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false } + BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false } } /// Send data in our local buffer into the inner writer, looping as @@ -161,10 +161,9 @@ impl BufWriter { } let mut guard = BufGuard::new(&mut self.buf); - let inner = self.inner.as_mut().unwrap(); while !guard.done() { self.panicked = true; - let r = inner.write(guard.remaining()); + let r = self.inner.write(guard.remaining()); self.panicked = false; match r { @@ -212,7 +211,7 @@ impl BufWriter { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { - self.inner.as_ref().unwrap() + &self.inner } /// Gets a mutable reference to the underlying writer. @@ -232,7 +231,7 @@ impl BufWriter { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { - self.inner.as_mut().unwrap() + &mut self.inner } /// Returns a reference to the internally buffered data. @@ -308,7 +307,7 @@ impl BufWriter { pub fn into_inner(mut self) -> Result>> { match self.flush_buf() { Err(e) => Err(IntoInnerError::new(self, e)), - Ok(()) => Ok(self.inner.take().unwrap()), + Ok(()) => Ok(self.into_raw_parts().0), } } @@ -339,7 +338,12 @@ impl BufWriter { pub fn into_raw_parts(mut self) -> (W, Result, WriterPanicked>) { let buf = mem::take(&mut self.buf); let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; - (self.inner.take().unwrap(), buf) + + // SAFETY: forget(self) prevents double dropping inner + let inner = unsafe { ptr::read(&mut self.inner) }; + mem::forget(self); + + (inner, buf) } // Ensure this function does not get inlined into `write`, so that it @@ -643,7 +647,7 @@ where { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("BufWriter") - .field("writer", &self.inner.as_ref().unwrap()) + .field("writer", &self.inner) .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity())) .finish() } @@ -663,7 +667,7 @@ impl Seek for BufWriter { #[stable(feature = "rust1", since = "1.0.0")] impl Drop for BufWriter { fn drop(&mut self) { - if self.inner.is_some() && !self.panicked { + if !self.panicked { // dtors should not panic, so we ignore a failed flush let _r = self.flush_buf(); } diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs index 65497817f8..38076ab3a2 100644 --- a/library/std/src/io/buffered/mod.rs +++ b/library/std/src/io/buffered/mod.rs @@ -133,7 +133,6 @@ impl IntoInnerError { /// /// # Example /// ``` - /// #![feature(io_into_inner_error_parts)] /// use std::io::{BufWriter, ErrorKind, Write}; /// /// let mut not_enough_space = [0u8; 10]; @@ -143,7 +142,7 @@ impl IntoInnerError { /// let err = into_inner_err.into_error(); /// assert_eq!(err.kind(), ErrorKind::WriteZero); /// ``` - #[unstable(feature = "io_into_inner_error_parts", issue = "79704")] + #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")] pub fn into_error(self) -> Error { self.1 } @@ -156,7 +155,6 @@ impl IntoInnerError { /// /// # Example /// ``` - /// #![feature(io_into_inner_error_parts)] /// use std::io::{BufWriter, ErrorKind, Write}; /// /// let mut not_enough_space = [0u8; 10]; @@ -167,7 +165,7 @@ impl IntoInnerError { /// assert_eq!(err.kind(), ErrorKind::WriteZero); /// assert_eq!(recovered_writer.buffer(), b"t be actually written"); /// ``` - #[unstable(feature = "io_into_inner_error_parts", issue = "79704")] + #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")] pub fn into_parts(self) -> (Error, W) { (self.1, self.0) } diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 9527254c94..ae0cea985d 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -205,6 +205,62 @@ impl Cursor { } } +impl Cursor +where + T: AsRef<[u8]>, +{ + /// Returns the remaining slice. + /// + /// # Examples + /// + /// ``` + /// #![feature(cursor_remaining)] + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.remaining_slice(), &[1, 2, 3, 4, 5]); + /// + /// buff.set_position(2); + /// assert_eq!(buff.remaining_slice(), &[3, 4, 5]); + /// + /// buff.set_position(4); + /// assert_eq!(buff.remaining_slice(), &[5]); + /// + /// buff.set_position(6); + /// assert_eq!(buff.remaining_slice(), &[]); + /// ``` + #[unstable(feature = "cursor_remaining", issue = "86369")] + pub fn remaining_slice(&self) -> &[u8] { + let len = self.pos.min(self.inner.as_ref().len() as u64); + &self.inner.as_ref()[(len as usize)..] + } + + /// Returns `true` if the remaining slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(cursor_remaining)] + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// buff.set_position(2); + /// assert!(!buff.is_empty()); + /// + /// buff.set_position(5); + /// assert!(buff.is_empty()); + /// + /// buff.set_position(10); + /// assert!(buff.is_empty()); + /// ``` + #[unstable(feature = "cursor_remaining", issue = "86369")] + pub fn is_empty(&self) -> bool { + self.pos >= self.inner.as_ref().len() as u64 + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Cursor where @@ -268,7 +324,7 @@ where T: AsRef<[u8]>, { fn read(&mut self, buf: &mut [u8]) -> io::Result { - let n = Read::read(&mut self.fill_buf()?, buf)?; + let n = Read::read(&mut self.remaining_slice(), buf)?; self.pos += n as u64; Ok(n) } @@ -291,7 +347,7 @@ where fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { let n = buf.len(); - Read::read_exact(&mut self.fill_buf()?, buf)?; + Read::read_exact(&mut self.remaining_slice(), buf)?; self.pos += n as u64; Ok(()) } @@ -308,8 +364,7 @@ where T: AsRef<[u8]>, { fn fill_buf(&mut self) -> io::Result<&[u8]> { - let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64); - Ok(&self.inner.as_ref()[(amt as usize)..]) + Ok(self.remaining_slice()) } fn consume(&mut self, amt: usize) { self.pos += amt as u64; diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 56e6f08268..829ef3d98b 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -105,6 +105,12 @@ pub enum ErrorKind { /// The connection was reset by the remote server. #[stable(feature = "rust1", since = "1.0.0")] ConnectionReset, + /// The remote host is not reachable. + #[unstable(feature = "io_error_more", issue = "86442")] + HostUnreachable, + /// The network containing the remote host is not reachable. + #[unstable(feature = "io_error_more", issue = "86442")] + NetworkUnreachable, /// The connection was aborted (terminated) by the remote server. #[stable(feature = "rust1", since = "1.0.0")] ConnectionAborted, @@ -119,6 +125,9 @@ pub enum ErrorKind { /// local. #[stable(feature = "rust1", since = "1.0.0")] AddrNotAvailable, + /// The system's networking is down. + #[unstable(feature = "io_error_more", issue = "86442")] + NetworkDown, /// The operation failed because a pipe was closed. #[stable(feature = "rust1", since = "1.0.0")] BrokenPipe, @@ -129,6 +138,38 @@ pub enum ErrorKind { /// requested to not occur. #[stable(feature = "rust1", since = "1.0.0")] WouldBlock, + /// A filesystem object is, unexpectedly, not a directory. + /// + /// For example, a filesystem path was specified where one of the intermediate directory + /// components was, in fact, a plain file. + #[unstable(feature = "io_error_more", issue = "86442")] + NotADirectory, + /// The filesystem object is, unexpectedly, a directory. + /// + /// A directory was specified when a non-directory was expected. + #[unstable(feature = "io_error_more", issue = "86442")] + IsADirectory, + /// A non-empty directory was specified where an empty directory was expected. + #[unstable(feature = "io_error_more", issue = "86442")] + DirectoryNotEmpty, + /// The filesystem or storage medium is read-only, but a write operation was attempted. + #[unstable(feature = "io_error_more", issue = "86442")] + ReadOnlyFilesystem, + /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. + /// + /// There was a loop (or excessively long chain) resolving a filesystem object + /// or file IO object. + /// + /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the + /// system-specific limit on the depth of symlink traversal. + #[unstable(feature = "io_error_more", issue = "86442")] + FilesystemLoop, + /// Stale network file handle. + /// + /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated + /// by problems with the network or server. + #[unstable(feature = "io_error_more", issue = "86442")] + StaleNetworkFileHandle, /// A parameter was incorrect. #[stable(feature = "rust1", since = "1.0.0")] InvalidInput, @@ -158,17 +199,78 @@ pub enum ErrorKind { /// [`Ok(0)`]: Ok #[stable(feature = "rust1", since = "1.0.0")] WriteZero, + /// The underlying storage (typically, a filesystem) is full. + /// + /// This does not include out of quota errors. + #[unstable(feature = "io_error_more", issue = "86442")] + StorageFull, + /// Seek on unseekable file. + /// + /// Seeking was attempted on an open file handle which is not suitable for seeking - for + /// example, on Unix, a named pipe opened with `File::open`. + #[unstable(feature = "io_error_more", issue = "86442")] + NotSeekable, + /// Filesystem quota was exceeded. + #[unstable(feature = "io_error_more", issue = "86442")] + FilesystemQuotaExceeded, + /// File larger than allowed or supported. + /// + /// This might arise from a hard limit of the underlying filesystem or file access API, or from + /// an administratively imposed resource limitation. Simple disk full, and out of quota, have + /// their own errors. + #[unstable(feature = "io_error_more", issue = "86442")] + FileTooLarge, + /// Resource is busy. + #[unstable(feature = "io_error_more", issue = "86442")] + ResourceBusy, + /// Executable file is busy. + /// + /// An attempt was made to write to a file which is also in use as a running program. (Not all + /// operating systems detect this situation.) + #[unstable(feature = "io_error_more", issue = "86442")] + ExecutableFileBusy, + /// Deadlock (avoided). + /// + /// A file locking operation would result in deadlock. This situation is typically detected, if + /// at all, on a best-effort basis. + #[unstable(feature = "io_error_more", issue = "86442")] + Deadlock, + /// Cross-device or cross-filesystem (hard) link or rename. + #[unstable(feature = "io_error_more", issue = "86442")] + CrossesDevices, + /// Too many (hard) links to the same filesystem object. + /// + /// The filesystem does not support making so many hardlinks to the same file. + #[unstable(feature = "io_error_more", issue = "86442")] + TooManyLinks, + /// Filename too long. + /// + /// The limit might be from the underlying filesystem or API, or an administratively imposed + /// resource limit. + #[unstable(feature = "io_error_more", issue = "86442")] + FilenameTooLong, + /// Program argument list too long. + /// + /// When trying to run an external program, a system or process limit on the size of the + /// arguments would have been exceeded. + #[unstable(feature = "io_error_more", issue = "86442")] + ArgumentListTooLong, /// This operation was interrupted. /// /// Interrupted operations can typically be retried. #[stable(feature = "rust1", since = "1.0.0")] Interrupted, - /// Any I/O error not part of this list. + + /// A custom error that does not fall under any other I/O error kind. /// - /// Errors that are `Other` now may move to a different or a new - /// [`ErrorKind`] variant in the future. It is not recommended to match - /// an error against `Other` and to expect any additional characteristics, - /// e.g., a specific [`Error::raw_os_error`] return value. + /// This can be used to construct your own [`Error`]s that do not match any + /// [`ErrorKind`]. + /// + /// This [`ErrorKind`] is not used by the standard library. + /// + /// Errors from the standard library that do not fall under any of the I/O + /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. + /// New [`ErrorKind`]s might be added in the future for some of those. #[stable(feature = "rust1", since = "1.0.0")] Other, @@ -191,31 +293,62 @@ pub enum ErrorKind { /// to allocate enough memory. #[stable(feature = "out_of_memory_error", since = "1.54.0")] OutOfMemory, + + /// Any I/O error from the standard library that's not part of this list. + /// + /// Errors that are `Uncategorized` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Uncategorized`; use a wildcard match (`_`) instead. + #[unstable(feature = "io_error_uncategorized", issue = "none")] + #[doc(hidden)] + Uncategorized, } impl ErrorKind { pub(crate) fn as_str(&self) -> &'static str { + use ErrorKind::*; match *self { - ErrorKind::NotFound => "entity not found", - ErrorKind::PermissionDenied => "permission denied", - ErrorKind::ConnectionRefused => "connection refused", - ErrorKind::ConnectionReset => "connection reset", - ErrorKind::ConnectionAborted => "connection aborted", - ErrorKind::NotConnected => "not connected", - ErrorKind::AddrInUse => "address in use", - ErrorKind::AddrNotAvailable => "address not available", - ErrorKind::BrokenPipe => "broken pipe", - ErrorKind::AlreadyExists => "entity already exists", - ErrorKind::WouldBlock => "operation would block", - ErrorKind::InvalidInput => "invalid input parameter", - ErrorKind::InvalidData => "invalid data", - ErrorKind::TimedOut => "timed out", - ErrorKind::WriteZero => "write zero", - ErrorKind::Interrupted => "operation interrupted", - ErrorKind::Other => "other os error", - ErrorKind::UnexpectedEof => "unexpected end of file", - ErrorKind::Unsupported => "unsupported", - ErrorKind::OutOfMemory => "out of memory", + AddrInUse => "address in use", + AddrNotAvailable => "address not available", + AlreadyExists => "entity already exists", + ArgumentListTooLong => "argument list too long", + BrokenPipe => "broken pipe", + ResourceBusy => "resource busy", + ConnectionAborted => "connection aborted", + ConnectionRefused => "connection refused", + ConnectionReset => "connection reset", + CrossesDevices => "cross-device link or rename", + Deadlock => "deadlock", + DirectoryNotEmpty => "directory not empty", + ExecutableFileBusy => "executable file busy", + FilenameTooLong => "filename too long", + FilesystemQuotaExceeded => "filesystem quota exceeded", + FileTooLarge => "file too large", + HostUnreachable => "host unreachable", + Interrupted => "operation interrupted", + InvalidData => "invalid data", + InvalidInput => "invalid input parameter", + IsADirectory => "is a directory", + NetworkDown => "network down", + NetworkUnreachable => "network unreachable", + NotADirectory => "not a directory", + StorageFull => "no storage space", + NotConnected => "not connected", + NotFound => "entity not found", + Other => "other error", + OutOfMemory => "out of memory", + PermissionDenied => "permission denied", + ReadOnlyFilesystem => "read-only filesystem or storage medium", + StaleNetworkFileHandle => "stale network file handle", + FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", + NotSeekable => "seek on unseekable file", + TimedOut => "timed out", + TooManyLinks => "too many links", + Uncategorized => "uncategorized error", + UnexpectedEof => "unexpected end of file", + Unsupported => "unsupported", + WouldBlock => "operation would block", + WriteZero => "write zero", } } } @@ -538,7 +671,7 @@ impl Error { /// } /// /// fn main() { - /// // Will print "Other". + /// // Will print "Uncategorized". /// print_error(Error::last_os_error()); /// // Will print "AddrInUse". /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 4c154dbe01..cc615b95f8 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -252,7 +252,9 @@ mod tests; use crate::cmp; +use crate::convert::TryInto; use crate::fmt; +use crate::mem::replace; use crate::ops::{Deref, DerefMut}; use crate::ptr; use crate::slice; @@ -275,6 +277,8 @@ pub use self::error::{Error, ErrorKind, Result}; pub use self::stdio::set_output_capture; #[stable(feature = "rust1", since = "1.0.0")] pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout}; +#[unstable(feature = "stdio_locked", issue = "86845")] +pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::stdio::{StderrLock, StdinLock, StdoutLock}; #[unstable(feature = "print_internals", issue = "none")] @@ -510,6 +514,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ /// [`File`]: crate::fs::File #[stable(feature = "rust1", since = "1.0.0")] #[doc(notable_trait)] +#[cfg_attr(not(test), rustc_diagnostic_item = "IoRead")] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -1044,6 +1049,32 @@ impl<'a> IoSliceMut<'a> { /// Advance the internal cursor of the slice. /// + /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of + /// multiple buffers. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_slice_advance)] + /// + /// use std::io::IoSliceMut; + /// use std::ops::Deref; + /// + /// let mut data = [1; 8]; + /// let mut buf = IoSliceMut::new(&mut data); + /// + /// // Mark 3 bytes as read. + /// buf.advance(3); + /// assert_eq!(buf.deref(), [1; 5].as_ref()); + /// ``` + #[unstable(feature = "io_slice_advance", issue = "62726")] + #[inline] + pub fn advance(&mut self, n: usize) { + self.0.advance(n) + } + + /// Advance the internal cursor of the slices. + /// /// # Notes /// /// Elements in the slice may be modified if the cursor is not advanced to @@ -1070,13 +1101,13 @@ impl<'a> IoSliceMut<'a> { /// ][..]; /// /// // Mark 10 bytes as read. - /// bufs = IoSliceMut::advance(bufs, 10); + /// IoSliceMut::advance_slices(&mut bufs, 10); /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); /// ``` #[unstable(feature = "io_slice_advance", issue = "62726")] #[inline] - pub fn advance<'b>(bufs: &'b mut [IoSliceMut<'a>], n: usize) -> &'b mut [IoSliceMut<'a>] { + pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; // Total length of all the to be removed buffers. @@ -1090,11 +1121,10 @@ impl<'a> IoSliceMut<'a> { } } - let bufs = &mut bufs[remove..]; + *bufs = &mut replace(bufs, &mut [])[remove..]; if !bufs.is_empty() { - bufs[0].0.advance(n - accumulated_len) + bufs[0].advance(n - accumulated_len) } - bufs } } @@ -1153,6 +1183,32 @@ impl<'a> IoSlice<'a> { /// Advance the internal cursor of the slice. /// + /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple + /// buffers. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_slice_advance)] + /// + /// use std::io::IoSlice; + /// use std::ops::Deref; + /// + /// let mut data = [1; 8]; + /// let mut buf = IoSlice::new(&mut data); + /// + /// // Mark 3 bytes as read. + /// buf.advance(3); + /// assert_eq!(buf.deref(), [1; 5].as_ref()); + /// ``` + #[unstable(feature = "io_slice_advance", issue = "62726")] + #[inline] + pub fn advance(&mut self, n: usize) { + self.0.advance(n) + } + + /// Advance the internal cursor of the slices. + /// /// # Notes /// /// Elements in the slice may be modified if the cursor is not advanced to @@ -1179,12 +1235,12 @@ impl<'a> IoSlice<'a> { /// ][..]; /// /// // Mark 10 bytes as written. - /// bufs = IoSlice::advance(bufs, 10); + /// IoSlice::advance_slices(&mut bufs, 10); /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); #[unstable(feature = "io_slice_advance", issue = "62726")] #[inline] - pub fn advance<'b>(bufs: &'b mut [IoSlice<'a>], n: usize) -> &'b mut [IoSlice<'a>] { + pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) { // Number of buffers to remove. let mut remove = 0; // Total length of all the to be removed buffers. @@ -1198,11 +1254,10 @@ impl<'a> IoSlice<'a> { } } - let bufs = &mut bufs[remove..]; + *bufs = &mut replace(bufs, &mut [])[remove..]; if !bufs.is_empty() { - bufs[0].0.advance(n - accumulated_len) + bufs[0].advance(n - accumulated_len) } - bufs } } @@ -1307,6 +1362,7 @@ impl Initializer { /// [`write_all`]: Write::write_all #[stable(feature = "rust1", since = "1.0.0")] #[doc(notable_trait)] +#[cfg_attr(not(test), rustc_diagnostic_item = "IoWrite")] pub trait Write { /// Write a buffer into this writer, returning how many bytes were written. /// @@ -1364,6 +1420,27 @@ pub trait Write { /// The default implementation calls [`write`] with either the first nonempty /// buffer provided, or an empty one if none exists. /// + /// # Examples + /// + /// ```no_run + /// use std::io::IoSlice; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut data1 = [1; 8]; + /// let mut data2 = [15; 8]; + /// let io_slice1 = IoSlice::new(&mut data1); + /// let io_slice2 = IoSlice::new(&mut data2); + /// + /// let mut buffer = File::create("foo.txt")?; + /// + /// // Writes some prefix of the byte string, not necessarily all of it. + /// buffer.write_vectored(&[io_slice1, io_slice2])?; + /// Ok(()) + /// } + /// ``` + /// /// [`write`]: Write::write #[stable(feature = "iovec", since = "1.36.0")] fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result { @@ -1511,7 +1588,7 @@ pub trait Write { fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> { // Guarantee that bufs is empty if it contains no data, // to avoid calling write_vectored if there is no data to be written. - bufs = IoSlice::advance(bufs, 0); + IoSlice::advance_slices(&mut bufs, 0); while !bufs.is_empty() { match self.write_vectored(bufs) { Ok(0) => { @@ -1520,7 +1597,7 @@ pub trait Write { &"failed to write whole buffer", )); } - Ok(n) => bufs = IoSlice::advance(bufs, n), + Ok(n) => IoSlice::advance_slices(&mut bufs, n), Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } @@ -1592,7 +1669,7 @@ pub trait Write { if output.error.is_err() { output.error } else { - Err(Error::new_const(ErrorKind::Other, &"formatter error")) + Err(Error::new_const(ErrorKind::Uncategorized, &"formatter error")) } } } @@ -1684,7 +1761,6 @@ pub trait Seek { /// # Example /// /// ```no_run - /// #![feature(seek_rewind)] /// use std::io::{Read, Seek, Write}; /// use std::fs::OpenOptions; /// @@ -1702,7 +1778,7 @@ pub trait Seek { /// f.read_to_string(&mut buf).unwrap(); /// assert_eq!(&buf, hello); /// ``` - #[unstable(feature = "seek_rewind", issue = "85149")] + #[stable(feature = "seek_rewind", since = "1.55.0")] fn rewind(&mut self) -> Result<()> { self.seek(SeekFrom::Start(0))?; Ok(()) @@ -1953,6 +2029,37 @@ pub trait BufRead: Read { #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); + /// Check if the underlying `Read` has any data left to be read. + /// + /// This function may fill the buffer to check for data, + /// so this functions returns `Result`, not `bool`. + /// + /// Default implementation calls `fill_buf` and checks that + /// returned slice is empty (which means that there is no data left, + /// since EOF is reached). + /// + /// Examples + /// + /// ``` + /// #![feature(buf_read_has_data_left)] + /// use std::io; + /// use std::io::prelude::*; + /// + /// let stdin = io::stdin(); + /// let mut stdin = stdin.lock(); + /// + /// while stdin.has_data_left().unwrap() { + /// let mut line = String::new(); + /// stdin.read_line(&mut line).unwrap(); + /// // work with line + /// println!("{:?}", line); + /// } + /// ``` + #[unstable(feature = "buf_read_has_data_left", reason = "recently added", issue = "86423")] + fn has_data_left(&mut self) -> Result { + self.fill_buf().map(|b| !b.is_empty()) + } + /// Read all bytes into `buf` until the delimiter `byte` or EOF is reached. /// /// This function will read bytes from the underlying stream until the @@ -2291,13 +2398,15 @@ impl BufRead for Chain { } impl SizeHint for Chain { + #[inline] fn lower_bound(&self) -> usize { SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second) } + #[inline] fn upper_bound(&self) -> Option { match (SizeHint::upper_bound(&self.first), SizeHint::upper_bound(&self.second)) { - (Some(first), Some(second)) => Some(first + second), + (Some(first), Some(second)) => first.checked_add(second), _ => None, } } @@ -2502,6 +2611,21 @@ impl BufRead for Take { } } +impl SizeHint for Take { + #[inline] + fn lower_bound(&self) -> usize { + cmp::min(SizeHint::lower_bound(&self.inner) as u64, self.limit) as usize + } + + #[inline] + fn upper_bound(&self) -> Option { + match SizeHint::upper_bound(&self.inner) { + Some(upper_bound) => Some(cmp::min(upper_bound as u64, self.limit) as usize), + None => self.limit.try_into().ok(), + } + } +} + /// An iterator over `u8` values of a reader. /// /// This struct is generally created by calling [`bytes`] on a reader. @@ -2546,15 +2670,53 @@ trait SizeHint { } impl SizeHint for T { + #[inline] default fn lower_bound(&self) -> usize { 0 } + #[inline] default fn upper_bound(&self) -> Option { None } } +impl SizeHint for &mut T { + #[inline] + fn lower_bound(&self) -> usize { + SizeHint::lower_bound(*self) + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(*self) + } +} + +impl SizeHint for Box { + #[inline] + fn lower_bound(&self) -> usize { + SizeHint::lower_bound(&**self) + } + + #[inline] + fn upper_bound(&self) -> Option { + SizeHint::upper_bound(&**self) + } +} + +impl SizeHint for &[u8] { + #[inline] + fn lower_bound(&self) -> usize { + self.len() + } + + #[inline] + fn upper_bound(&self) -> Option { + Some(self.len()) + } +} + /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 2b0d2b7e0b..65ad7d88e2 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -7,7 +7,7 @@ use crate::io::prelude::*; use crate::cell::{Cell, RefCell}; use crate::fmt; -use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter}; +use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter, Lines, Split}; use crate::lazy::SyncOnceCell; use crate::pin::Pin; use crate::sync::atomic::{AtomicBool, Ordering}; @@ -310,6 +310,48 @@ pub fn stdin() -> Stdin { } } +/// Constructs a new locked handle to the standard input of the current +/// process. +/// +/// Each handle returned is a guard granting locked access to a shared +/// global buffer whose access is synchronized via a mutex. If you need +/// more explicit control over locking, for example, in a multi-threaded +/// program, use the [`io::stdin`] function to obtain an unlocked handle, +/// along with the [`Stdin::lock`] method. +/// +/// The lock is released when the returned guard goes out of scope. The +/// returned guard also implements the [`Read`] and [`BufRead`] traits for +/// accessing the underlying data. +/// +/// **Note**: The mutex locked by this handle is not reentrant. Even in a +/// single-threaded program, calling other code that accesses [`Stdin`] +/// could cause a deadlock or panic, if this locked handle is held across +/// that call. +/// +/// ### Note: Windows Portability Consideration +/// When operating in a console, the Windows implementation of this stream does not support +/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return +/// an error. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(stdio_locked)] +/// use std::io::{self, Read}; +/// +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// let mut handle = io::stdin_locked(); +/// +/// handle.read_to_string(&mut buffer)?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "stdio_locked", issue = "86845")] +pub fn stdin_locked() -> StdinLock<'static> { + stdin().into_locked() +} + impl Stdin { /// Locks this handle to the standard input stream, returning a readable /// guard. @@ -334,7 +376,7 @@ impl Stdin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock<'_> { - StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + self.lock_any() } /// Locks this handle and reads a line of input, appending it to the specified buffer. @@ -367,6 +409,86 @@ impl Stdin { pub fn read_line(&self, buf: &mut String) -> io::Result { self.lock().read_line(buf) } + + // Locks this handle with any lifetime. This depends on the + // implementation detail that the underlying `Mutex` is static. + fn lock_any<'a>(&self) -> StdinLock<'a> { + StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + } + + /// Consumes this handle to the standard input stream, locking the + /// shared global buffer associated with the stream and returning a + /// readable guard. + /// + /// The lock is released when the returned guard goes out of scope. The + /// returned guard also implements the [`Read`] and [`BufRead`] traits + /// for accessing the underlying data. + /// + /// It is often simpler to directly get a locked handle using the + /// [`stdin_locked`] function instead, unless nearby code also needs to + /// use an unlocked handle. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(stdio_locked)] + /// use std::io::{self, Read}; + /// + /// fn main() -> io::Result<()> { + /// let mut buffer = String::new(); + /// let mut handle = io::stdin().into_locked(); + /// + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "stdio_locked", issue = "86845")] + pub fn into_locked(self) -> StdinLock<'static> { + self.lock_any() + } + + /// Consumes this handle and returns an iterator over input lines. + /// + /// For detailed semantics of this method, see the documentation on + /// [`BufRead::lines`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(stdin_forwarders)] + /// use std::io; + /// + /// let lines = io::stdin().lines(); + /// for line in lines { + /// println!("got a line: {}", line.unwrap()); + /// } + /// ``` + #[unstable(feature = "stdin_forwarders", issue = "87096")] + pub fn lines(self) -> Lines> { + self.into_locked().lines() + } + + /// Consumes this handle and returns an iterator over input bytes, + /// split at the specified byte value. + /// + /// For detailed semantics of this method, see the documentation on + /// [`BufRead::split`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(stdin_forwarders)] + /// use std::io; + /// + /// let splits = io::stdin().split(b'-'); + /// for split in splits { + /// println!("got a chunk: {}", String::from_utf8_lossy(&split.unwrap())); + /// } + /// ``` + #[unstable(feature = "stdin_forwarders", issue = "87096")] + pub fn split(self, byte: u8) -> Split> { + self.into_locked().split(byte) + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -558,6 +680,42 @@ pub fn stdout() -> Stdout { } } +/// Constructs a new locked handle to the standard output of the current +/// process. +/// +/// Each handle returned is a guard granting locked access to a shared +/// global buffer whose access is synchronized via a mutex. If you need +/// more explicit control over locking, for example, in a multi-threaded +/// program, use the [`io::stdout`] function to obtain an unlocked handle, +/// along with the [`Stdout::lock`] method. +/// +/// The lock is released when the returned guard goes out of scope. The +/// returned guard also implements the [`Write`] trait for writing data. +/// +/// ### Note: Windows Portability Consideration +/// When operating in a console, the Windows implementation of this stream does not support +/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return +/// an error. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(stdio_locked)] +/// use std::io::{self, Write}; +/// +/// fn main() -> io::Result<()> { +/// let mut handle = io::stdout_locked(); +/// +/// handle.write_all(b"hello world")?; +/// +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "stdio_locked", issue = "86845")] +pub fn stdout_locked() -> StdoutLock<'static> { + stdout().into_locked() +} + pub fn cleanup() { if let Some(instance) = STDOUT.get() { // Flush the data and disable buffering during shutdown @@ -595,8 +753,45 @@ impl Stdout { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock<'_> { + self.lock_any() + } + + // Locks this handle with any lifetime. This depends on the + // implementation detail that the underlying `ReentrantMutex` is + // static. + fn lock_any<'a>(&self) -> StdoutLock<'a> { StdoutLock { inner: self.inner.lock() } } + + /// Consumes this handle to the standard output stream, locking the + /// shared global buffer associated with the stream and returning a + /// writable guard. + /// + /// The lock is released when the returned lock goes out of scope. The + /// returned guard also implements the [`Write`] trait for writing data. + /// + /// It is often simpler to directly get a locked handle using the + /// [`io::stdout_locked`] function instead, unless nearby code also + /// needs to use an unlocked handle. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(stdio_locked)] + /// use std::io::{self, Write}; + /// + /// fn main() -> io::Result<()> { + /// let mut handle = io::stdout().into_locked(); + /// + /// handle.write_all(b"hello world")?; + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "stdio_locked", issue = "86845")] + pub fn into_locked(self) -> StdoutLock<'static> { + self.lock_any() + } } #[stable(feature = "std_debug", since = "1.16.0")] @@ -769,6 +964,35 @@ pub fn stderr() -> Stderr { } } +/// Constructs a new locked handle to the standard error of the current +/// process. +/// +/// This handle is not buffered. +/// +/// ### Note: Windows Portability Consideration +/// When operating in a console, the Windows implementation of this stream does not support +/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return +/// an error. +/// +/// # Example +/// +/// ```no_run +/// #![feature(stdio_locked)] +/// use std::io::{self, Write}; +/// +/// fn main() -> io::Result<()> { +/// let mut handle = io::stderr_locked(); +/// +/// handle.write_all(b"hello world")?; +/// +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "stdio_locked", issue = "86845")] +pub fn stderr_locked() -> StderrLock<'static> { + stderr().into_locked() +} + impl Stderr { /// Locks this handle to the standard error stream, returning a writable /// guard. @@ -792,8 +1016,42 @@ impl Stderr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StderrLock<'_> { + self.lock_any() + } + + // Locks this handle with any lifetime. This depends on the + // implementation detail that the underlying `ReentrantMutex` is + // static. + fn lock_any<'a>(&self) -> StderrLock<'a> { StderrLock { inner: self.inner.lock() } } + + /// Locks and consumes this handle to the standard error stream, + /// returning a writable guard. + /// + /// The lock is released when the returned guard goes out of scope. The + /// returned guard also implements the [`Write`] trait for writing + /// data. + /// + /// # Examples + /// + /// ``` + /// #![feature(stdio_locked)] + /// use std::io::{self, Write}; + /// + /// fn foo() -> io::Result<()> { + /// let stderr = io::stderr(); + /// let mut handle = stderr.into_locked(); + /// + /// handle.write_all(b"hello world")?; + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "stdio_locked", issue = "86845")] + pub fn into_locked(self) -> StderrLock<'static> { + self.lock_any() + } } #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/library/std/src/io/stdio/tests.rs b/library/std/src/io/stdio/tests.rs index 04af500268..b1df6b7131 100644 --- a/library/std/src/io/stdio/tests.rs +++ b/library/std/src/io/stdio/tests.rs @@ -1,5 +1,6 @@ use super::*; use crate::panic::{RefUnwindSafe, UnwindSafe}; +use crate::sync::mpsc::sync_channel; use crate::thread; #[test] @@ -45,3 +46,121 @@ fn panic_doesnt_poison() { let _a = stderr(); let _a = _a.lock(); } + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_lock_stderr() { + test_lock(stderr, stderr_locked); +} +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_lock_stdin() { + test_lock(stdin, stdin_locked); +} +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_lock_stdout() { + test_lock(stdout, stdout_locked); +} + +// Helper trait to make lock testing function generic. +trait Stdio<'a>: 'static +where + Self::Lock: 'a, +{ + type Lock; + fn lock(&'a self) -> Self::Lock; +} +impl<'a> Stdio<'a> for Stderr { + type Lock = StderrLock<'a>; + fn lock(&'a self) -> StderrLock<'a> { + self.lock() + } +} +impl<'a> Stdio<'a> for Stdin { + type Lock = StdinLock<'a>; + fn lock(&'a self) -> StdinLock<'a> { + self.lock() + } +} +impl<'a> Stdio<'a> for Stdout { + type Lock = StdoutLock<'a>; + fn lock(&'a self) -> StdoutLock<'a> { + self.lock() + } +} + +// Helper trait to make lock testing function generic. +trait StdioOwnedLock: 'static {} +impl StdioOwnedLock for StderrLock<'static> {} +impl StdioOwnedLock for StdinLock<'static> {} +impl StdioOwnedLock for StdoutLock<'static> {} + +// Tests locking on stdio handles by starting two threads and checking that +// they block each other appropriately. +fn test_lock(get_handle: fn() -> T, get_locked: fn() -> U) +where + T: for<'a> Stdio<'a>, + U: StdioOwnedLock, +{ + // State enum to track different phases of the test, primarily when + // each lock is acquired and released. + #[derive(Debug, PartialEq)] + enum State { + Start1, + Acquire1, + Start2, + Release1, + Acquire2, + Release2, + } + use State::*; + // Logging vector to be checked to make sure lock acquisitions and + // releases happened in the correct order. + let log = Arc::new(Mutex::new(Vec::new())); + let ((tx1, rx1), (tx2, rx2)) = (sync_channel(0), sync_channel(0)); + let th1 = { + let (log, tx) = (Arc::clone(&log), tx1); + thread::spawn(move || { + log.lock().unwrap().push(Start1); + let handle = get_handle(); + { + let locked = handle.lock(); + log.lock().unwrap().push(Acquire1); + tx.send(Acquire1).unwrap(); // notify of acquisition + tx.send(Release1).unwrap(); // wait for release command + log.lock().unwrap().push(Release1); + } + tx.send(Acquire1).unwrap(); // wait for th2 acquire + { + let locked = handle.lock(); + log.lock().unwrap().push(Acquire1); + } + log.lock().unwrap().push(Release1); + }) + }; + let th2 = { + let (log, tx) = (Arc::clone(&log), tx2); + thread::spawn(move || { + tx.send(Start2).unwrap(); // wait for start command + let locked = get_locked(); + log.lock().unwrap().push(Acquire2); + tx.send(Acquire2).unwrap(); // notify of acquisition + tx.send(Release2).unwrap(); // wait for release command + log.lock().unwrap().push(Release2); + }) + }; + assert_eq!(rx1.recv().unwrap(), Acquire1); // wait for th1 acquire + log.lock().unwrap().push(Start2); + assert_eq!(rx2.recv().unwrap(), Start2); // block th2 + assert_eq!(rx1.recv().unwrap(), Release1); // release th1 + assert_eq!(rx2.recv().unwrap(), Acquire2); // wait for th2 acquire + assert_eq!(rx1.recv().unwrap(), Acquire1); // block th1 + assert_eq!(rx2.recv().unwrap(), Release2); // release th2 + th2.join().unwrap(); + th1.join().unwrap(); + assert_eq!( + *log.lock().unwrap(), + [Start1, Acquire1, Start2, Release1, Acquire2, Release2, Acquire1, Release1] + ); +} diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 2b14e16150..1beb72a9a5 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -71,6 +71,16 @@ fn lines() { assert!(s.next().is_none()); } +#[test] +fn buf_read_has_data_left() { + let mut buf = Cursor::new(&b"abcd"[..]); + assert!(buf.has_data_left().unwrap()); + buf.read_exact(&mut [0; 2]).unwrap(); + assert!(buf.has_data_left().unwrap()); + buf.read_exact(&mut [0; 2]).unwrap(); + assert!(!buf.has_data_left().unwrap()); +} + #[test] fn read_to_end() { let mut c = Cursor::new(&b""[..]); @@ -224,6 +234,24 @@ fn empty_size_hint() { assert_eq!(size_hint, (0, Some(0))); } +#[test] +fn slice_size_hint() { + let size_hint = (&[1, 2, 3]).bytes().size_hint(); + assert_eq!(size_hint, (3, Some(3))); +} + +#[test] +fn take_size_hint() { + let size_hint = (&[1, 2, 3]).take(2).bytes().size_hint(); + assert_eq!(size_hint, (2, Some(2))); + + let size_hint = (&[1, 2, 3]).take(4).bytes().size_hint(); + assert_eq!(size_hint, (3, Some(3))); + + let size_hint = io::repeat(0).take(3).bytes().size_hint(); + assert_eq!(size_hint, (3, Some(3))); +} + #[test] fn chain_empty_size_hint() { let chain = io::empty().chain(io::empty()); @@ -242,7 +270,7 @@ fn chain_size_hint() { let chain = buf_reader_1.chain(buf_reader_2); let size_hint = chain.bytes().size_hint(); - assert_eq!(size_hint, (testdata.len(), None)); + assert_eq!(size_hint, (testdata.len(), Some(testdata.len()))); } #[test] @@ -308,6 +336,10 @@ fn seek_position() -> io::Result<()> { assert_eq!(c.stream_position()?, 8); assert_eq!(c.stream_position()?, 8); + c.rewind()?; + assert_eq!(c.stream_position()?, 0); + assert_eq!(c.stream_position()?, 0); + Ok(()) } @@ -353,7 +385,7 @@ fn test_read_to_end_capacity() -> io::Result<()> { } #[test] -fn io_slice_mut_advance() { +fn io_slice_mut_advance_slices() { let mut buf1 = [1; 8]; let mut buf2 = [2; 16]; let mut buf3 = [3; 8]; @@ -364,75 +396,75 @@ fn io_slice_mut_advance() { ][..]; // Only in a single buffer.. - bufs = IoSliceMut::advance(bufs, 1); + IoSliceMut::advance_slices(&mut bufs, 1); assert_eq!(bufs[0].deref(), [1; 7].as_ref()); assert_eq!(bufs[1].deref(), [2; 16].as_ref()); assert_eq!(bufs[2].deref(), [3; 8].as_ref()); // Removing a buffer, leaving others as is. - bufs = IoSliceMut::advance(bufs, 7); + IoSliceMut::advance_slices(&mut bufs, 7); assert_eq!(bufs[0].deref(), [2; 16].as_ref()); assert_eq!(bufs[1].deref(), [3; 8].as_ref()); // Removing a buffer and removing from the next buffer. - bufs = IoSliceMut::advance(bufs, 18); + IoSliceMut::advance_slices(&mut bufs, 18); assert_eq!(bufs[0].deref(), [3; 6].as_ref()); } #[test] -fn io_slice_mut_advance_empty_slice() { - let empty_bufs = &mut [][..]; +fn io_slice_mut_advance_slices_empty_slice() { + let mut empty_bufs = &mut [][..]; // Shouldn't panic. - IoSliceMut::advance(empty_bufs, 1); + IoSliceMut::advance_slices(&mut empty_bufs, 1); } #[test] -fn io_slice_mut_advance_beyond_total_length() { +fn io_slice_mut_advance_slices_beyond_total_length() { let mut buf1 = [1; 8]; let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..]; // Going beyond the total length should be ok. - bufs = IoSliceMut::advance(bufs, 9); + IoSliceMut::advance_slices(&mut bufs, 9); assert!(bufs.is_empty()); } #[test] -fn io_slice_advance() { +fn io_slice_advance_slices() { let buf1 = [1; 8]; let buf2 = [2; 16]; let buf3 = [3; 8]; let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..]; // Only in a single buffer.. - bufs = IoSlice::advance(bufs, 1); + IoSlice::advance_slices(&mut bufs, 1); assert_eq!(bufs[0].deref(), [1; 7].as_ref()); assert_eq!(bufs[1].deref(), [2; 16].as_ref()); assert_eq!(bufs[2].deref(), [3; 8].as_ref()); // Removing a buffer, leaving others as is. - bufs = IoSlice::advance(bufs, 7); + IoSlice::advance_slices(&mut bufs, 7); assert_eq!(bufs[0].deref(), [2; 16].as_ref()); assert_eq!(bufs[1].deref(), [3; 8].as_ref()); // Removing a buffer and removing from the next buffer. - bufs = IoSlice::advance(bufs, 18); + IoSlice::advance_slices(&mut bufs, 18); assert_eq!(bufs[0].deref(), [3; 6].as_ref()); } #[test] -fn io_slice_advance_empty_slice() { - let empty_bufs = &mut [][..]; +fn io_slice_advance_slices_empty_slice() { + let mut empty_bufs = &mut [][..]; // Shouldn't panic. - IoSlice::advance(empty_bufs, 1); + IoSlice::advance_slices(&mut empty_bufs, 1); } #[test] -fn io_slice_advance_beyond_total_length() { +fn io_slice_advance_slices_beyond_total_length() { let buf1 = [1; 8]; let mut bufs = &mut [IoSlice::new(&buf1)][..]; // Going beyond the total length should be ok. - bufs = IoSlice::advance(bufs, 9); + IoSlice::advance_slices(&mut bufs, 9); assert!(bufs.is_empty()); } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 73f2f3eb3f..fd52de7430 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -13,9 +13,8 @@ use crate::io::{ /// This struct is generally created by calling [`empty()`]. Please see /// the documentation of [`empty()`] for more details. #[stable(feature = "rust1", since = "1.0.0")] -pub struct Empty { - _priv: (), -} +#[non_exhaustive] +pub struct Empty; /// Constructs a new handle to an empty reader. /// @@ -35,7 +34,7 @@ pub struct Empty { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn empty() -> Empty { - Empty { _priv: () } + Empty } #[stable(feature = "rust1", since = "1.0.0")] @@ -83,6 +82,7 @@ impl fmt::Debug for Empty { } impl SizeHint for Empty { + #[inline] fn upper_bound(&self) -> Option { Some(0) } @@ -147,6 +147,18 @@ impl Read for Repeat { } } +impl SizeHint for Repeat { + #[inline] + fn lower_bound(&self) -> usize { + usize::MAX + } + + #[inline] + fn upper_bound(&self) -> Option { + None + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Repeat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -159,9 +171,8 @@ impl fmt::Debug for Repeat { /// This struct is generally created by calling [`sink`]. Please /// see the documentation of [`sink()`] for more details. #[stable(feature = "rust1", since = "1.0.0")] -pub struct Sink { - _priv: (), -} +#[non_exhaustive] +pub struct Sink; /// Creates an instance of a writer which will successfully consume all data. /// @@ -182,7 +193,7 @@ pub struct Sink { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_io_structs", issue = "78812")] pub const fn sink() -> Sink { - Sink { _priv: () } + Sink } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 5b8e83766f..605bd33a4b 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -971,7 +971,7 @@ mod match_keyword {} /// ``` /// /// Like [`struct`]s and [`enum`]s, a module and its content are private by -/// default, unaccessible to code outside of the module. +/// default, inaccessible to code outside of the module. /// /// To learn more about allowing access, see the documentation for the [`pub`] /// keyword. @@ -1092,8 +1092,7 @@ mod move_keyword {} /// Mutable raw pointers work much like mutable references, with the added /// possibility of not pointing to a valid object. The syntax is `*mut Type`. /// -/// More information on mutable references and pointers can be found in``` -/// [Reference]. +/// More information on mutable references and pointers can be found in the [Reference]. /// /// [Reference]: ../reference/types/pointer.html#mutable-references-mut mod mut_keyword {} @@ -2257,6 +2256,9 @@ mod await_keyword {} /// At run-time, when a method needs to be called on the `dyn Trait`, the vtable is consulted to get /// the function pointer and then that function pointer is called. /// +/// See the Reference for more information on [trait objects][ref-trait-obj] +/// and [object safety][ref-obj-safety]. +/// /// ## Trade-offs /// /// The above indirection is the additional runtime cost of calling a function on a `dyn Trait`. @@ -2265,9 +2267,9 @@ mod await_keyword {} /// However, `dyn Trait` is likely to produce smaller code than `impl Trait` / generic parameters as /// the method won't be duplicated for each concrete type. /// -/// Read more about `object safety` and [trait object]s. -/// /// [trait object]: ../book/ch17-02-trait-objects.html +/// [ref-trait-obj]: ../reference/types/trait-object.html +/// [ref-obj-safety]: ../reference/items/traits.html#object-safety /// [erased]: https://en.wikipedia.org/wiki/Type_erasure mod dyn_keyword {} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 31dcd9546b..cfbfe7cc19 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -225,13 +225,14 @@ #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(async_stream)] #![feature(arbitrary_self_types)] #![feature(array_error_internals)] #![feature(asm)] #![feature(assert_matches)] #![feature(associated_type_bounds)] +#![feature(async_stream)] #![feature(atomic_mut_ptr)] +#![feature(auto_traits)] #![feature(bench_black_box)] #![feature(box_syntax)] #![feature(c_variadic)] @@ -244,14 +245,14 @@ #![feature(concat_idents)] #![feature(const_cstr_unchecked)] #![feature(const_fn_floating_point_arithmetic)] -#![feature(const_fn_transmute)] #![feature(const_fn_fn_ptr_basics)] +#![feature(const_fn_transmute)] #![feature(const_io_structs)] #![feature(const_ip)] +#![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] #![feature(const_socketaddr)] -#![feature(const_ipv4)] #![feature(container_error_extra)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] @@ -261,12 +262,13 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] +#![feature(duration_checked_float)] #![feature(duration_constants)] #![feature(edition_panic)] #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] -#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] +#![feature(float_interpolation)] #![feature(fn_traits)] #![feature(format_args_nl)] #![feature(gen_future)] @@ -275,8 +277,8 @@ #![feature(global_asm)] #![feature(hashmap_internals)] #![feature(int_error_internals)] -#![feature(int_error_matching)] #![feature(integer_atomics)] +#![feature(int_log)] #![feature(into_future)] #![feature(intra_doc_pointers)] #![feature(iter_zip)] @@ -286,7 +288,6 @@ #![feature(log_syntax)] #![feature(map_try_insert)] #![feature(maybe_uninit_extra)] -#![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] @@ -297,15 +298,12 @@ #![feature(nll)] #![feature(nonnull_slice_from_raw_parts)] #![feature(once_cell)] -#![feature(auto_traits)] #![feature(panic_info_message)] #![feature(panic_internals)] #![feature(panic_unwind)] #![feature(pin_static_ref)] -#![feature(prelude_2021)] #![feature(prelude_import)] #![feature(ptr_internals)] -#![feature(raw)] #![feature(ready_macro)] #![feature(rustc_attrs)] #![feature(rustc_private)] @@ -330,6 +328,7 @@ #![feature(unboxed_closures)] #![feature(unsafe_cell_raw_get)] #![feature(unwind_attributes)] +#![feature(unwrap_infallible)] #![feature(vec_into_raw_parts)] #![feature(vec_spare_capacity)] // NB: the above list is sorted to minimize merge conflicts. @@ -456,9 +455,6 @@ pub use core::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use core::ptr; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future)] -pub use core::raw; -#[stable(feature = "rust1", since = "1.0.0")] pub use core::result; #[unstable(feature = "async_stream", issue = "79024")] pub use core::stream; @@ -560,9 +556,9 @@ pub use core::{ #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] pub use core::{ - asm, assert, assert_matches, cfg, column, compile_error, concat, concat_idents, env, file, - format_args, format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, - log_syntax, module_path, option_env, stringify, trace_macros, + assert, assert_matches, cfg, column, compile_error, concat, concat_idents, env, file, + format_args, format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, + module_path, option_env, stringify, trace_macros, }; #[stable(feature = "core_primitive", since = "1.43.0")] diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index b2c5df5410..7afe52a3fd 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -6,7 +6,8 @@ #[doc = include_str!("../../core/src/macros/panic.md")] #[macro_export] -#[rustc_builtin_macro = "std_panic"] +#[cfg_attr(bootstrap, rustc_builtin_macro = "std_panic")] +#[cfg_attr(not(bootstrap), rustc_builtin_macro(std_panic))] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(edition_panic)] #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")] diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 2b6d0d7d5d..4b6d60d121 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -379,7 +379,7 @@ impl Ipv4Addr { /// This property is defined in _UNIX Network Programming, Second Edition_, /// W. Richard Stevens, p. 891; see also [ip7]. /// - /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html + /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html /// /// # Examples /// @@ -1346,47 +1346,6 @@ impl Ipv6Addr { (self.segments()[0] & 0xffc0) == 0xfe80 } - /// Returns [`true`] if this is a deprecated unicast site-local address (`fec0::/10`). The - /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as: - /// - /// ```no_rust - /// | 10 | - /// | bits | 54 bits | 64 bits | - /// +----------+-------------------------+----------------------------+ - /// |1111111011| subnet ID | interface ID | - /// +----------+-------------------------+----------------------------+ - /// ``` - /// - /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// assert_eq!( - /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), - /// false - /// ); - /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); - /// ``` - /// - /// # Warning - /// - /// As per [RFC 3879], the whole `fec0::/10` prefix is - /// deprecated. New software must not support site-local - /// addresses. - /// - /// [RFC 3879]: https://tools.ietf.org/html/rfc3879 - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] - #[unstable(feature = "ip", issue = "27709")] - #[inline] - pub const fn is_unicast_site_local(&self) -> bool { - (self.segments()[0] & 0xffc0) == 0xfec0 - } - /// Returns [`true`] if this is an address reserved for documentation /// (`2001:db8::/32`). /// diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index 05f8dea0b7..2109980ad0 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -480,7 +480,6 @@ fn ipv6_properties() { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 6; let unicast_global: u16 = 1 << 7; let documentation: u16 = 1 << 8; let multicast_interface_local: u16 = 1 << 9; @@ -523,11 +522,6 @@ fn ipv6_properties() { } else { assert!(!ip!($s).is_unicast_link_local()); } - if ($mask & unicast_site_local) == unicast_site_local { - assert!(ip!($s).is_unicast_site_local()); - } else { - assert!(!ip!($s).is_unicast_site_local()); - } if ($mask & unicast_global) == unicast_global { assert!(ip!($s).is_unicast_global()); } else { @@ -581,7 +575,6 @@ fn ipv6_properties() { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 6; let unicast_global: u16 = 1 << 7; let documentation: u16 = 1 << 8; let multicast_interface_local: u16 = 1 << 9; @@ -651,7 +644,7 @@ fn ipv6_properties() { check!( "fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_site_local | unicast_global | global + unicast_global | global ); check!( @@ -889,9 +882,6 @@ fn ipv6_const() { const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local(); assert!(!IS_UNICAST_LINK_LOCAL); - const IS_UNICAST_SITE_LOCAL: bool = IP_ADDRESS.is_unicast_site_local(); - assert!(!IS_UNICAST_SITE_LOCAL); - const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); assert!(!IS_DOCUMENTATION); diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index abe9bc24ce..387a3617e5 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -342,7 +342,7 @@ fn double_bind() { Err(e) => { assert!( e.kind() == ErrorKind::ConnectionRefused - || e.kind() == ErrorKind::Other + || e.kind() == ErrorKind::Uncategorized || e.kind() == ErrorKind::AddrInUse, "unknown error: {} {:?}", e, diff --git a/library/std/src/num.rs b/library/std/src/num.rs index 0f1c596268..e7051f0ce9 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num.rs @@ -22,12 +22,7 @@ pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, #[stable(feature = "nonzero", since = "1.28.0")] pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; -#[unstable( - feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639" -)] +#[stable(feature = "int_error_matching", since = "1.55.0")] pub use core::num::IntErrorKind; #[cfg(test)] diff --git a/library/std/src/os/fortanix_sgx/arch.rs b/library/std/src/os/fortanix_sgx/arch.rs index b0170e6744..4ce482e23c 100644 --- a/library/std/src/os/fortanix_sgx/arch.rs +++ b/library/std/src/os/fortanix_sgx/arch.rs @@ -33,13 +33,13 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result, u32> asm!( // rbx is reserved by LLVM - "xchg {0}, rbx", + "xchg %rbx, {0}", "enclu", - "mov rbx, {0}", + "mov {0}, %rbx", inout(reg) request => _, inlateout("eax") ENCLU_EGETKEY => error, in("rcx") out.as_mut_ptr(), - options(nostack), + options(att_syntax, nostack), ); match error { @@ -64,14 +64,14 @@ pub fn ereport( asm!( // rbx is reserved by LLVM - "xchg {0}, rbx", + "xchg %rbx, {0}", "enclu", - "mov rbx, {0}", + "mov {0}, %rbx", inout(reg) targetinfo => _, in("eax") ENCLU_EREPORT, in("rcx") reportdata, in("rdx") report.as_mut_ptr(), - options(preserves_flags, nostack), + options(att_syntax, preserves_flags, nostack), ); report.assume_init() diff --git a/library/std/src/os/fortanix_sgx/ffi.rs b/library/std/src/os/fortanix_sgx/ffi.rs index 63fc5ff286..ac1db0e5e3 100644 --- a/library/std/src/os/fortanix_sgx/ffi.rs +++ b/library/std/src/os/fortanix_sgx/ffi.rs @@ -34,5 +34,8 @@ #![unstable(feature = "sgx_platform", issue = "56975")] +#[path = "../unix/ffi/os_str.rs"] +mod os_str; + #[unstable(feature = "sgx_platform", issue = "56975")] -pub use crate::sys_common::os_str_bytes::*; +pub use self::os_str::{OsStrExt, OsStringExt}; diff --git a/library/std/src/os/hermit/ffi.rs b/library/std/src/os/hermit/ffi.rs index 07b59a0255..19761fd99b 100644 --- a/library/std/src/os/hermit/ffi.rs +++ b/library/std/src/os/hermit/ffi.rs @@ -34,5 +34,8 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[path = "../unix/ffi/os_str.rs"] +mod os_str; + #[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::os_str_bytes::*; +pub use self::os_str::{OsStrExt, OsStringExt}; diff --git a/library/std/src/os/unix/ffi.rs b/library/std/src/os/unix/ffi/mod.rs similarity index 93% rename from library/std/src/os/unix/ffi.rs rename to library/std/src/os/unix/ffi/mod.rs index 123f85deaf..c29df6596f 100644 --- a/library/std/src/os/unix/ffi.rs +++ b/library/std/src/os/unix/ffi/mod.rs @@ -34,5 +34,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +mod os_str; + #[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::os_str_bytes::*; +pub use self::os_str::{OsStrExt, OsStringExt}; diff --git a/library/std/src/os/unix/ffi/os_str.rs b/library/std/src/os/unix/ffi/os_str.rs new file mode 100644 index 0000000000..54c9a9382f --- /dev/null +++ b/library/std/src/os/unix/ffi/os_str.rs @@ -0,0 +1,68 @@ +use crate::ffi::{OsStr, OsString}; +use crate::mem; +use crate::sealed::Sealed; +use crate::sys::os_str::Buf; +use crate::sys_common::{AsInner, FromInner, IntoInner}; + +// Note: this file is currently reused in other `std::os::{platform}::ffi` modules to reduce duplication. +// Keep this in mind when applying changes to this file that only apply to `unix`. + +/// Platform-specific extensions to [`OsString`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStringExt: Sealed { + /// Creates an [`OsString`] from a byte vector. + /// + /// See the module documentation for an example. + #[stable(feature = "rust1", since = "1.0.0")] + fn from_vec(vec: Vec) -> Self; + + /// Yields the underlying byte vector of this [`OsString`]. + /// + /// See the module documentation for an example. + #[stable(feature = "rust1", since = "1.0.0")] + fn into_vec(self) -> Vec; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStringExt for OsString { + fn from_vec(vec: Vec) -> OsString { + FromInner::from_inner(Buf { inner: vec }) + } + fn into_vec(self) -> Vec { + self.into_inner().inner + } +} + +/// Platform-specific extensions to [`OsStr`]. +/// +/// This trait is sealed: it cannot be implemented outside the standard library. +/// This is so that future additional methods are not breaking changes. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStrExt: Sealed { + #[stable(feature = "rust1", since = "1.0.0")] + /// Creates an [`OsStr`] from a byte slice. + /// + /// See the module documentation for an example. + fn from_bytes(slice: &[u8]) -> &Self; + + /// Gets the underlying byte view of the [`OsStr`] slice. + /// + /// See the module documentation for an example. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_bytes(&self) -> &[u8]; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStrExt for OsStr { + #[inline] + fn from_bytes(slice: &[u8]) -> &OsStr { + unsafe { mem::transmute(slice) } + } + #[inline] + fn as_bytes(&self) -> &[u8] { + &self.as_inner().inner + } +} diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 913c71d410..e4ce788f74 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -9,6 +9,8 @@ use crate::path::Path; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; // Used for `File::read` on intra-doc links +use crate::ffi::OsStr; +use crate::sealed::Sealed; #[allow(unused_imports)] use io::{Read, Write}; @@ -839,6 +841,43 @@ impl DirEntryExt for fs::DirEntry { } } +/// Sealed Unix-specific extension methods for [`fs::DirEntry`]. +#[unstable(feature = "dir_entry_ext2", issue = "85573")] +pub trait DirEntryExt2: Sealed { + /// Returns a reference to the underlying `OsStr` of this entry's filename. + /// + /// # Examples + /// + /// ``` + /// #![feature(dir_entry_ext2)] + /// use std::os::unix::fs::DirEntryExt2; + /// use std::{fs, io}; + /// + /// fn main() -> io::Result<()> { + /// let mut entries = fs::read_dir(".")?.collect::, io::Error>>()?; + /// entries.sort_unstable_by(|a, b| a.file_name_ref().cmp(b.file_name_ref())); + /// + /// for p in entries { + /// println!("{:?}", p); + /// } + /// + /// Ok(()) + /// } + /// ``` + fn file_name_ref(&self) -> &OsStr; +} + +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl Sealed for fs::DirEntry {} + +#[unstable(feature = "dir_entry_ext2", issue = "85573")] +impl DirEntryExt2 for fs::DirEntry { + fn file_name_ref(&self) -> &OsStr { + self.as_inner().file_name_os_str() + } +} + /// Creates a new symbolic link on the filesystem. /// /// The `link` path will be a symbolic link pointing to the `original` path. diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 15ce7056fe..cd429d1426 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -32,23 +32,8 @@ pub(super) fn recv_vectored_with_ancillary_from( msg.msg_name = &mut msg_name as *mut _ as *mut _; msg.msg_namelen = size_of::() as libc::socklen_t; msg.msg_iov = bufs.as_mut_ptr().cast(); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_iovlen = bufs.len() as libc::size_t; - msg.msg_controllen = ancillary.buffer.len() as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_iovlen = bufs.len() as libc::c_int; - msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t; - } - } + msg.msg_iovlen = bufs.len() as _; + msg.msg_controllen = ancillary.buffer.len() as _; // macos requires that the control pointer is null when the len is 0. if msg.msg_controllen > 0 { msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); @@ -80,23 +65,8 @@ pub(super) fn send_vectored_with_ancillary_to( msg.msg_name = &mut msg_name as *mut _ as *mut _; msg.msg_namelen = msg_namelen; msg.msg_iov = bufs.as_ptr() as *mut _; - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_iovlen = bufs.len() as libc::size_t; - msg.msg_controllen = ancillary.length as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_iovlen = bufs.len() as libc::c_int; - msg.msg_controllen = ancillary.length as libc::socklen_t; - } - } + msg.msg_iovlen = bufs.len() as _; + msg.msg_controllen = ancillary.length as _; // macos requires that the control pointer is null when the len is 0. if msg.msg_controllen > 0 { msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); @@ -144,21 +114,7 @@ fn add_to_ancillary_data( let mut msg: libc::msghdr = zeroed(); msg.msg_control = buffer.as_mut_ptr().cast(); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_controllen = *length as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_controllen = *length as libc::socklen_t; - } - } + msg.msg_controllen = *length as _; let mut cmsg = libc::CMSG_FIRSTHDR(&msg); let mut previous_cmsg = cmsg; @@ -180,21 +136,7 @@ fn add_to_ancillary_data( (*previous_cmsg).cmsg_level = cmsg_level; (*previous_cmsg).cmsg_type = cmsg_type; - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::socklen_t; - } - } + (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as _; let data = libc::CMSG_DATA(previous_cmsg).cast(); @@ -364,28 +306,10 @@ impl<'a> AncillaryData<'a> { fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result { unsafe { - cfg_if::cfg_if! { - if #[cfg(any( - target_os = "android", - all(target_os = "linux", target_env = "gnu"), - all(target_os = "linux", target_env = "uclibc"), - ))] { - let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - let cmsg_len_zero = libc::CMSG_LEN(0) as libc::socklen_t; - } - } - let data_len = (*cmsg).cmsg_len - cmsg_len_zero; + let cmsg_len_zero = libc::CMSG_LEN(0) as usize; + let data_len = (*cmsg).cmsg_len as usize - cmsg_len_zero; let data = libc::CMSG_DATA(cmsg).cast(); - let data = from_raw_parts(data, data_len as usize); + let data = from_raw_parts(data, data_len); match (*cmsg).cmsg_level { libc::SOL_SOCKET => match (*cmsg).cmsg_type { @@ -419,21 +343,7 @@ impl<'a> Iterator for Messages<'a> { unsafe { let mut msg: libc::msghdr = zeroed(); msg.msg_control = self.buffer.as_ptr() as *mut _; - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_controllen = self.buffer.len() as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_controllen = self.buffer.len() as libc::socklen_t; - } - } + msg.msg_controllen = self.buffer.len() as _; let cmsg = if let Some(current) = self.current { libc::CMSG_NXTHDR(&msg, current) diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 3dc389b758..f3b5227df8 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -226,7 +226,7 @@ pub trait ExitStatusExt: Sealed { /// /// Panics on an attempt to make an `ExitStatusError` from a wait status of `0`. /// - /// Making an `ExitStatus` always succeds and never panics. + /// Making an `ExitStatus` always succeeds and never panics. #[stable(feature = "exit_status_from", since = "1.12.0")] fn from_raw(raw: i32) -> Self; diff --git a/library/std/src/os/wasi/ffi.rs b/library/std/src/os/wasi/ffi.rs index f71f316d1b..17e12a395a 100644 --- a/library/std/src/os/wasi/ffi.rs +++ b/library/std/src/os/wasi/ffi.rs @@ -2,5 +2,8 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[path = "../unix/ffi/os_str.rs"] +mod os_str; + #[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::os_str_bytes::*; +pub use self::os_str::{OsStrExt, OsStringExt}; diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index ba4057bd34..bd30d6ae3f 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -1,7 +1,7 @@ //! WASI-specific extensions to primitives in the `std::fs` module. #![deny(unsafe_op_in_unsafe_fn)] -#![unstable(feature = "wasi_ext", issue = "none")] +#![unstable(feature = "wasi_ext", issue = "71213")] use crate::ffi::OsStr; use crate::fs::{self, File, Metadata, OpenOptions}; @@ -532,5 +532,6 @@ pub fn symlink_path, U: AsRef>(old_path: P, new_path: U) -> } fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) + f.to_str() + .ok_or_else(|| io::Error::new_const(io::ErrorKind::Uncategorized, &"input must be utf-8")) } diff --git a/library/std/src/os/wasi/io.rs b/library/std/src/os/wasi/io.rs index b2e79cc1b4..cf4501b98c 100644 --- a/library/std/src/os/wasi/io.rs +++ b/library/std/src/os/wasi/io.rs @@ -1,7 +1,7 @@ //! WASI-specific extensions to general I/O primitives #![deny(unsafe_op_in_unsafe_fn)] -#![unstable(feature = "wasi_ext", issue = "none")] +#![unstable(feature = "wasi_ext", issue = "71213")] use crate::fs; use crate::io; diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 67756b1553..9e7ccd015b 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -2,6 +2,7 @@ #![stable(feature = "process_extensions", since = "1.2.0")] +use crate::ffi::OsStr; use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; use crate::process; use crate::sealed::Sealed; @@ -125,6 +126,13 @@ pub trait CommandExt: Sealed { /// [2]: #[unstable(feature = "windows_process_extensions_force_quotes", issue = "82227")] fn force_quotes(&mut self, enabled: bool) -> &mut process::Command; + + /// Append literal text to the command line without any quoting or escaping. + /// + /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow + /// `CommandLineToArgvW` escaping rules. + #[unstable(feature = "windows_process_extensions_raw_arg", issue = "29494")] + fn raw_arg>(&mut self, text_to_append_as_is: S) -> &mut process::Command; } #[stable(feature = "windows_process_extensions", since = "1.16.0")] @@ -138,4 +146,9 @@ impl CommandExt for process::Command { self.as_inner_mut().force_quotes(enabled); self } + + fn raw_arg>(&mut self, raw_text: S) -> &mut process::Command { + self.as_inner_mut().raw_arg(raw_text.as_ref()); + self + } } diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 9e3880dfd4..7bc987db88 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -133,7 +133,7 @@ pub fn panic_any(msg: M) -> ! { /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be /// implemented for any closed over variables passed to `catch_unwind`. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(all(not(bootstrap), not(test)), lang = "unwind_safe")] +#[cfg_attr(not(test), rustc_diagnostic_item = "unwind_safe_trait")] #[rustc_on_unimplemented( message = "the type `{Self}` may not be safely transferred across an unwind boundary", label = "`{Self}` may not be safely transferred across an unwind boundary" @@ -149,7 +149,7 @@ pub auto trait UnwindSafe {} /// This is a "helper marker trait" used to provide impl blocks for the /// [`UnwindSafe`] trait, for more information see that documentation. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(all(not(bootstrap), not(test)), lang = "ref_unwind_safe")] +#[cfg_attr(not(test), rustc_diagnostic_item = "ref_unwind_safe_trait")] #[rustc_on_unimplemented( message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ transferrable across a catch_unwind boundary", diff --git a/library/std/src/path.rs b/library/std/src/path.rs index ede147aca1..c71751efb9 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -951,7 +951,7 @@ impl FusedIterator for Components<'_> {} impl<'a> cmp::PartialEq for Components<'a> { #[inline] fn eq(&self, other: &Components<'a>) -> bool { - Iterator::eq(self.clone(), other.clone()) + Iterator::eq(self.clone().rev(), other.clone().rev()) } } @@ -2592,6 +2592,32 @@ impl Path { fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) } + /// Returns true if the path exists on disk and is pointing at a symbolic link. + /// + /// This function will not traverse symbolic links. + /// In case of a broken symbolic link this will also return true. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return false. + /// + /// # Examples + /// + #[cfg_attr(unix, doc = "```no_run")] + #[cfg_attr(not(unix), doc = "```ignore")] + /// #![feature(is_symlink)] + /// use std::path::Path; + /// use std::os::unix::fs::symlink; + /// + /// let link_path = Path::new("link"); + /// symlink("/origin_does_not_exists/", link_path).unwrap(); + /// assert_eq!(link_path.is_symlink(), true); + /// assert_eq!(link_path.exists(), false); + /// ``` + #[unstable(feature = "is_symlink", issue = "85748")] + pub fn is_symlink(&self) -> bool { + fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false) + } + /// Converts a [`Box`](Box) into a [`PathBuf`] without copying or /// allocating. #[stable(feature = "into_boxed_path", since = "1.20.0")] diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index 12d52cc8e0..d4bf6aeefe 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -25,8 +25,10 @@ //! //! # Prelude contents //! -//! The current version of the prelude (version 1) lives in -//! [`std::prelude::v1`], and re-exports the following: +//! The first version of the prelude is used in Rust 2015 and Rust 2018, +//! and lives in [`std::prelude::v1`]. +//! [`std::prelude::rust_2015`] and [`std::prelude::rust_2018`] re-export this prelude. +//! It re-exports the following: //! //! * [std::marker]::{[Copy], [Send], [Sized], [Sync], [Unpin]}, //! marker traits that indicate fundamental properties of types. @@ -58,6 +60,12 @@ //! * [std::string]::{[String], [ToString]}, heap-allocated strings. //! * [std::vec]::[Vec], a growable, heap-allocated vector. //! +//! The prelude used in Rust 2021, [`std::prelude::rust_2021`], includes all of the above, +//! and in addition re-exports: +//! +//! * [std::convert]::{[TryFrom], [TryInto]}, +//! * [std::iter]::[FromIterator]. +//! //! [mem::drop]: crate::mem::drop //! [std::borrow]: crate::borrow //! [std::boxed]: crate::boxed @@ -71,10 +79,16 @@ //! [std::ops]: crate::ops //! [std::option]: crate::option //! [`std::prelude::v1`]: v1 +//! [`std::prelude::rust_2015`]: rust_2015 +//! [`std::prelude::rust_2018`]: rust_2018 +//! [`std::prelude::rust_2021`]: rust_2021 //! [std::result]: crate::result //! [std::slice]: crate::slice //! [std::string]: crate::string //! [std::vec]: mod@crate::vec +//! [TryFrom]: crate::convert::TryFrom +//! [TryInto]: crate::convert::TryInto +//! [FromIterator]: crate::iter::FromIterator //! [`to_owned`]: crate::borrow::ToOwned::to_owned //! [book-closures]: ../../book/ch13-01-closures.html //! [book-dtor]: ../../book/ch15-03-drop.html @@ -88,9 +102,9 @@ pub mod v1; /// The 2015 version of the prelude of The Rust Standard Library. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2015", issue = "85684")] +#[stable(feature = "prelude_2015", since = "1.55.0")] pub mod rust_2015 { - #[unstable(feature = "prelude_2015", issue = "85684")] + #[stable(feature = "prelude_2015", since = "1.55.0")] #[doc(no_inline)] pub use super::v1::*; } @@ -98,9 +112,9 @@ pub mod rust_2015 { /// The 2018 version of the prelude of The Rust Standard Library. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2018", issue = "85684")] +#[stable(feature = "prelude_2018", since = "1.55.0")] pub mod rust_2018 { - #[unstable(feature = "prelude_2018", issue = "85684")] + #[stable(feature = "prelude_2018", since = "1.55.0")] #[doc(no_inline)] pub use super::v1::*; } @@ -108,13 +122,13 @@ pub mod rust_2018 { /// The 2021 version of the prelude of The Rust Standard Library. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2021", issue = "85684")] +#[stable(feature = "prelude_2021", since = "1.55.0")] pub mod rust_2021 { - #[unstable(feature = "prelude_2021", issue = "85684")] + #[stable(feature = "prelude_2021", since = "1.55.0")] #[doc(no_inline)] pub use super::v1::*; - #[unstable(feature = "prelude_2021", issue = "85684")] + #[stable(feature = "prelude_2021", since = "1.55.0")] #[doc(no_inline)] pub use core::prelude::rust_2021::*; } diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 4a3c3ba163..772044f014 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -39,12 +39,28 @@ pub use crate::result::Result::{self, Err, Ok}; #[allow(deprecated)] #[doc(no_inline)] pub use core::prelude::v1::{ - asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, - format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax, - module_path, option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord, - PartialEq, PartialOrd, + assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, + format_args_nl, include, include_bytes, include_str, line, llvm_asm, log_syntax, module_path, + option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, + PartialOrd, }; +#[unstable( + feature = "asm", + issue = "72016", + reason = "inline assembly is not stable enough for use and is subject to change" +)] +#[doc(no_inline)] +pub use core::prelude::v1::asm; + +#[unstable( + feature = "global_asm", + issue = "35119", + reason = "`global_asm!` is not stable enough for use and is subject to change" +)] +#[doc(no_inline)] +pub use core::prelude::v1::global_asm; + // FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates // dead links which fail link checker testing. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 8a3e425350..7bc1f5e918 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -277,8 +277,8 @@ mod prim_never {} /// scalar value]', which is similar to, but not the same as, a '[Unicode code /// point]'. /// -/// [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value -/// [Unicode code point]: http://www.unicode.org/glossary/#code_point +/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [Unicode code point]: https://www.unicode.org/glossary/#code_point /// /// This documentation describes a number of methods and trait implementations on the /// `char` type. For technical reasons, there is additional, separate diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 6903ba9056..11a0432ce2 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -452,7 +452,7 @@ impl fmt::Debug for ChildStderr { /// /// let output = if cfg!(target_os = "windows") { /// Command::new("cmd") -/// .args(&["/C", "echo hello"]) +/// .args(["/C", "echo hello"]) /// .output() /// .expect("failed to execute process") /// } else { @@ -609,7 +609,7 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .args(&["-l", "-a"]) + /// .args(["-l", "-a"]) /// .spawn() /// .expect("ls command failed to start"); /// ``` @@ -1568,7 +1568,7 @@ impl ExitStatusError { /// Reports the exit code, if applicable, from an `ExitStatusError`, as a `NonZero` /// - /// This is exaclty like [`code()`](Self::code), except that it returns a `NonZeroI32`. + /// 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. /// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want @@ -1658,8 +1658,7 @@ impl Child { /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] /// error is returned. /// - /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function, - /// especially the [`Other`] kind might change to more specific kinds in the future. + /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function. /// /// This is equivalent to sending a SIGKILL on Unix platforms. /// @@ -1680,7 +1679,6 @@ impl Child { /// /// [`ErrorKind`]: io::ErrorKind /// [`InvalidInput`]: io::ErrorKind::InvalidInput - /// [`Other`]: io::ErrorKind::Other #[stable(feature = "process", since = "1.0.0")] pub fn kill(&mut self) -> io::Result<()> { self.handle.kill() @@ -1900,6 +1898,9 @@ pub fn exit(code: i32) -> ! { /// process, no destructors on the current stack or any other thread's stack /// will be run. /// +/// Rust IO buffers (eg, from `BufWriter`) will not be flushed. +/// Likewise, C stdio buffers will (on most platforms) not be flushed. +/// /// This is in contrast to the default behaviour of [`panic!`] which unwinds /// the current thread's stack and calls all destructors. /// When `panic="abort"` is set, either as an argument to `rustc` or in a @@ -1910,6 +1911,10 @@ pub fn exit(code: i32) -> ! { /// this function at a known point where there are no more destructors left /// to run. /// +/// The process's termination will be similar to that from the C `abort()` +/// function. On Unix, the process will terminate with signal `SIGABRT`, which +/// typically means that the shell prints "Aborted". +/// /// # Examples /// /// ```no_run diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 05e093434b..bc71c15055 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -399,3 +399,12 @@ fn test_command_implements_send_sync() { fn take_send_sync_type(_: T) {} take_send_sync_type(Command::new("")) } + +// Ensure that starting a process with no environment variables works on Windows. +// This will fail if the environment block is ill-formed. +#[test] +#[cfg(windows)] +fn env_empty() { + let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn(); + assert!(p.is_ok()); +} diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 1e19aff51f..72e6c23ee4 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -24,18 +24,32 @@ fn lang_start_internal( main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe), argc: isize, argv: *const *const u8, -) -> isize { - use crate::panic; - use crate::sys_common; - +) -> Result { + use crate::{mem, panic, sys, sys_common}; + let rt_abort = move |e| { + mem::forget(e); + rtabort!("initialization or cleanup bug"); + }; + // Guard against the code called by this function from unwinding outside of the Rust-controlled + // code, which is UB. This is a requirement imposed by a combination of how the + // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking + // mechanism itself. + // + // There are a couple of instances where unwinding can begin. First is inside of the + // `rt::init`, `rt::cleanup` and similar functions controlled by libstd. In those instances a + // panic is a libstd implementation bug. A quite likely one too, as there isn't any way to + // prevent libstd from accidentally introducing a panic to these functions. Another is from + // user code from `main` or, more nefariously, as described in e.g. issue #86030. // SAFETY: Only called once during runtime initialization. - unsafe { sys_common::rt::init(argc, argv) }; - - let exit_code = panic::catch_unwind(main); - - sys_common::rt::cleanup(); - - exit_code.unwrap_or(101) as isize + panic::catch_unwind(move || unsafe { sys_common::rt::init(argc, argv) }).map_err(rt_abort)?; + let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize) + .map_err(move |e| { + mem::forget(e); + rtprintpanic!("drop of the panic payload panicked"); + sys::abort_internal() + }); + panic::catch_unwind(sys_common::rt::cleanup).map_err(rt_abort)?; + ret_code } #[cfg(not(test))] @@ -50,4 +64,5 @@ fn lang_start( argc, argv, ) + .into_ok() } diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index ea1d598d26..b4f4456537 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -105,6 +105,35 @@ //! }); //! rx.recv().unwrap(); //! ``` +//! +//! Unbounded receive loop: +//! +//! ``` +//! use std::sync::mpsc::sync_channel; +//! use std::thread; +//! +//! let (tx, rx) = sync_channel(3); +//! +//! for _ in 0..3 { +//! // It would be the same without thread and clone here +//! // since there will still be one `tx` left. +//! let tx = tx.clone(); +//! // cloned tx dropped within thread +//! thread::spawn(move || tx.send("ok").unwrap()); +//! } +//! +//! // Drop the last sender to stop `rx` waiting for message. +//! // The program will not complete if we comment this out. +//! // **All** `tx` needs to be dropped for `rx` to have `Err`. +//! drop(tx); +//! +//! // Unbounded receiver waiting for all senders to complete. +//! while let Ok(msg) = rx.recv() { +//! println!("{}", msg); +//! } +//! +//! println!("completed"); +//! ``` #![stable(feature = "rust1", since = "1.0.0")] @@ -437,6 +466,9 @@ pub struct IntoIter { /// /// Messages can be sent through this channel with [`send`]. /// +/// Note: all senders (the original and the clones) need to be dropped for the receiver +/// to stop blocking to receive messages with [`Receiver::recv`]. +/// /// [`send`]: Sender::send /// /// # Examples @@ -643,7 +675,7 @@ impl UnsafeFlavor for Receiver { /// the same order as it was sent, and no [`send`] will block the calling thread /// (this channel has an "infinite buffer", unlike [`sync_channel`], which will /// block after its buffer limit is reached). [`recv`] will block until a message -/// is available. +/// is available while there is at least one [`Sender`] alive (including clones). /// /// The [`Sender`] can be cloned to [`send`] to the same channel multiple times, but /// only one [`Receiver`] is supported. @@ -806,6 +838,11 @@ impl Sender { #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Sender { + /// Clone a sender to send to other threads. + /// + /// Note, be aware of the lifetime of the sender because all senders + /// (including the original) need to be dropped in order for + /// [`Receiver::recv`] to stop blocking. fn clone(&self) -> Sender { let packet = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { @@ -1064,9 +1101,10 @@ impl Receiver { /// corresponding channel has hung up. /// /// This function will always block the current thread if there is no data - /// available and it's possible for more data to be sent. Once a message is - /// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this - /// receiver will wake up and return that message. + /// available and it's possible for more data to be sent (at least one sender + /// still exists). Once a message is sent to the corresponding [`Sender`] + /// (or [`SyncSender`]), this receiver will wake up and return that + /// message. /// /// If the corresponding [`Sender`] has disconnected, or it disconnects while /// this call is blocking, this call will wake up and return [`Err`] to @@ -1146,9 +1184,10 @@ impl Receiver { /// corresponding channel has hung up, or if it waits more than `timeout`. /// /// This function will always block the current thread if there is no data - /// available and it's possible for more data to be sent. Once a message is - /// sent to the corresponding [`Sender`] (or [`SyncSender`]), then this - /// receiver will wake up and return that message. + /// available and it's possible for more data to be sent (at least one sender + /// still exists). Once a message is sent to the corresponding [`Sender`] + /// (or [`SyncSender`]), this receiver will wake up and return that + /// message. /// /// If the corresponding [`Sender`] has disconnected, or it disconnects while /// this call is blocking, this call will wake up and return [`Err`] to diff --git a/library/std/src/sync/mpsc/mpsc_queue.rs b/library/std/src/sync/mpsc/mpsc_queue.rs index 42bc639dc2..b93eb056da 100644 --- a/library/std/src/sync/mpsc/mpsc_queue.rs +++ b/library/std/src/sync/mpsc/mpsc_queue.rs @@ -8,8 +8,8 @@ //! method, and see the method for more information about it. Due to this //! caveat, this queue may not be appropriate for all use-cases. -// http://www.1024cores.net/home/lock-free-algorithms -// /queues/non-intrusive-mpsc-node-based-queue +// https://www.1024cores.net/home/lock-free-algorithms +// /queues/non-intrusive-mpsc-node-based-queue #[cfg(all(test, not(target_os = "emscripten")))] mod tests; diff --git a/library/std/src/sync/mpsc/spsc_queue.rs b/library/std/src/sync/mpsc/spsc_queue.rs index 9bf99f193c..7e745eb31d 100644 --- a/library/std/src/sync/mpsc/spsc_queue.rs +++ b/library/std/src/sync/mpsc/spsc_queue.rs @@ -4,7 +4,7 @@ //! concurrently between two threads. This data structure is safe to use and //! enforces the semantics that there is one pusher and one popper. -// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue +// https://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue #[cfg(all(test, not(target_os = "emscripten")))] mod tests; diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index e7c5479ab9..e1d6324c17 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -217,26 +217,6 @@ impl Mutex { data: UnsafeCell::new(t), } } - - /// Immediately drops the guard, and consequently unlocks the mutex. - /// - /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. - /// Alternately, the guard will be automatically dropped when it goes out of scope. - /// - /// ``` - /// #![feature(mutex_unlock)] - /// - /// use std::sync::Mutex; - /// let mutex = Mutex::new(0); - /// - /// let mut guard = mutex.lock().unwrap(); - /// *guard += 20; - /// Mutex::unlock(guard); - /// ``` - #[unstable(feature = "mutex_unlock", issue = "81872")] - pub fn unlock(guard: MutexGuard<'_, T>) { - drop(guard); - } } impl Mutex { @@ -333,6 +313,26 @@ impl Mutex { } } + /// Immediately drops the guard, and consequently unlocks the mutex. + /// + /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. + /// Alternately, the guard will be automatically dropped when it goes out of scope. + /// + /// ``` + /// #![feature(mutex_unlock)] + /// + /// use std::sync::Mutex; + /// let mutex = Mutex::new(0); + /// + /// let mut guard = mutex.lock().unwrap(); + /// *guard += 20; + /// Mutex::unlock(guard); + /// ``` + #[unstable(feature = "mutex_unlock", issue = "81872")] + pub fn unlock(guard: MutexGuard<'_, T>) { + drop(guard); + } + /// Determines whether the mutex is poisoned. /// /// If another thread is active, the mutex can still become poisoned at any diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 0d00f74eaa..e50d62d817 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -23,7 +23,19 @@ use crate::sys_common::rwlock as sys; /// system's implementation, and this type does not guarantee that any /// particular policy will be used. In particular, a writer which is waiting to /// acquire the lock in `write` might or might not block concurrent calls to -/// `read`. +/// `read`, e.g.: +/// +///

This enum has four variants with different types: * `Quit` has no data associated with it at all. -* `Move` includes an anonymous struct inside it. +* `Move` has named fields like a struct does. * `Write` includes a single `String`. * `ChangeColor` includes three `i32` values. @@ -222,8 +222,8 @@ as follows: ```rust enum Option { - Some(T), None, + Some(T), } ``` diff --git a/src/doc/book/src/ch07-01-packages-and-crates.md b/src/doc/book/src/ch07-01-packages-and-crates.md index a24b608f48..7292726128 100644 --- a/src/doc/book/src/ch07-01-packages-and-crates.md +++ b/src/doc/book/src/ch07-01-packages-and-crates.md @@ -8,8 +8,8 @@ Privacy”][modules] section). A *package* is one or more crates that provide a set of functionality. A package contains a *Cargo.toml* file that describes how to build those crates. -Several rules determine what a package can contain. A package *must* contain -zero or one library crates, and no more. It can contain as many binary crates +Several rules determine what a package can contain. A package can contain +at most one library crate. It can contain as many binary crates as you’d like, but it must contain at least one crate (either library or binary). diff --git a/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md index 3e4f1aa69b..dd59ae6061 100644 --- a/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md +++ b/src/doc/book/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md @@ -59,10 +59,11 @@ 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` so we have to specify 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 unclear as to where `add_to_waitlist` is defined. +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 +unclear as to where `add_to_waitlist` is defined. On the other hand, when bringing in structs, enums, and other items with `use`, it’s idiomatic to specify the full path. Listing 7-14 shows the idiomatic way diff --git a/src/doc/book/src/ch08-02-strings.md b/src/doc/book/src/ch08-02-strings.md index 18314e9bbf..9daefa91aa 100644 --- a/src/doc/book/src/ch08-02-strings.md +++ b/src/doc/book/src/ch08-02-strings.md @@ -211,7 +211,8 @@ combining, we can use the `format!` macro: This code also sets `s` to `tic-tac-toe`. The `format!` macro works in the same way as `println!`, but instead of printing the output to the screen, it returns a `String` with the contents. The version of the code using `format!` is much -easier to read and doesn’t take ownership of any of its parameters. +easier to read, and the code generated by the `format!` macro uses references +so that this call doesn’t take ownership of any of its parameters. ### Indexing into Strings diff --git a/src/doc/book/src/ch08-03-hash-maps.md b/src/doc/book/src/ch08-03-hash-maps.md index 12f6b6e320..2708f11790 100644 --- a/src/doc/book/src/ch08-03-hash-maps.md +++ b/src/doc/book/src/ch08-03-hash-maps.md @@ -49,9 +49,9 @@ the [”Processing a Series of Items with Iterators” section of Chapter 13][iterators]. The `collect` method gathers data into a number of collection types, including `HashMap`. For example, if we had the team names and initial scores in two separate vectors, we could use the `zip` method to -create a vector of tuples where “Blue” is paired with 10, and so forth. Then we -could use the `collect` method to turn that vector of tuples into a hash map, -as shown in Listing 8-21. +create an iterator of tuples where “Blue” is paired with 10, and so forth. Then +we could use the `collect` method to turn that iterator of tuples into a hash +map, as shown in Listing 8-21. ```rust {{#rustdoc_include ../listings/ch08-common-collections/listing-08-21/src/main.rs:here}} @@ -207,7 +207,7 @@ loop, so all of these changes are safe and allowed by the borrowing rules. ### Hashing Functions -By default, `HashMap` uses a hashing function called SipHash that can provide +By default, `HashMap` uses a hashing function called SipHash that can provide resistance to Denial of Service (DoS) attacks involving hash tables[^siphash]. This is not the fastest hashing algorithm available, but the trade-off for better security that comes with the drop in performance is worth it. If you profile diff --git a/src/doc/book/src/ch10-02-traits.md b/src/doc/book/src/ch10-02-traits.md index abfc001a10..083b767f59 100644 --- a/src/doc/book/src/ch10-02-traits.md +++ b/src/doc/book/src/ch10-02-traits.md @@ -2,8 +2,8 @@ A *trait* tells the Rust compiler about functionality a particular type has and can share with other types. We can use traits to define shared behavior in an -abstract way. We can use trait bounds to specify that a generic can be any type -that has certain behavior. +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. @@ -404,6 +404,9 @@ reference to a `T` value in the slice. If we change the return type to `&T` instead of `T`, thereby changing the body of the function to return a reference, we wouldn’t need the `Clone` or `Copy` trait bounds and we could avoid heap allocations. Try implementing these alternate solutions on your own! +If you get stuck with errors having to do with lifetimes, keep reading: the +“Validating References with Lifetimes” section coming up will explain, but +lifetimes aren't required to solve these challenges. ### Using Trait Bounds to Conditionally Implement Methods diff --git a/src/doc/book/src/ch11-03-test-organization.md b/src/doc/book/src/ch11-03-test-organization.md index 2110ff14c1..ea4c142426 100644 --- a/src/doc/book/src/ch11-03-test-organization.md +++ b/src/doc/book/src/ch11-03-test-organization.md @@ -66,9 +66,12 @@ Consider the code in Listing 11-12 with the private function `internal_adder`. Listing 11-12: Testing a private function -Note that the `internal_adder` function is not marked as `pub`, but because -tests are just Rust code and the `tests` module is just another module, you can -bring `internal_adder` into a test’s scope and call it. If you don’t think +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”][paths] +section, 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 be tested, there’s nothing in Rust that will compel you to do so. @@ -235,5 +238,6 @@ 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! +[paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html [separating-modules-into-files]: ch07-05-separating-modules-into-different-files.html diff --git a/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md b/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md index d079439c67..bf3e4f1f52 100644 --- a/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md +++ b/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md @@ -48,8 +48,10 @@ yet. 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"`. We assert that the value returned -from the `search` function contains only the line we expect. +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. We aren’t able to run this test and watch it fail because the test doesn’t even compile: the `search` function doesn’t exist yet! So now we’ll add just enough diff --git a/src/doc/book/src/ch12-05-working-with-environment-variables.md b/src/doc/book/src/ch12-05-working-with-environment-variables.md index 86457e8385..6554df4dfa 100644 --- a/src/doc/book/src/ch12-05-working-with-environment-variables.md +++ b/src/doc/book/src/ch12-05-working-with-environment-variables.md @@ -18,7 +18,7 @@ tests, as shown in Listing 12-20. Filename: src/lib.rs -```rust,noplayground +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch12-an-io-project/listing-12-20/src/lib.rs:here}} ``` diff --git a/src/doc/book/src/ch13-04-performance.md b/src/doc/book/src/ch13-04-performance.md index eacb1ba80b..5d09bf2940 100644 --- a/src/doc/book/src/ch13-04-performance.md +++ b/src/doc/book/src/ch13-04-performance.md @@ -1,8 +1,8 @@ ## Comparing Performance: Loops vs. Iterators -To determine whether to use loops or iterators, you need to know which version -of our `search` functions is faster: the version with an explicit `for` loop or -the version with iterators. +To determine whether to use loops or iterators, you need to know which +implementation is faster: the version of the `search` function with an explicit +`for` loop or the version with iterators. We ran a benchmark by loading the entire contents of *The Adventures of Sherlock Holmes* by Sir Arthur Conan Doyle into a `String` and looking for the 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 b9f43fb0bc..4fde74a2ac 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 @@ -177,7 +177,7 @@ function named `mix`, as shown in Listing 14-3: Filename: src/lib.rs ```rust,noplayground,test_harness -{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-03/src/lib.rs}} +{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-03/src/lib.rs:here}} ``` Listing 14-3: An `art` library with items organized into @@ -360,8 +360,7 @@ same way as Rust by using a dual license of `MIT OR Apache-2.0`. This practice demonstrates that you can also specify multiple license identifiers separated by `OR` to have multiple licenses for your project. -With a unique name, the version, the author details that `cargo new` added -when you created the crate, your description, and a license added, the +With a unique name, the version, your description, and a license added, the *Cargo.toml* file for a project that is ready to publish might look like this: Filename: Cargo.toml @@ -370,7 +369,6 @@ when you created the crate, your description, and a license added, the [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] edition = "2018" description = "A fun game where you guess what number the computer has chosen." license = "MIT OR Apache-2.0" diff --git a/src/doc/book/src/ch15-02-deref.md b/src/doc/book/src/ch15-02-deref.md index 9030df02b2..1daa39ddb7 100644 --- a/src/doc/book/src/ch15-02-deref.md +++ b/src/doc/book/src/ch15-02-deref.md @@ -185,7 +185,7 @@ Listing 15-9. and methods. Deref coercion works only on types that implement the `Deref` trait. Deref coercion converts such a type into a reference to another type. For example, deref coercion can convert `&String` to `&str` because `String` -implements the `Deref` trait such that it returns `str`. Deref coercion happens +implements the `Deref` trait such that it returns `&str`. Deref coercion happens automatically when we pass a reference to a particular type’s value as an argument to a function or method that doesn’t match the parameter type in the function or method definition. A sequence of calls to the `deref` method diff --git a/src/doc/book/src/ch15-04-rc.md b/src/doc/book/src/ch15-04-rc.md index fb685bc5e9..6b753b5e41 100644 --- a/src/doc/book/src/ch15-04-rc.md +++ b/src/doc/book/src/ch15-04-rc.md @@ -9,9 +9,9 @@ edges pointing to it. To enable multiple ownership, Rust has a type called `Rc`, which is an abbreviation for *reference counting*. The `Rc` type keeps track of the -number of references to a value which determines whether or not a value is -still in use. If there are zero references to a value, the value can be cleaned -up without any references becoming invalid. +number of references to a value to determine whether or not the value is still +in use. If there are zero references to a value, the value can be cleaned up +without any references becoming invalid. Imagine `Rc` 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 diff --git a/src/doc/book/src/ch17-02-trait-objects.md b/src/doc/book/src/ch17-02-trait-objects.md index 90535ddfa7..4f774fea8c 100644 --- a/src/doc/book/src/ch17-02-trait-objects.md +++ b/src/doc/book/src/ch17-02-trait-objects.md @@ -305,10 +305,12 @@ We would get this error: ``` This error means you can’t use this trait as a trait object in this way. If -you’re interested in more details on object safety, see [Rust RFC 255]. +you’re interested in more details on object safety, see [Rust RFC 255] or check the +object safety section in the [Rust Reference][object-safety-reference]. [Rust RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md [performance-of-code-using-generics]: ch10-01-syntax.html#performance-of-code-using-generics [dynamically-sized]: ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait +[object-safety-reference]: ../reference/items/traits.html#object-safety diff --git a/src/doc/book/src/ch19-01-unsafe-rust.md b/src/doc/book/src/ch19-01-unsafe-rust.md index 5dc2f81cee..4eb5f3af98 100644 --- a/src/doc/book/src/ch19-01-unsafe-rust.md +++ b/src/doc/book/src/ch19-01-unsafe-rust.md @@ -125,7 +125,7 @@ Recall that we can create raw pointers in safe code, but we can’t *dereference raw pointers and read the data being pointed to. In Listing 19-3, we use the dereference operator `*` on a raw pointer that requires an `unsafe` block. -```rust,unsafe +```rust {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-03/src/main.rs:here}} ``` @@ -166,7 +166,7 @@ responsibility for upholding the function’s contracts. Here is an unsafe function named `dangerous` that doesn’t do anything in its body: -```rust,unsafe +```rust {{#rustdoc_include ../listings/ch19-advanced-features/no-listing-01-unsafe-fn/src/main.rs:here}} ``` @@ -240,7 +240,7 @@ know code is okay, but Rust doesn’t, it’s time to reach for unsafe code. Listing 19-6 shows how to use an `unsafe` block, a raw pointer, and some calls to unsafe functions to make the implementation of `split_at_mut` work. -```rust,unsafe +```rust {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-06/src/main.rs:here}} ``` @@ -282,7 +282,7 @@ In contrast, the use of `slice::from_raw_parts_mut` in Listing 19-7 would likely crash when the slice is used. This code takes an arbitrary memory location and creates a slice 10,000 items long. -```rust,unsafe +```rust {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-07/src/main.rs:here}} ``` @@ -309,7 +309,7 @@ responsibility falls on the programmer to ensure safety. Filename: src/main.rs -```rust,unsafe +```rust {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-08/src/main.rs}} ``` @@ -370,11 +370,10 @@ Static variables are similar to constants, which we discussed in the [“Differences Between Variables and Constants”][differences-between-variables-and-constants] section in Chapter 3. The names of static variables are in -`SCREAMING_SNAKE_CASE` by convention, and we *must* annotate the variable’s -type, which is `&'static str` in this example. Static variables can only store +`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; we don’t need to annotate it explicitly. Accessing an -immutable static variable is safe. +figure out the lifetime and we aren’t required to annotate it explicitly. +Accessing an immutable static variable is safe. Constants and immutable static variables might seem similar, but a subtle difference is that values in a static variable have a fixed address in memory. @@ -388,7 +387,7 @@ static variable named `COUNTER`. Filename: src/main.rs -```rust,unsafe +```rust {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-10/src/main.rs}} ``` @@ -415,7 +414,7 @@ can’t verify. We can declare that a trait is `unsafe` by adding the `unsafe` keyword before `trait` and marking the implementation of the trait as `unsafe` too, as shown in Listing 19-11. -```rust,unsafe +```rust {{#rustdoc_include ../listings/ch19-advanced-features/listing-19-11/src/main.rs}} ``` diff --git a/src/doc/book/src/ch19-03-advanced-traits.md b/src/doc/book/src/ch19-03-advanced-traits.md index 1d396463ec..79b2e42d90 100644 --- a/src/doc/book/src/ch19-03-advanced-traits.md +++ b/src/doc/book/src/ch19-03-advanced-traits.md @@ -137,9 +137,12 @@ the `Add` trait where we want to customize the `Rhs` type rather than using the default. We have two structs, `Millimeters` and `Meters`, holding values in different -units. 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. +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”][newtype] 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. Filename: src/lib.rs @@ -451,6 +454,7 @@ Now you know how the newtype pattern is used in relation to traits; it’s also useful pattern even when traits are not involved. Let’s switch focus and look at some advanced ways to interact with Rust’s type system. +[newtype]: ch19-04-advanced-types.html#using-the-newtype-pattern-for-type-safety-and-abstraction [implementing-a-trait-on-a-type]: ch10-02-traits.html#implementing-a-trait-on-a-type [the-iterator-trait-and-the-next-method]: diff --git a/src/doc/book/src/ch19-04-advanced-types.md b/src/doc/book/src/ch19-04-advanced-types.md index a4b1d1d3c2..bfc77c9e48 100644 --- a/src/doc/book/src/ch19-04-advanced-types.md +++ b/src/doc/book/src/ch19-04-advanced-types.md @@ -6,12 +6,12 @@ examine why newtypes are useful as types. Then we’ll move on to type aliases, feature similar to newtypes but with slightly different semantics. We’ll also discuss the `!` type and dynamically sized types. -> Note: The next section assumes you’ve read the earlier section [“Using the +### 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.”][using-the-newtype-pattern] -### Using the Newtype Pattern for Type Safety and Abstraction - The newtype pattern is 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 @@ -274,8 +274,9 @@ restriction: {{#rustdoc_include ../listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/src/lib.rs}} ``` -A trait bound on `?Sized` is the opposite of a trait bound on `Sized`: we would -read this as “`T` may or may not be `Sized`.” This syntax is only available for +A trait bound on `?Sized` means “`T` may or may not be `Sized`” and this +notation overrides the default that generic types must have a known size at +compile time. The `?Trait` syntax with this meaning is only available for `Sized`, not any other traits. Also note that we switched the type of the `t` parameter from `T` to `&T`. diff --git a/src/doc/book/src/ch19-06-macros.md b/src/doc/book/src/ch19-06-macros.md index a714413b6f..fe2605fd81 100644 --- a/src/doc/book/src/ch19-06-macros.md +++ b/src/doc/book/src/ch19-06-macros.md @@ -151,9 +151,9 @@ effectively deprecated. With this in mind, as well as the fact that most Rust programmers will *use* macros more than *write* macros, we won’t discuss `macro_rules!` any further. To learn more about how to write macros, consult the online documentation or other resources, such as [“The Little Book of Rust -Macros”][tlborm]. +Macros”][tlborm] started by Daniel Keep and continued by Lukas Wirth. -[tlborm]: https://danielkeep.github.io/tlborm/book/index.html +[tlborm]: https://veykril.github.io/tlborm/ ### Procedural Macros for Generating Code from Attributes diff --git a/src/doc/book/src/ch20-02-multithreaded.md b/src/doc/book/src/ch20-02-multithreaded.md index 24c7206979..244f8e53fb 100644 --- a/src/doc/book/src/ch20-02-multithreaded.md +++ b/src/doc/book/src/ch20-02-multithreaded.md @@ -226,8 +226,9 @@ shows us the following: ```rust,ignore pub fn spawn(f: F) -> JoinHandle where - F: FnOnce() -> T + Send + 'static, - T: Send + 'static + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, ``` The `F` type parameter is the one we’re concerned with here; the `T` type @@ -321,8 +322,9 @@ the `thread::spawn` signature: ```rust,ignore pub fn spawn(f: F) -> JoinHandle where - F: FnOnce() -> T + Send + 'static, - T: Send + 'static + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, ``` The `spawn` function returns a `JoinHandle`, where `T` is the type that the diff --git a/src/doc/book/src/img/ferris/unsafe.svg b/src/doc/book/src/img/ferris/unsafe.svg deleted file mode 100644 index d4fdc08dd6..0000000000 --- a/src/doc/book/src/img/ferris/unsafe.svg +++ /dev/null @@ -1,291 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/doc/book/tools/src/bin/convert_quotes.rs b/src/doc/book/tools/src/bin/convert_quotes.rs index e548c5e075..c8cfd456d1 100644 --- a/src/doc/book/tools/src/bin/convert_quotes.rs +++ b/src/doc/book/tools/src/bin/convert_quotes.rs @@ -8,7 +8,7 @@ fn main() { let mut buffer = String::new(); if let Err(e) = io::stdin().read_to_string(&mut buffer) { - panic!(e); + panic!("{}", e); } for line in buffer.lines() { diff --git a/src/doc/book/tools/src/bin/link2print.rs b/src/doc/book/tools/src/bin/link2print.rs index 33d90ec240..9688d10bf5 100644 --- a/src/doc/book/tools/src/bin/link2print.rs +++ b/src/doc/book/tools/src/bin/link2print.rs @@ -14,7 +14,7 @@ fn read_md() -> String { let mut buffer = String::new(); match io::stdin().read_to_string(&mut buffer) { Ok(_) => buffer, - Err(error) => panic!(error), + Err(error) => panic!("{}", error), } } @@ -27,14 +27,18 @@ fn parse_references(buffer: String) -> (String, HashMap) { // FIXME: currently doesn't handle "title" in following line. let re = Regex::new(r###"(?m)\n?^ {0,3}\[([^]]+)\]:[[:blank:]]*(.*)$"###) .unwrap(); - let output = re.replace_all(&buffer, |caps: &Captures<'_>| { - let key = caps.get(1).unwrap().as_str().to_uppercase(); - let val = caps.get(2).unwrap().as_str().to_string(); - if ref_map.insert(key, val).is_some() { - panic!("Did not expect markdown page to have duplicate reference"); - } - "".to_string() - }).to_string(); + let output = re + .replace_all(&buffer, |caps: &Captures<'_>| { + let key = caps.get(1).unwrap().as_str().to_uppercase(); + let val = caps.get(2).unwrap().as_str().to_string(); + if ref_map.insert(key, val).is_some() { + panic!( + "Did not expect markdown page to have duplicate reference" + ); + } + "".to_string() + }) + .to_string(); (output, ref_map) } @@ -196,8 +200,7 @@ more text" #[test] fn parses_name_with_utf8() { let source = r###"[user’s forum](the user’s forum)"###.to_string(); - let target = - r###"user’s forum at *the user’s forum*"###.to_string(); + let target = r###"user’s forum at *the user’s forum*"###.to_string(); assert_eq!(parse(source), target); } @@ -251,7 +254,6 @@ more text" [package] name = "hello_cargo" version = "0.1.0" -authors = ["Your Name "] [dependencies] ``` @@ -284,7 +286,6 @@ is still here` link at *ref*" [package] name = "hello_cargo" version = "0.1.0" -authors = ["Your Name "] [dependencies] ``` @@ -297,7 +298,6 @@ more text [package] name = "hello_cargo" version = "0.1.0" -authors = ["Your Name "] [dependencies] ``` diff --git a/src/doc/book/tools/src/bin/remove_hidden_lines.rs b/src/doc/book/tools/src/bin/remove_hidden_lines.rs index fa3b705210..45ce031aa3 100644 --- a/src/doc/book/tools/src/bin/remove_hidden_lines.rs +++ b/src/doc/book/tools/src/bin/remove_hidden_lines.rs @@ -9,7 +9,7 @@ fn read_md() -> String { let mut buffer = String::new(); match io::stdin().read_to_string(&mut buffer) { Ok(_) => buffer, - Err(error) => panic!(error), + Err(error) => panic!("{}", error), } } diff --git a/src/doc/book/tools/src/bin/remove_links.rs b/src/doc/book/tools/src/bin/remove_links.rs index a096389b83..edccc53c1a 100644 --- a/src/doc/book/tools/src/bin/remove_links.rs +++ b/src/doc/book/tools/src/bin/remove_links.rs @@ -8,7 +8,7 @@ use std::io::{Read, Write}; fn main() { let mut buffer = String::new(); if let Err(e) = io::stdin().read_to_string(&mut buffer) { - panic!(e); + panic!("{}", e); } let mut refs = HashSet::new(); diff --git a/src/doc/book/tools/src/bin/remove_markup.rs b/src/doc/book/tools/src/bin/remove_markup.rs index 8877e038f7..06f6a6ba98 100644 --- a/src/doc/book/tools/src/bin/remove_markup.rs +++ b/src/doc/book/tools/src/bin/remove_markup.rs @@ -12,7 +12,7 @@ fn read_md() -> String { let mut buffer = String::new(); match io::stdin().read_to_string(&mut buffer) { Ok(_) => buffer, - Err(error) => panic!(error), + Err(error) => panic!("{}", error), } } @@ -39,9 +39,11 @@ fn remove_markup(input: String) -> String { } else { let result = regexen.iter().fold(line.to_string(), |result, regex| { - regex.replace_all(&result, |caps: &Captures<'_>| { - caps.get(1).unwrap().as_str().to_string() - }).to_string() + regex + .replace_all(&result, |caps: &Captures<'_>| { + caps.get(1).unwrap().as_str().to_string() + }) + .to_string() }); Some(result) } diff --git a/src/doc/edition-guide/src/SUMMARY.md b/src/doc/edition-guide/src/SUMMARY.md index 2eae013202..6804ac2d68 100644 --- a/src/doc/edition-guide/src/SUMMARY.md +++ b/src/doc/edition-guide/src/SUMMARY.md @@ -7,6 +7,7 @@ - [What are editions?](editions/index.md) - [Creating a new project](editions/creating-a-new-project.md) - [Transitioning an existing project to a new edition](editions/transitioning-an-existing-project-to-a-new-edition.md) + - [Advanced migrations](editions/advanced-migrations.md) ## Rust 2015 diff --git a/src/doc/edition-guide/src/editions/advanced-migrations.md b/src/doc/edition-guide/src/editions/advanced-migrations.md new file mode 100644 index 0000000000..b804ae6441 --- /dev/null +++ b/src/doc/edition-guide/src/editions/advanced-migrations.md @@ -0,0 +1,210 @@ +# Advanced migration strategies + +## How migrations work + +[`cargo fix --edition`][`cargo fix`] works by running the equivalent of [`cargo check`] on your project with special [lints] enabled which will detect code that may not compile in the next edition. +These lints include instructions on how to modify the code to make it compatible on both the current and the next edition. +`cargo fix` applies these changes to the source code, and then runs `cargo check` again to verify that the fixes work. +If the fixes fail, then it will back out the changes and display a warning. + +Changing the code to be simultaneously compatible with both the current and next edition makes it easier to incrementally migrate the code. +If the automated migration does not completely succeed, or requires manual help, you can iterate while staying on the original edition before changing `Cargo.toml` to use the next edition. + +The lints that `cargo fix --edition` apply are part of a [lint group]. +For example, when migrating from 2018 to 2021, Cargo uses the `rust-2021-compatibility` group of lints to fix the code. +Check the [Partial migration](#partial-migration-with-broken-code) section below for tips on using individual lints to help with migration. + +`cargo fix` may run `cargo check` multiple times. +For example, after applying one set of fixes, this may trigger new warnings which require further fixes. +Cargo repeats this until no new warnings are generated. + +## Migrating multiple configurations + +`cargo fix` can only work with a single configuration at a time. +If you use [Cargo features] or [conditional compilation], then you may need to run `cargo fix` multiple times with different flags. + +For example, if you have code that uses `#[cfg]` attributes to include different code for different platforms, you may need to run `cargo fix` with the `--target` option to fix for different targets. +This may require moving your code between machines if you don't have cross-compiling available. + +Similarly, if you have conditions on Cargo features, like `#[cfg(feature = "my-optional-thing")]`, it is recommended to use the `--all-features` flag to allow `cargo fix` to migrate all the code behind those feature gates. +If you want to migrate feature code individually, you can use the `--features` flag to migrate one at a time. + +## Migrating a large project or workspace + +You can migrate a large project incrementally to make the process easier if you run into problems. + +In a [Cargo workspace], each package defines its own edition, so the process naturally involves migrating one package at a time. + +Within a [Cargo package], you can either migrate the entire package at once, or migrate individual [Cargo targets] one at a time. +For example, if you have multiple binaries, tests, and examples, you can use specific target selection flags with `cargo fix --edition` to migrate just that one target. +By default, `cargo fix` uses `--all-targets`. + +For even more advanced cases, you can specify the edition for each individual target in `Cargo.toml` like this: + +```toml +[[bin]] +name = "my-binary" +edition = "2018" +``` + +This usually should not be required, but is an option if you have a lot of targets and are having difficulty migrating them all together. + +## Partial migration with broken code + +Sometimes the fixes suggested by the compiler may fail to work. +When this happens, Cargo will report a warning indicating what happened and what the error was. +However, by default it will automatically back out the changes it made. +It can be helpful to keep the code in the broken state and manually resolve the issue. +Some of the fixes may have been correct, and the broken fix maybe be *mostly* correct, but just need minor tweaking. + +In this situation, use the `--broken-code` option with `cargo fix` to tell Cargo not to back out the changes. +Then, you can go manually inspect the error and investigate what is needed to fix it. + +Another option to incrementally migrate a project is to apply individual fixes separately, one at a time. +You can do this by adding the individual lints as warnings, and then either running `cargo fix` (without the `--edition` flag) or using your editor or IDE to apply its suggestions if it supports "Quick Fixes". + +For example, the 2018 edition uses the [`keyword-idents`] lint to fix any conflicting keywords. +You can add `#![warn(keyword_idents)]` to the top of each crate (like at the top of `src/lib.rs` or `src/main.rs`). +Then, running `cargo fix` will apply just the suggestions for that lint. + +You can see the list of lints enabled for each edition in the [lint group] page, or run the `rustc -Whelp` command. + +## Migrating macros + +Some macros may require manual work to fix them for the next edition. +For example, `cargo fix --edition` may not be able to automatically fix a macro that generates syntax that does not work in the next edition. + +This may be a problem for both [proc macros] and `macro_rules`-style macros. +`macro_rules` macros can sometimes be automatically updated if the macro is used within the same crate, but there are several situations where it cannot. +Proc macros in general cannot be automatically fixed at all. + +For example, if we migrate a crate containing this (contrived) macro `foo` from 2015 to 2018, `foo` would not be automatically fixed. + +```rust +#[macro_export] +macro_rules! foo { + () => { + let dyn = 1; + println!("it is {}", dyn); + }; +} +``` + +When this macro is defined in a 2015 crate, it can be used from a crate of any other edition due to macro hygiene (discussed below). +In 2015, `dyn` is a normal identifier and can be used without restriction. + +However, in 2018, `dyn` is no longer a valid identifier. +When using `cargo fix --edition` to migrate to 2018, Cargo won't display any warnings or errors at all. +However, `foo` won't work when called from any crate. + +If you have macros, you are encouraged to make sure you have tests that fully cover the macro's syntax. +You may also want to test the macros by importing and using them in crates from multiple editions, just to ensure it works correctly everywhere. +If you run into issues, you'll need to read through the chapters of this guide to understand how the code can be changed to work across all editions. + +### Macro hygiene + +Macros use a system called "edition hygiene" where the tokens within a macro are marked with which edition they come from. +This allows external macros to be called from crates of varying editions without needing to worry about which edition it is called from. + +Let's take a closer look at the example above that defines a `macro_rules` macro using `dyn` as an identifier. +If that macro was defined in a crate using the 2015 edition, then that macro works fine, even if it were called from a 2018 crate where `dyn` is a keyword and that would normally be a syntax error. +The `let dyn = 1;` tokens are marked as being from 2015, and the compiler will remember that wherever that code gets expanded. +The parser looks at the edition of the tokens to know how to interpret it. + +The problem arises when changing the edition to 2018 in the crate where it is defined. +Now, those tokens are tagged with the 2018 edition, and those will fail to parse. +However, since we never called the macro from our crate, `cargo fix --edition` never had a chance to inspect the macro and fix it. + + + +## Documentation tests + +At this time, `cargo fix` is not able to update [documentation tests]. +After updating the edition in `Cargo.toml`, you should run `cargo test` to ensure everything still passes. +If your documentation tests use syntax that is not supported in the new edition, you will need to update them manually. + +In rare cases, you can manually set the edition for each test. +For example, you can use the [`edition2018` annotation][rustdoc-annotation] on the triple backticks to tell `rustdoc` which edition to use. + +## Generated code + +Another area where the automated fixes cannot apply is if you have a build script which generates Rust code at compile time (see [Code generation] for an example). +In this situation, if you end up with code that doesn't work in the next edition, you will need to manually change the build script to generate code that is compatible. + +## Migrating non-Cargo projects + +If your project is not using Cargo as a build system, it may still be possible to make use of the automated lints to assist migrating to the next edition. +You can enable the migration lints as described above by enabling the appropriate [lint group]. +For example, you can use the `#![warn(rust_2021_compatibility)]` attribute or the `-Wrust-2021-compatibility` or `--force-warns=rust-2021-compatibility` [CLI flag]. + +The next step is to apply those lints to your code. +There are several options here: + +* Manually read the warnings and apply the suggestions recommended by the compiler. +* Use an editor or IDE that supports automatically applying suggestions. + For example, [Visual Studio Code] with the [Rust Analyzer extension] has the ability to use the "Quick Fix" links to automatically apply suggestions. + Many other editors and IDEs have similar functionality. +* Write a migration tool using the [`rustfix`] library. + This is the library that Cargo uses internally to take the [JSON messages] from the compiler and modify the source code. + Check the [`examples` directory][rustfix-examples] for examples of how to use the library. + +## Writing idiomatic code in a new edition + +Editions are not only about new features and removing old ones. +In any programming language, idioms change over time, and Rust is no exception. +While old code will continue to compile, it might be written with different idioms today. + +For example, in Rust 2015, external crates must be listed with `extern crate` like this: + +```rust,ignore +// src/lib.rs +extern crate rand; +``` + +In Rust 2018, it is [no longer necessary](../rust-2018/path-changes.md#no-more-extern-crate) to include these items. + +`cargo fix` has the `--edition-idioms` option to automatically transition some of these idioms to the new syntax. + +> **Warning**: The current *"idiom lints"* are known to have some problems. +> They may make incorrect suggestions which may fail to compile. +> The current lints are: +> * Edition 2018: +> * [`unused-extern-crates`] +> * [`explicit-outlives-requirements`] +> * Edition 2021 does not have any idiom lints. +> +> The following instructions are recommended only for the intrepid who are willing to work through a few compiler/Cargo bugs! +> If you run into problems, you can try the `--broken-code` option [described above](#partial-migration-with-broken-code) to make as much progress as possible, and then resolve the remaining issues manually. + +With that out of the way, we can instruct Cargo to fix our code snippet with: + +```console +cargo fix --edition-idioms +``` + +Afterwards, the line with `extern crate rand;` in `src/lib.rs` will be removed. + +We're now more idiomatic, and we didn't have to fix our code manually! + +[`cargo check`]: ../../cargo/commands/cargo-check.html +[`cargo fix`]: ../../cargo/commands/cargo-fix.html +[`explicit-outlives-requirements`]: ../../rustc/lints/listing/allowed-by-default.html#explicit-outlives-requirements +[`keyword-idents`]: ../../rustc/lints/listing/allowed-by-default.html#keyword-idents +[`rustfix`]: https://github.com/rust-lang/rustfix +[`unused-extern-crates`]: ../../rustc/lints/listing/allowed-by-default.html#unused-extern-crates +[Cargo features]: ../../cargo/reference/features.html +[Cargo package]: ../../cargo/reference/manifest.html#the-package-section +[Cargo targets]: ../../cargo/reference/cargo-targets.html +[Cargo workspace]: ../../cargo/reference/workspaces.html +[CLI flag]: ../../rustc/lints/levels.html#via-compiler-flag +[Code generation]: ../../cargo/reference/build-script-examples.html#code-generation +[conditional compilation]: ../../reference/conditional-compilation.html +[documentation tests]: ../../rustdoc/documentation-tests.html +[JSON messages]: ../../rustc/json.html +[lint group]: ../../rustc/lints/groups.html +[lints]: ../../rustc/lints/index.html +[proc macros]: ../../reference/procedural-macros.html +[Rust Analyzer extension]: https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer +[rustdoc-annotation]: ../../rustdoc/documentation-tests.html#attributes +[rustfix-examples]: https://github.com/rust-lang/rustfix/tree/master/examples +[Visual Studio Code]: https://code.visualstudio.com/ diff --git a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md index beb2360435..6732837e82 100644 --- a/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md +++ b/src/doc/edition-guide/src/editions/transitioning-an-existing-project-to-a-new-edition.md @@ -1,37 +1,54 @@ # Transitioning an existing project to a new edition -New editions might change the way you write Rust – they add new syntax, -language, and library features, and also remove features. For example, `try`, -`async`, and `await` are keywords in Rust 2018, but not Rust 2015. If you -have a project that's using Rust 2015, and you'd like to use Rust 2018 for it -instead, there's a few steps that you need to take. +Rust includes tooling to automatically transition a project from one edition to the next. +It will update your source code so that it is compatible with the next edition. +Briefly, the steps to update to the next edition are: + +1. Run `cargo fix --edition` +2. Edit `Cargo.toml` and set the `edition` field to the next edition, for example `edition = "2021"` +3. Run `cargo build` or `cargo test` to verify the fixes worked. + + +> If you are migrating from 2018 to 2021, the steps are slightly different because 2021 is not yet stabilized, and is only available on the [nightly channel]. +> The steps to follow are: +> +> 1. Install the most recent nightly: `rustup update nightly`. +> 2. Run `cargo +nightly fix --edition`. +> 3. Edit `Cargo.toml` and place `cargo-features = ["edition2021"]` at the top (above `[package]`), and change the edition field to say `edition = "2021"`. +> 4. Run `cargo +nightly check` to verify it now works in the new edition. + +The following sections dig into the details of these steps, and some of the issues you may encounter along the way. > It's our intention that the migration to new editions is as smooth an > experience as possible. If it's difficult for you to upgrade to the latest edition, > we consider that a bug. If you run into problems with this process, please -> [file a bug](https://github.com/rust-lang/rust/issues/new). Thank you! +> [file a bug](https://github.com/rust-lang/rust/issues/new/choose). Thank you! + +## Starting the migration + +As an example, let's take a look at transitioning from the 2015 edition to the 2018 edition. +The steps are essentially the same when transitioning to other editions like 2021. -Here's an example. Imagine we have a crate that has this code in -`src/lib.rs`: +Imagine we have a crate that has this code in `src/lib.rs`: ```rust trait Foo { - fn foo(&self, Box); + fn foo(&self, i32); } ``` -This code uses an anonymous parameter, that `Box`. This is [not +This code uses an anonymous parameter, that `i32`. This is [not supported in Rust 2018](../rust-2018/trait-system/no-anon-params.md), and so this would fail to compile. Let's get this code up to date! ## Updating your code to be compatible with the new edition -Your code may or may not use features that are incompatible with the new -edition. In order to help transition to Rust 2018, we've included a new -subcommand with Cargo. To start, let's run it: +Your code may or may not use features that are incompatible with the new edition. +In order to help transition to the next edition, Cargo includes the [`cargo fix`] subcommand to automatically update your source code. +To start, let's run it: ```console -> cargo fix --edition +cargo fix --edition ``` This will check your code, and automatically fix any issues that it can. @@ -39,106 +56,43 @@ Let's look at `src/lib.rs` again: ```rust trait Foo { - fn foo(&self, _: Box); + fn foo(&self, _: i32); } ``` -It's re-written our code to introduce a parameter name for that trait object. +It's re-written our code to introduce a parameter name for that `i32` value. In this case, since it had no name, `cargo fix` will replace it with `_`, which is conventional for unused variables. `cargo fix` can't always fix your code automatically. If `cargo fix` can't fix something, it will print the warning that it cannot fix -to the console. If you see one of these warnings, you'll have to update your code -manually. See the corresponding section of this guide for help, and if you have -problems, please seek help at the [user's forums](https://users.rust-lang.org/). - -Keep running `cargo fix --edition` until you have no more warnings. - -Congrats! Your code is now valid in both Rust 2015 and Rust 2018! +to the console. If you see one of these warnings, you'll have to update your code manually. +See the [Advanced migration strategies] chapter for more on working with the migration process, and read the chapters in this guide which explain which changes are needed. +If you have problems, please seek help at the [user's forums](https://users.rust-lang.org/). ## Enabling the new edition to use new features In order to use some new features, you must explicitly opt in to the new -edition. Once you're ready to commit, change your `Cargo.toml` to add the new +edition. Once you're ready to continue, change your `Cargo.toml` to add the new `edition` key/value pair. For example: ```toml [package] name = "foo" version = "0.1.0" -authors = ["Your Name "] edition = "2018" ``` If there's no `edition` key, Cargo will default to Rust 2015. But in this case, -we've chosen `2018`, and so our code is compiling with Rust 2018! - -## Writing idiomatic code in a new edition - -Editions are not only about new features and removing old ones. In any programming -language, idioms change over time, and Rust is no exception. While old code -will continue to compile, it might be written with different idioms today. - -Our sample code contains an outdated idiom. Here it is again: - -```rust -trait Foo { - fn foo(&self, _: Box); -} -``` - -In Rust 2018, it's considered idiomatic to use the [`dyn` -keyword](../rust-2018/trait-system/dyn-trait-for-trait-objects.md) for -trait objects. - -Eventually, we want `cargo fix` to fix all these idioms automatically in the same -manner we did for upgrading to the 2018 edition. **Currently, -though, the *"idiom lints"* are not ready for widespread automatic fixing.** The -compiler isn't making `cargo fix`-compatible suggestions in many cases right -now, and it is making incorrect suggestions in others. Enabling the idiom lints, -even with `cargo fix`, is likely to leave your crate either broken or with many -warnings still remaining. +we've chosen `2018`, and so our code will compile with Rust 2018! -We have plans to make these idiom migrations a seamless part of the Rust 2018 -experience, but we're not there yet. As a result the following instructions are -recommended only for the intrepid who are willing to work through a few -compiler/Cargo bugs! +The next step is to test your project on the new edition. +Run your project tests to verify that everything still works, such as running [`cargo test`]. +If new warnings are issued, you may want to consider running `cargo fix` again (without the `--edition` flag) to apply any suggestions given by the compiler. -With that out of the way, we can instruct Cargo to fix our code snippet with: - -```console -$ cargo fix --edition-idioms -``` - -Afterwards, `src/lib.rs` looks like this: - -```rust -trait Foo { - fn foo(&self, _: Box); -} -``` - -We're now more idiomatic, and we didn't have to fix our code manually! - -Note that `cargo fix` may still not be able to automatically update our code. -If `cargo fix` can't fix something, it will print a warning to the console, and -you'll have to fix it manually. - -As mentioned before, there are known bugs around the idiom lints which -means they're not all ready for prime time yet. You may get a scary-looking -warning to report a bug to Cargo, which happens whenever a fix proposed by -`rustc` actually caused code to stop compiling by accident. If you'd like `cargo -fix` to make as much progress as possible, even if it causes code to stop -compiling, you can execute: - -```console -$ cargo fix --edition-idioms --broken-code -``` - -This will instruct `cargo fix` to apply automatic suggestions regardless of -whether they work or not. Like usual, you'll see the compilation result after -all fixes are applied. If you notice anything wrong or unusual, please feel free -to report an issue to Cargo and we'll help prioritize and fix it. +Congrats! Your code is now valid in both Rust 2015 and Rust 2018! -Enjoy the new edition! +[`cargo fix`]: ../../cargo/commands/cargo-fix.html +[`cargo test`]: ../../cargo/commands/cargo-test.html +[Advanced migration strategies]: advanced-migrations.md +[nightly channel]: ../../book/appendix-07-nightly-rust.html diff --git a/src/doc/edition-guide/src/rust-2021/IntoIterator-for-arrays.md b/src/doc/edition-guide/src/rust-2021/IntoIterator-for-arrays.md index e26e7fbfeb..acdb2282dd 100644 --- a/src/doc/edition-guide/src/rust-2021/IntoIterator-for-arrays.md +++ b/src/doc/edition-guide/src/rust-2021/IntoIterator-for-arrays.md @@ -2,6 +2,12 @@ ## Summary +- Arrays implement `IntoIterator` in *all* editions. +- Calls to `IntoIterator::into_iter` are *hidden* in Rust 2015 and Rust 2018 when using method call syntax + (i.e., `array.into_iter()`). So, `array.into_iter()` still resolves to `(&array).into_iter()` as it + has before. +- `array.into_iter()` changes meaning to be the call to `IntoIterator::into_inter` in Rust 2021. + ## Details Until Rust 1.53, only *references* to arrays implement `IntoIterator`. @@ -20,8 +26,7 @@ Just [adding the trait implementation][20] would break existing code. `(&array).into_iter()` due to [how method call syntax works][22]. Adding the trait implementation would change the meaning. -Usually we categorize this type of breakage -(adding a trait implementation) 'minor' and acceptable. +Usually this type of breakage (adding a trait implementation) is categorized as 'minor' and acceptable. But in this case there is too much code that would be broken by it. It has been suggested many times to "only implement `IntoIterator` for arrays in Rust 2021". @@ -29,8 +34,8 @@ However, this is simply not possible. You can't have a trait implementation exist in one edition and not in another, since editions can be mixed. -Instead, we decided to add the trait implementation in *all* editions (starting in Rust 1.53.0), -but add a small hack to avoid breakage until Rust 2021. +Instead, the trait implementation was added in *all* editions (starting in Rust 1.53.0) +but with a small hack to avoid breakage until Rust 2021. In Rust 2015 and 2018 code, the compiler will still resolve `array.into_iter()` to `(&array).into_iter()` like before, as if the trait implementation does not exist. This *only* applies to the `.into_iter()` method call syntax. @@ -39,11 +44,55 @@ It does not affect any other syntax such as `for e in [1, 2, 3]`, `iter.zip([1, Those will start to work in *all* editions. While it's a shame that this required a small hack to avoid breakage, -we're very happy with how this solution keeps the difference between -the editions to an absolute minimum. -Since the hack is only present in the older editions, -there is no added complexity in the new edition. +this solution keeps the difference between the editions to an absolute minimum. [25]: https://github.com/rust-lang/rust/issues/25725 [20]: https://github.com/rust-lang/rust/pull/65819 -[22]: https://doc.rust-lang.org/book/ch05-03-method-syntax.html#wheres-the---operator \ No newline at end of file +[22]: https://doc.rust-lang.org/book/ch05-03-method-syntax.html#wheres-the---operator + +## Migration + +A lint, `array_into_iter`, gets triggered whenever there is some call to `into_iter()` that will change +meaning in Rust 2021. The `array_into_iter` lint has already been a warning by default on all editions +since the 1.41 release (with several enhancements made in 1.55). If your code is already warning free, +then it should already be ready to go for Rust 2021! + +You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by +running: + +```sh +cargo fix --edition +``` + +Because the difference between editions is small, the migration to Rust 2021 is fairly straight-forward. + +For method calls of `into_iter` on arrays, the elements being implemented will change from references to owned values. + +For example: + +```rust +fn main() { + let array = [1u8, 2, 3]; + for x in array.into_iter() { + // x is a `&u8` in Rust 2015 and Rust 2018 + // x is a `u8` in Rust 2021 + } +} +``` + +The most straightforward way to migrate in Rust 2021, is by keeping the exact behavior from previous editions +by calling `iter()` which also iterates over owned arrays by reference: + +```rust +fn main() { + let array = [1u8, 2, 3]; + for x in array.iter() { // <- This line changed + // x is a `&u8` in all editions + } +} +``` + +### Optional migration + +If you are using fully qualified method syntax (i.e., `IntoIterator::into_iter(array)`) in a previous edition, +this can be upgraded to method call syntax (i.e., `array.into_iter()`). \ No newline at end of file diff --git a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md index a798b873fd..aae3f39897 100644 --- a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +++ b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md @@ -2,6 +2,8 @@ ## Summary +- `edition = "2021"` implies `resolver = "2"` in `Cargo.toml`. + ## Details Since Rust 1.51.0, Cargo has opt-in support for a [new feature resolver][4] @@ -14,5 +16,156 @@ The new feature resolver no longer merges all requested features for crates that are depended on in multiple ways. See [the announcement of Rust 1.51][5] for details. -[4]: https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2 -[5]: https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver \ No newline at end of file +[4]: ../../cargo/reference/resolver.html#feature-resolver-version-2 +[5]: https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver + +## Migration + +There are no automated migration tools for updating for the new resolver. +For most projects, there are usually few or no changes as a result of updating. + +When updating with `cargo fix --edition`, Cargo will display a report if the new resolver will build dependencies with different features. +It may look something like this: + +> note: Switching to Edition 2021 will enable the use of the version 2 feature resolver in Cargo. +> This may cause some dependencies to be built with fewer features enabled than previously. +> More information about the resolver changes may be found at
+> When building the following dependencies, the given features will no longer be used: +> +> ```text +> bstr v0.2.16: default, lazy_static, regex-automata, unicode +> libz-sys v1.1.3 (as host dependency): libc +> ``` + +This lets you know that certain dependencies will no longer be built with the given features. + +### Build failures + +There may be some circumstances where your project may not build correctly after the change. +If a dependency declaration in one package assumes that certain features are enabled in another, and those features are now disabled, it may fail to compile. + +For example, let's say we have a dependency like this: + +```toml +# Cargo.toml + +[dependencies] +bstr = { version = "0.2.16", default-features = false } +# ... +``` + +And somewhere in our dependency tree, another package has this: + +```toml +# Another package's Cargo.toml + +[build-dependencies] +bstr = "0.2.16" +``` + +In our package, we've been using the [`words_with_breaks`](https://docs.rs/bstr/0.2.16/bstr/trait.ByteSlice.html#method.words_with_breaks) method from `bstr`, which requires `bstr`'s "unicode" feature to be enabled. +This has historically worked because Cargo unified the features of `bstr` between the two packages. +However, after updating to Rust 2021, the new resolver will build `bstr` twice, once with the default features (as a build dependency), and once with no features (as our normal dependency). +Since `bstr` is now being built without the "unicode" feature, the `words_with_breaks` method doesn't exist, and the build will fail with an error that the method is missing. + +The solution here is to ensure that the dependency is declared with the features you are actually using. +For example: + +```toml +[dependencies] +bstr = { version = "0.2.16", default-features = false, features = ["unicode"] } +``` + +In some cases, this may be a problem with a third-party dependency that you don't have direct control over. +You can consider submitting a patch to that project to try to declare the correct set of features for the problematic dependency. +Alternatively, you can add features to any dependency from within your own `Cargo.toml` file. +For example, if the `bstr` example given above was declared in some third-party dependency, you can just copy the correct dependency declaration into your own project. +The features will be unified, as long as they match the unification rules of the new resolver. Those are: + +* Features enabled on platform-specific dependencies for targets not currently being built are ignored. +* Build-dependencies and proc-macros do not share features with normal dependencies. +* Dev-dependencies do not activate features unless building a target that needs them (like tests or examples). + +A real-world example is using [`diesel`](https://crates.io/crates/diesel) and [`diesel_migrations`](https://crates.io/crates/diesel_migrations). +These packages provide database support, and the database is selected using a feature, like this: + +```toml +[dependencies] +diesel = { version = "1.4.7", features = ["postgres"] } +diesel_migrations = "1.4.0" +``` + +The problem is that `diesel_migrations` has an internal proc-macro which itself depends on `diesel`, and the proc-macro assumes its own copy of `diesel` has the same features enabled as the rest of the dependency graph. +After updating to the new resolver, it fails to build because now there are two copies of `diesel`, and the one built for the proc-macro is missing the "postgres" feature. + +A solution here is to add `diesel` as a build-dependency with the required features, for example: + +```toml +[build-dependencies] +diesel = { version = "1.4.7", features = ["postgres"] } +``` + +This causes Cargo to add "postgres" as a feature for host dependencies (proc-macros and build-dependencies). +Now, the `diesel_migrations` proc-macro will get the "postgres" feature enabled, and it will build correctly. + +The 2.0 release of `diesel` (currently in development) does not have this problem as it has been restructured to not have this dependency requirement. + +### Exploring features + +The [`cargo tree`] command has had substantial improvements to help with the migration to the new resolver. +`cargo tree` can be used to explore the dependency graph, and to see which features are being enabled, and importantly *why* they are being enabled. + +One option is to use the `--duplicates` flag (`-d` for short), which will tell you when a package is being built multiple times. +Taking the `bstr` example from earlier, we might see: + +```console +> cargo tree -d +bstr v0.2.16 +└── foo v0.1.0 (/MyProjects/foo) + +bstr v0.2.16 +[build-dependencies] +└── bar v0.1.0 + └── foo v0.1.0 (/MyProjects/foo) + +``` + +This output tells us that `bstr` is built twice, and shows the chain of dependencies that led to its inclusion in both cases. + +You can print which features each package is using with the `-f` flag, like this: + +```console +cargo tree -f '{p} {f}' +``` + +This tells Cargo to change the "format" of the output, where it will print both the package and the enabled features. + +You can also use the `-e` flag to tell it which "edges" to display. +For example, `cargo tree -e features` will show in-between each dependency which features are being added by each dependency. +This option becomes more useful with the `-i` flag which can be used to "invert" the tree. +This allows you to see how features *flow* into a given dependency. +For example, let's say the dependency graph is large, and we're not quite sure who is depending on `bstr`, the following command will show that: + +```console +> cargo tree -e features -i bstr +bstr v0.2.16 +├── bstr feature "default" +│ [build-dependencies] +│ └── bar v0.1.0 +│ └── bar feature "default" +│ └── foo v0.1.0 (/MyProjects/foo) +├── bstr feature "lazy_static" +│ └── bstr feature "unicode" +│ └── bstr feature "default" (*) +├── bstr feature "regex-automata" +│ └── bstr feature "unicode" (*) +├── bstr feature "std" +│ └── bstr feature "default" (*) +└── bstr feature "unicode" (*) +``` + +This snippet of output shows that the project `foo` depends on `bar` with the "default" feature. +Then, `bar` depends on `bstr` as a build-dependency with the "default" feature +We can further see that `bstr`'s "default" feature enables "unicode" (among other features). + +[`cargo tree`]: ../../cargo/commands/cargo-tree.html diff --git a/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md b/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md index 4e47fd452d..f82b486ac9 100644 --- a/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md +++ b/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md @@ -2,36 +2,153 @@ ## Summary +- `|| a.x + 1` now captures only `a.x` instead of `a`. +- This can cause things to be dropped at different times or affect whether closures implement traits like `Send` or `Clone`. + - If possible changes are detected, `cargo fix` will insert statements like `let _ = &a` to force a closure to capture the entire variable. + ## Details [Closures](https://doc.rust-lang.org/book/ch13-01-closures.html) automatically capture anything that you refer to from within their body. For example, `|| a + 1` automatically captures a reference to `a` from the surrounding context. -Currently, this applies to whole structs, even when only using one field. +In Rust 2018 and before, closures capture entire variables, even if the closure only uses one field. For example, `|| a.x + 1` captures a reference to `a` and not just `a.x`. -In some situations, this is a problem. -When a field of the struct is already borrowed (mutably) or moved out of, -the other fields can no longer be used in a closure, -since that would capture the whole struct, which is no longer available. +Capturing `a` in its entirety prevents mutation or moves from other fields of `a`, so that code like this does not compile: ```rust,ignore let a = SomeStruct::new(); - drop(a.x); // Move out of one field of the struct - println!("{}", a.y); // Ok: Still use another field of the struct - let c = || println!("{}", a.y); // Error: Tries to capture all of `a` c(); ``` -Starting in Rust 2021, closures will only capture the fields that they use. -So, the above example will compile fine in Rust 2021. +Starting in Rust 2021, closures captures are more precise. Typically they will only capture the fields they use (in some cases, they might capture more than just what they use, see the Rust reference for full details). Therefore, the above example will compile fine in Rust 2021. + +Disjoint capture was proposed as part of [RFC 2229](https://github.com/rust-lang/rfcs/blob/master/text/2229-capture-disjoint-fields.md) and the RFC contains details about the motivation. + +## Migrating to Rust 2021 + +Changing the variables captured by a closure can cause programs to change behavior or to stop compiling in two cases: + +- changes to drop order, or when destructors run ([details](#drop-order)); +- changes to which traits a closure implements ([details](#trait-implementations)). + +Whenever any of the scenarios below are detected, `cargo fix` will insert a "dummy let" into your closure to force it to capture the entire variable: + +```rust +let x = (vec![22], vec![23]); +let c = move || { + // "Dummy let" that forces `x` to be captured in its entirety + let _ = &x; + + // Otherwise, only `x.0` would be captured here + println!("{:?}", x.0); +}; +``` + +This is a conservative analysis: in many cases, these dummy lets can be safely removed and your program will work fine. + +### Wild Card Patterns + +Closures now only capture data that needs to be read, which means the following closures will not capture `x`: + +```rust +let x = 10; +let c = || { + let _ = x; // no-op +}; + +let c = || match x { + _ => println!("Hello World!") +}; +``` + +The `let _ = x` statement here is a no-op, since the `_` pattern completely ignores the right-hand side, and `x` is a reference to a place in memory (in this case, a variable). + +This change by itself (capturing fewer values) doesn't trigger any suggestions, but it may do so in conjunction with the "drop order" change below. + +**Subtle:** There are other similar expressions, such as the "dummy lets" `let _ = &x` that we insert, which are not no-ops. This is because the right-hand side (`&x`) is not a reference to a place in memory, but rather an expression that must first be evaluated (and whose result is then discarded). + +### Drop Order + +When a closure takes ownership of a value from a variable `t`, that value is then dropped when the closure is dropped, and not when the variable `t` goes out of scope: -This new behavior is only activated in the new edition, -since it can change the order in which fields are dropped. -As for all edition changes, an automatic migration is available, -which will update your closures for which this matters. -It can insert `let _ = &a;` inside the closure to force the entire -struct to be captured as before. +```rust +# fn move_value(_: T){} +{ + let t = (vec![0], vec![0]); + + { + let c = || move_value(t); // t is moved here + } // c is dropped, which drops the tuple `t` as well +} // t goes out of scope here +``` + +The above code will run the same in both Rust 2018 and Rust 2021. However, in cases where the closure only takes ownership of _part_ of a variable, there can be differences: + +```rust +# fn move_value(_: T){} +{ + let t = (vec![0], vec![0]); + + { + let c = || { + // In Rust 2018, captures all of `t`. + // In Rust 2021, captures only `t.0` + move_value(t.0); + }; + + // In Rust 2018, `c` (and `t`) are both dropped when we + // exit this block. + // + // In Rust 2021, `c` and `t.0` are both dropped when we + // exit this block. + } + +// In Rust 2018, the value from `t` has been moved and is +// not dropped. +// +// In Rust 2021, the value from `t.0` has been moved, but `t.1` +// remains, so it will be dropped here. +} +``` + +In most cases, dropping values at different times just affects when memory is freed and is not important. However, some `Drop` impls (aka, destructors) have side-effects, and changing the drop order in those cases can alter the semantics of your program. In such cases, the compiler will suggest inserting a dummy `let` to force the entire variable to be captured. + +### Trait implementations + +Closures automatically implement the following traits based on what values they capture: + +- [`Clone`]: if all captured values are [`Clone`]. +- [Auto traits] like [`Send`], [`Sync`], and [`UnwindSafe`]: if all captured values implement the given trait. + +[auto traits]: https://doc.rust-lang.org/nightly/reference/special-types-and-traits.html#auto-traits +[`clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html +[`send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +[`sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +[`unwindsafe`]: https://doc.rust-lang.org/std/marker/trait.UnwindSafe.html + +In Rust 2021, since different values are being captured, this can affect what traits a closure will implement. The migration lints test each closure to see whether it would have implemented a given trait before and whether it still implements it now; if they find that a trait used to be implemented but no longer is, then "dummy lets" are inserted. + +For instance, a common way to allow passing around raw pointers between threads is to wrap them in a struct and then implement `Send`/`Sync` auto trait for the wrapper. The closure that is passed to `thread::spawn` uses the specific fields within the wrapper but the entire wrapper is captured regardless. Since the wrapper is `Send`/`Sync`, the code is considered safe and therefore compiles successfully. + +With disjoint captures, only the specific field mentioned in the closure gets captured, which wasn't originally `Send`/`Sync` defeating the purpose of the wrapper. + +```rust +use std::thread; + +struct Ptr(*mut i32); +unsafe impl Send for Ptr {} + + +let mut x = 5; +let px = Ptr(&mut x as *mut i32); + +let c = thread::spawn(move || { + unsafe { + *(px.0) += 10; + } +}); // Closure captured px.0 which is not Send +``` diff --git a/src/doc/edition-guide/src/rust-2021/or-patterns-macro-rules.md b/src/doc/edition-guide/src/rust-2021/or-patterns-macro-rules.md index 451b0e5f64..58d6d5517e 100644 --- a/src/doc/edition-guide/src/rust-2021/or-patterns-macro-rules.md +++ b/src/doc/edition-guide/src/rust-2021/or-patterns-macro-rules.md @@ -2,6 +2,11 @@ ## Summary +- How patterns work in `macro_rules` macros changes slightly: + - `$_:pat` in `macro_rules` now matches usage of `|` too: e.g. `A | B`. + - The new `$_:pat_param` behaves like `$_:pat` did before; it does not match (top level) `|`. + - `$_:pat_param` is available in all editions. + ## Details Starting in Rust 1.53.0, [patterns](https://doc.rust-lang.org/stable/reference/patterns.html) @@ -11,18 +16,57 @@ Since this was simply not allowed before, this is not a breaking change. However, this change also affects [`macro_rules` macros](https://doc.rust-lang.org/stable/reference/macros-by-example.html). Such macros can accept patterns using the `:pat` fragment specifier. -Currently, `:pat` does *not* match `|`, since before Rust 1.53, +Currently, `:pat` does *not* match top level `|`, since before Rust 1.53, not all patterns (at all nested levels) could contain a `|`. Macros that accept patterns like `A | B`, such as [`matches!()`](https://doc.rust-lang.org/1.51.0/std/macro.matches.html) -use something like `$($_:pat)|+`. -Because we don't want to break any existing macros, -we did *not* change the meaning of `:pat` in Rust 1.53.0 to include `|`. +use something like `$($_:pat)|+`. -Instead, we will make that change as part of Rust 2021. +Because this would potentially break existing macros, the meaning of `:pat` did +not change in Rust 1.53.0 to include `|`. Instead, that change happens in Rust 2021. In the new edition, the `:pat` fragment specifier *will* match `A | B`. -Since there are times that one still wishes to match a single pattern -variant without `|`, the fragment specified `:pat_param` has been added -to retain the older behavior. -The name refers to its main use case: a pattern in a closure parameter. +`$_:pat` fragments in Rust 2021 cannot be followed by an explicit `|`. Since there are times +that one still wishes to match pattern fragments followed by a `|`, the fragment specified `:pat_param` +has been added to retain the older behavior. + +It's important to remember that editions are _per crate_, so the only relevant edition is the edition +of the crate where the macro is defined. The edition of the crate where the macro is used does not +change how the macro works. + +## Migration to Rust 2021 + +A lint, `rust_2021_incompatible_or_patterns`, gets triggered whenever there is a use `$:_pat` which +will change meaning in Rust 2021. + +You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by +running: + +```sh +cargo fix --edition +``` + +If you have a macro which relies on `$_:pat` not matching the top level use of `|` in patterns, +you'll need to change each occurrence of `$_:pat` to `$_:pat_param`. + +For example: + +```rust +macro_rules! my_macro { + ($x:pat | $y:pat) => { + // TODO: implementation + } +} + +// This macro works in Rust 2018 since `$x:pat` does not match against `|`: +my_macro!(1 | 2); + +// In Rust 2021 however, the `$_:pat` fragment matches `|` and is not allowed +// to be followed by a `|`. To make sure this macro still works in Rust 2021 +// change the macro to the following: +macro_rules! my_macro { + ($x:pat_param | $y:pat) => { // <- this line is different + // TODO: implementation + } +} +``` \ No newline at end of file diff --git a/src/doc/edition-guide/src/rust-2021/panic-macro-consistency.md b/src/doc/edition-guide/src/rust-2021/panic-macro-consistency.md index cf4265bcc5..0e3295186e 100644 --- a/src/doc/edition-guide/src/rust-2021/panic-macro-consistency.md +++ b/src/doc/edition-guide/src/rust-2021/panic-macro-consistency.md @@ -2,14 +2,21 @@ ## Summary -## Details +- `panic!(..)` now always uses `format_args!(..)`, just like `println!()`. +- `panic!("{")` is no longer accepted, without escaping the `{` as `{{`. +- `panic!(x)` is no longer accepted if `x` is not a string literal. + - Use `std::panic::panic_any(x)` to panic with a non-string payload. + - Or use `panic!("{}", x)` to use `x`'s `Display` implementation. +- The same applies to `assert!(expr, ..)`. +## Details The `panic!()` macro is one of Rust's most well known macros. However, it has [some subtle surprises](https://github.com/rust-lang/rfcs/blob/master/text/3007-panic-plan.md) that we can't just change due to backwards compatibility. ```rust,ignore +// Rust 2018 panic!("{}", 1); // Ok, panics with the message "1" panic!("{}"); // Ok, panics with the message "{}" ``` @@ -18,12 +25,14 @@ The `panic!()` macro only uses string formatting when it's invoked with more tha When invoked with a single argument, it doesn't even look at that argument. ```rust,ignore +// Rust 2018 let a = "{"; println!(a); // Error: First argument must be a format string literal panic!(a); // Ok: The panic macro doesn't care ``` -(It even accepts non-strings such as `panic!(123)`, which is uncommon and rarely useful.) +It even accepts non-strings such as `panic!(123)`, which is uncommon and rarely useful since it +produces a surprisingly unhelpful message: `panicked at 'Box'`. This will especially be a problem once [implicit format arguments](https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html) @@ -39,6 +48,37 @@ Since `panic!()` will no longer accept arbitrary payloads, [`panic_any()`](https://doc.rust-lang.org/stable/std/panic/fn.panic_any.html) will be the only way to panic with something other than a formatted string. +```rust,ignore +// Rust 2021 +panic!("{}", 1); // Ok, panics with the message "1" +panic!("{}"); // Error, missing argument +panic!(a); // Error, must be a string literal +``` + In addition, `core::panic!()` and `std::panic!()` will be identical in Rust 2021. Currently, there are some historical differences between those two, -which can be noticable when switching `#![no_std]` on or off. \ No newline at end of file +which can be noticeable when switching `#![no_std]` on or off. + +## Migration + +A lint, `non_fmt_panics`, gets triggered whenever there is some call to `panic` that uses some +deprecated behavior that will error in Rust 2021. The `non_fmt_panics` lint has already been a warning +by default on all editions since the 1.50 release (with several enhancements made in later releases). +If your code is already warning free, then it should already be ready to go for Rust 2021! + +You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by +running: + +```sh +cargo fix --edition +``` + +Should you choose or need to manually migrate, you'll need to update all panic invocations to either use the same +formatting as `println` or use `std::panic::panic_any` to panic with non-string data. + +For example, in the case of `panic!(MyStruct)`, you'll need to convert to using `std::panic::panic_any` (note +that this is a function not a macro): `std::panic::panic_any(MyStruct)`. + +In the case of panic messages that include curly braces but the wrong number of arguments (e.g., `panic!("Some curlies: {}")`), +you can panic with the string literal by either using the same syntax as `println!` (i.e., `panic!("{}", "Some curlies: {}")`) +or by escaping the curly braces (i.e., `panic!("Some curlies: {{}}")`). \ No newline at end of file diff --git a/src/doc/edition-guide/src/rust-2021/prelude.md b/src/doc/edition-guide/src/rust-2021/prelude.md index 2d182066f0..97e6df865d 100644 --- a/src/doc/edition-guide/src/rust-2021/prelude.md +++ b/src/doc/edition-guide/src/rust-2021/prelude.md @@ -2,6 +2,9 @@ ## Summary +- The `TryInto`, `TryFrom` and `FromIterator` traits are now part of the prelude. +- This might make calls to trait methods ambiguous which could make some code fail to compile. + ## Details The [prelude of the standard library](https://doc.rust-lang.org/stable/std/prelude/index.html) @@ -14,12 +17,11 @@ For example, if you have a crate or module called `example` containing a `pub st then `use example::*;` will make `Option` unambiguously refer to the one from `example`; not the one from the standard library. -However, adding a *trait* to the prelude can break existing code in a subtle way. -A call to `x.try_into()` using a `MyTryInto` trait might become ambiguous and -fail to compile if `std`'s `TryInto` is also imported, -since it provides a method with the same name. -This is the reason we haven't added `TryInto` to the prelude yet, -since there is a lot of code that would break this way. +However, adding a _trait_ to the prelude can break existing code in a subtle way. +For example, a call to `x.try_into()` which comes from a `MyTryInto` trait might fail +to compile if `std`'s `TryInto` is also imported, because the call to `try_into` is now +ambiguous and could come from either trait. This is the reason we haven't added `TryInto` +to the prelude yet, since there is a lot of code that would break this way. As a solution, Rust 2021 will use a new prelude. It's identical to the current one, except for three new additions: @@ -28,5 +30,130 @@ It's identical to the current one, except for three new additions: - [`std::convert::TryFrom`](https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html) - [`std::iter::FromIterator`](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html) -The library team still needs to formally approve these, which will likely happen soon. - +The tracking issue [can be found here](https://github.com/rust-lang/rust/issues/85684). + +## Migration to Rust 2021 + +As a part of the 2021 edition a migration lint, `rust_2021_prelude_collisions`, has been added in order to aid in automatic migration of Rust 2018 codebases to Rust 2021. + +In order to have `rustfix` migrate your code to be Rust 2021 Edition compatible, run: + +```sh +cargo fix --edition +``` + +The lint detects cases where functions or methods are called that have the same name as the methods defined in one of the new prelude traits. In some cases, it may rewrite your calls in various ways to ensure that you continue to call the same function you did before. + +If you'd like to migrate your code manually or better understand what `rustfix` is doing, below we've outlined the situations where a migration is needed along with a counter example of when it's not needed. + +### Migration needed + +#### Conflicting trait methods + +When two traits that are in scope have the same method name, it is ambiguous which trait method should be used. For example: + +```rust +trait MyTrait
{ + // This name is the same as the `from_iter` method on the `FromIterator` trait from `std`. + fn from_iter(x: Option); +} + +impl MyTrait<()> for Vec { + fn from_iter(_: Option<()>) {} +} + +fn main() { + // Vec implements both `std::iter::FromIterator` and `MyTrait` + // If both traits are in scope (as would be the case in Rust 2021), + // then it becomes ambiguous which `from_iter` method to call + >::from_iter(None); +} +``` + +We can fix this by using fully qualified syntax: + +```rust,ignore +fn main() { + // Now it is clear which trait method we're referring to + as MyTrait>::from_iter(None); +} +``` + +#### Inherent methods on `dyn Trait` objects + +Some users invoke methods on a `dyn Trait` value where the method name overlaps with a new prelude trait: + +```rust +mod submodule { + pub trait MyTrait { + // This has the same name as `TryInto::try_into` + fn try_into(&self) -> Result; + } +} + +// `MyTrait` isn't in scope here and can only be referred to through the path `submodule::MyTrait` +fn bar(f: Box) { + // If `std::convert::TryInto` is in scope (as would be the case in Rust 2021), + // then it becomes ambiguous which `try_into` method to call + f.try_into(); +} +``` + +Unlike with static dispatch methods, calling a trait method on a trait object does not require that the trait be in scope. The code above works +as long as there is no trait in scope with a conflicting method name. When the `TryInto` trait is in scope (which is the case in Rust 2021), +this causes an ambiguity. Should the call be to `MyTrait::try_into` or `std::convert::TryInto::try_into`? + +In these cases, we can fix this by adding an additional dereferences or otherwise clarify the type of the method receiver. This ensures that +the `dyn Trait` method is chosen, versus the methods from the prelude trait. For example, turning `f.try_into()` above into `(&*f).try_into()` +ensures that we're calling `try_into` on the `dyn MyTrait` which can only refer to the `MyTrait::try_into` method. + +### No migration needed + +#### Inherent methods + +Many types define their own inherent methods with the same name as a trait method. For instance, below the struct `MyStruct` implements `from_iter` which shares the same name with the method from the trait `FromIterator` found in the standard library: + +```rust +use std::iter::IntoIterator; + +struct MyStruct { + data: Vec +} + +impl MyStruct { + // This has the same name as `std::iter::FromIterator::from_iter` + fn from_iter(iter: impl IntoIterator) -> Self { + Self { + data: iter.into_iter().collect() + } + } +} + +impl std::iter::FromIterator for MyStruct { + fn from_iter>(iter: I) -> Self { + Self { + data: iter.into_iter().collect() + } + } +} +``` + +Inherent methods always take precedent over trait methods so there's no need for any migration. + +### Implementation Reference + +The lint needs to take a couple of factors into account when determining whether or not introducing 2021 Edition to a codebase will cause a name resolution collision (thus breaking the code after changing edition). These factors include: + +- Is the call a [fully-qualified call] or does it use [dot-call method syntax]? + - This will affect how the name is resolved due to auto-reference and auto-dereferencing on method call syntax. Manually dereferencing/referencing will allow specifying priority in the case of dot-call method syntax, while fully-qualified call requires specification of the type and the trait name in the method path (e.g. `::method`) +- Is this an [inherent method] or [a trait method]? + - Inherent methods that take `self` will take priority over `TryInto::try_into` as inherent methods take priority over trait methods, but inherent methods that take `&self` or `&mut self` won't take priority due to requiring a auto-reference (while `TryInto::try_into` does not, as it takes `self`) +- Is the origin of this method from `core`/`std`? (As the traits can't have a collision with themselves) +- Does the given type implement the trait it could have a collision against? +- Is the method being called via dynamic dispatch? (i.e. is the `self` type `dyn Trait`) + - If so, trait imports don't affect resolution, and no migration lint needs to occur + +[fully-qualified call]: https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls +[dot-call method syntax]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html +[inherent method]: https://doc.rust-lang.org/reference/items/implementations.html#inherent-implementations +[a trait method]: https://doc.rust-lang.org/reference/items/implementations.html#trait-implementations diff --git a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md index 315954be53..52f8e1221a 100644 --- a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md +++ b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md @@ -2,6 +2,11 @@ ## Summary +- `any_prefix#..`, `any_prefix".."`, and `any_prefix'..'` are reserved syntax, and no longer tokenize. +- This is mostly relevant to macros. E.g. `quote!{ #a#b }` is no longer accepted. +- It doesn't treat keywords specially, so e.g. `match".." {}` is no longer accepted. +- Insert whitespace to avoid errors. + ## Details To make space for some new syntax in the future, @@ -37,4 +42,4 @@ These are some new prefixes you might see in the future: this prefix would've allowed us to accept `k#async` in edition 2015 without having to wait for edition 2018 to reserve `async` as a keyword. -[10]: https://github.com/rust-lang/rfcs/pull/3101 \ No newline at end of file +[10]: https://github.com/rust-lang/rfcs/pull/3101 diff --git a/src/doc/edition-guide/src/rust-2021/warnings-promoted-to-error.md b/src/doc/edition-guide/src/rust-2021/warnings-promoted-to-error.md index 5c20246d18..f17e2b2b26 100644 --- a/src/doc/edition-guide/src/rust-2021/warnings-promoted-to-error.md +++ b/src/doc/edition-guide/src/rust-2021/warnings-promoted-to-error.md @@ -2,16 +2,48 @@ ## Summary +- Code that triggered the `bare_trait_objects` and `ellipsis_inclusive_range_patterns` lints will error in Rust 2021. + ## Details -Two existing lints are becoming hard errors in Rust 2021. -These lints will remain warnings in older editions. +Two existing lints are becoming hard errors in Rust 2021, but these lints will remain warnings in older editions. + +### `bare_trait_objects`: + +The use of the `dyn` keyword to identify [trait objects](https://doc.rust-lang.org/book/ch17-02-trait-objects.html) +will be mandatory in Rust 2021. + +For example, the following code which does not include the `dyn` keyword in `&MyTrait` +will produce an error instead of just a lint in Rust 2021: + +```rust +pub trait MyTrait {} + +pub fn my_function(_trait_object: &MyTrait) { // should be `&dyn MyTrait` + unimplemented!() +} +``` + +### `ellipsis_inclusive_range_patterns`: + +The [deprecated `...` syntax](https://doc.rust-lang.org/stable/reference/patterns.html#range-patterns) +for inclusive range patterns (i.e., ranges where the end value is *included* in the range) is no longer +accepted in Rust 2021. It has been superseded by `..=`, which is consistent with expressions. + +For example, the following code which uses `...` in a pattern will produce an error instead of +just a lint in Rust 2021: + +```rust +pub fn less_or_eq_to_100(n: u8) -> bool { + matches!(n, 0...100) // should be `0..=100` +} +``` + +## Migrations -* `bare-trait-objects`: - The use of the `dyn` keyword to identify [trait objects](https://doc.rust-lang.org/book/ch17-02-trait-objects.html) - will be mandatory in Rust 2021. +If your Rust 2015 or 2018 code does not produce any warnings for `bare_trait_objects` +or `ellipsis_inclusive_range_patterns` and you've not allowed these lints through the +use of `#![allow()]` or some other mechanism, then there's no need to migrate. -* `ellipsis-inclusive-range-patterns`: - The [deprecated `...` syntax](https://doc.rust-lang.org/stable/reference/patterns.html#range-patterns) - for inclusive range patterns is no longer accepted in Rust 2021. - It has been superseded by `..=`, which is consistent with expressions. \ No newline at end of file +To automatically migrate any crate that uses `...` in patterns or does not use `dyn` with +trait objects, you can run `cargo fix --edition`. \ No newline at end of file diff --git a/src/doc/edition-guide/triagebot.toml b/src/doc/edition-guide/triagebot.toml new file mode 100644 index 0000000000..5648018b6b --- /dev/null +++ b/src/doc/edition-guide/triagebot.toml @@ -0,0 +1,4 @@ +[assign] + +[relabel] + diff --git a/src/doc/embedded-book/src/collections/index.md b/src/doc/embedded-book/src/collections/index.md index 5f5a09808e..7319a397ac 100644 --- a/src/doc/embedded-book/src/collections/index.md +++ b/src/doc/embedded-book/src/collections/index.md @@ -10,7 +10,7 @@ memory allocator (AKA the heap). [`HashMap`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html As `core` is, by definition, free of memory allocations these implementations -are not available there, but they can be found in the *unstable* `alloc` crate +are not available there, but they can be found in the `alloc` crate that's shipped with the compiler. If you need collections, a heap allocated implementation is not your only diff --git a/src/doc/embedded-book/src/interoperability/c-with-rust.md b/src/doc/embedded-book/src/interoperability/c-with-rust.md index 3de7c49e36..f7cfb959cc 100644 --- a/src/doc/embedded-book/src/interoperability/c-with-rust.md +++ b/src/doc/embedded-book/src/interoperability/c-with-rust.md @@ -58,7 +58,7 @@ pub x: cty::c_int, pub y: cty::c_int, ``` -Due to the flexibility of how C or C++ defines an `int` or `char`, it is recommended to use primitive data types defined in `cty`, which will map types from C to types in Rust +Due to the flexibility of how C or C++ defines an `int` or `char`, it is recommended to use primitive data types defined in `cty`, which will map types from C to types in Rust. ```rust,ignore pub extern "C" fn cool_function( ... ); @@ -80,8 +80,8 @@ We have one new type here, `*mut CoolStruct`. As C does not have a concept of Ru Rather than manually generating these interfaces, which may be tedious and error prone, there is a tool called [bindgen] which will perform these conversions automatically. For instructions of the usage of [bindgen], please refer to the [bindgen user's manual], however the typical process consists of the following: -1. Gather all C or C++ headers defining interfaces or datatypes you would like to use with Rust -2. Write a `bindings.h` file, which `#include "..."`'s each of the files you gathered in step one +1. Gather all C or C++ headers defining interfaces or datatypes you would like to use with Rust. +2. Write a `bindings.h` file, which `#include "..."`'s each of the files you gathered in step one. 3. Feed this `bindings.h` file, along with any compilation flags used to compile your code into `bindgen`. Tip: use `Builder.ctypes_prefix("cty")` / `--ctypes-prefix=cty` and `Builder.use_core()` / `--use-core` to make the generated code `#![no_std]` compatible. @@ -104,7 +104,7 @@ If your code exists as a source project, it will be necessary to compile your C/ A `build.rs` script is a file written in Rust syntax, that is executed on your compilation machine, AFTER dependencies of your project have been built, but BEFORE your project is built. -The full reference may be found [here](https://doc.rust-lang.org/cargo/reference/build-scripts.html). `build.rs` scripts are useful for generating code (such as via [bindgen]), calling out to external build systems such as `Make`, or directly compiling C/C++ through use of the `cc` crate +The full reference may be found [here](https://doc.rust-lang.org/cargo/reference/build-scripts.html). `build.rs` scripts are useful for generating code (such as via [bindgen]), calling out to external build systems such as `Make`, or directly compiling C/C++ through use of the `cc` crate. ### Triggering external build systems diff --git a/src/doc/embedded-book/src/start/hardware.md b/src/doc/embedded-book/src/start/hardware.md index 94221e4274..5af7804a64 100644 --- a/src/doc/embedded-book/src/start/hardware.md +++ b/src/doc/embedded-book/src/start/hardware.md @@ -49,10 +49,10 @@ $ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart $ cd app ``` -Step number one is to set a default compilation target in `.cargo/config`. +Step number one is to set a default compilation target in `.cargo/config.toml`. ``` console -tail -n5 .cargo/config +tail -n5 .cargo/config.toml ``` ``` toml @@ -320,10 +320,10 @@ OpenOCD, enable semihosting, load the program and start the process. Alternatively, you can turn ` -x openocd.gdb` into a custom runner to make `cargo run` build a program *and* start a GDB session. This runner is included -in `.cargo/config` but it's commented out. +in `.cargo/config.toml` but it's commented out. ``` console -head -n10 .cargo/config +head -n10 .cargo/config.toml ``` ``` toml diff --git a/src/doc/embedded-book/src/start/qemu.md b/src/doc/embedded-book/src/start/qemu.md index 69866569c3..a56f7394c6 100644 --- a/src/doc/embedded-book/src/start/qemu.md +++ b/src/doc/embedded-book/src/start/qemu.md @@ -137,11 +137,11 @@ bit in the function signature) to ensure at compile time that'll be the case. The next step is to *cross* compile the program for the Cortex-M3 architecture. That's as simple as running `cargo build --target $TRIPLE` if you know what the -compilation target (`$TRIPLE`) should be. Luckily, the `.cargo/config` in the +compilation target (`$TRIPLE`) should be. Luckily, the `.cargo/config.toml` in the template has the answer: ```console -tail -n6 .cargo/config +tail -n6 .cargo/config.toml ``` ```toml @@ -161,7 +161,7 @@ if you haven't done it yet: rustup target add thumbv7m-none-eabi ``` Since the `thumbv7m-none-eabi` compilation target has been set as the default in - your `.cargo/config` file, the two commands below do the same: + your `.cargo/config.toml` file, the two commands below do the same: ```console cargo build --target thumbv7m-none-eabi @@ -401,11 +401,11 @@ Let's break down that QEMU command: machine. Typing out that long QEMU command is too much work! We can set a custom runner -to simplify the process. `.cargo/config` has a commented out runner that invokes +to simplify the process. `.cargo/config.toml` has a commented out runner that invokes QEMU; let's uncomment it: ```console -head -n3 .cargo/config +head -n3 .cargo/config.toml ``` ```toml diff --git a/src/doc/embedded-book/src/start/semihosting.md b/src/doc/embedded-book/src/start/semihosting.md index feae1a0725..cf4626f44b 100644 --- a/src/doc/embedded-book/src/start/semihosting.md +++ b/src/doc/embedded-book/src/start/semihosting.md @@ -48,7 +48,7 @@ semihosting is enabled QEMU understands semihosting operations so the above program will also work with `qemu-system-arm` without having to start a debug session. Note that you'll need to pass the `-semihosting-config` flag to QEMU to enable semihosting -support; these flags are already included in the `.cargo/config` file of the +support; these flags are already included in the `.cargo/config.toml` file of the template. ``` text diff --git a/src/doc/embedded-book/src/unsorted/speed-vs-size.md b/src/doc/embedded-book/src/unsorted/speed-vs-size.md index da914e6ab9..6538d94ba4 100644 --- a/src/doc/embedded-book/src/unsorted/speed-vs-size.md +++ b/src/doc/embedded-book/src/unsorted/speed-vs-size.md @@ -148,10 +148,10 @@ closures). When optimizing for size you may want to try increasing the inline threshold to see if that has any effect on the binary size. The recommended way to change the inline threshold is to append the `-C inline-threshold` flag to the other -rustflags in `.cargo/config`. +rustflags in `.cargo/config.toml`. ``` toml -# .cargo/config +# .cargo/config.toml # this assumes that you are using the cortex-m-quickstart template [target.'cfg(all(target_arch = "arm", target_os = "none"))'] rustflags = [ diff --git a/src/doc/nomicon/README.md b/src/doc/nomicon/README.md index 9e511a2b11..8b61a3de6d 100644 --- a/src/doc/nomicon/README.md +++ b/src/doc/nomicon/README.md @@ -19,14 +19,14 @@ order to write correct Unsafe Rust programs. Due to the nature of this problem, it may lead to unleashing untold horrors that shatter your psyche into a billion infinitesimal fragments of despair. -### Requirements +## Requirements Building the Nomicon requires [mdBook]. To get it: [mdBook]: https://github.com/rust-lang/mdBook ```bash -$ cargo install mdbook +cargo install mdbook ``` ### `mdbook` usage @@ -34,7 +34,7 @@ $ cargo install mdbook To build the Nomicon use the `build` sub-command: ```bash -$ mdbook build +mdbook build ``` The output will be placed in the `book` subdirectory. To check it out, open the @@ -43,13 +43,23 @@ build` and it'll open the index page in your default browser (if the process is successful) just like with `cargo doc --open`: ```bash -$ mdbook build --open +mdbook build --open ``` There is also a `test` sub-command to test all code samples contained in the book: ```bash -$ mdbook test +mdbook test +``` + +### `linkcheck` + +We use the `linkcheck` tool to find broken links. +To run it locally: + +```sh +curl -sSLo linkcheck.sh https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh +sh linkcheck.sh --all nomicon ``` ## Contributing diff --git a/src/doc/nomicon/book.toml b/src/doc/nomicon/book.toml index 37984f1300..a2011c61f9 100644 --- a/src/doc/nomicon/book.toml +++ b/src/doc/nomicon/book.toml @@ -4,4 +4,32 @@ title = "The Rustonomicon" description = "The Dark Arts of Advanced and Unsafe Rust Programming" [output.html] +additional-css = ["theme/nomicon.css"] git-repository-url = "https://github.com/rust-lang/nomicon" + +[output.html.redirect] +# Vec-related chapters. +"./vec-alloc.html" = "./vec/vec-alloc.html" +"./vec-dealloc.html" = "./vec/vec-dealloc.html" +"./vec-deref.html" = "./vec/vec-deref.html" +"./vec-drain.html" = "./vec/vec-drain.html" +"./vec-final.html" = "./vec/vec-final.html" +"./vec-insert-remove.html" = "./vec/vec-insert-remove.html" +"./vec-into-iter.html" = "./vec/vec-into-iter.html" +"./vec-layout.html" = "./vec/vec-layout.html" +"./vec-push-pop.html" = "./vec/vec-push-pop.html" +"./vec-raw.html" = "./vec/vec-raw.html" +"./vec-zsts.html" = "./vec/vec-zsts.html" +"./vec.html" = "./vec/vec.html" + +# Arc and Mutex related chapters. +"./arc-and-mutex.html" = "./arc-mutex/arc-and-mutex.html" +"./arc-base.html" = "./arc-mutex/arc-base.html" +"./arc-clone.html" = "./arc-mutex/arc-clone.html" +"./arc-drop.html" = "./arc-mutex/arc-drop.html" +"./arc-final.html" = "./arc-mutex/arc-final.html" +"./arc-layout.html" = "./arc-mutex/arc-layout.html" +"./arc.html" = "./arc-mutex/arc.html" + +[rust] +edition = "2018" diff --git a/src/doc/nomicon/src/README.md b/src/doc/nomicon/src/README.md deleted file mode 100644 index cc50b5f459..0000000000 --- a/src/doc/nomicon/src/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# The Rustonomicon - -#### The Dark Arts of Unsafe Rust - -> THE KNOWLEDGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF UNLEASHING INDESCRIBABLE HORRORS THAT -SHATTER YOUR PSYCHE AND SET YOUR MIND ADRIFT IN THE UNKNOWABLY INFINITE COSMOS. - -The Rustonomicon digs into all the awful details that you need to understand when -writing Unsafe Rust programs. - -Should you wish a long and happy career of writing Rust programs, you should -turn back now and forget you ever saw this book. It is not necessary. However -if you intend to write unsafe code — or just want to dig into the guts of the -language — this book contains lots of useful information. - -Unlike *[The Rust Programming Language][trpl]*, we will be assuming considerable -prior knowledge. In particular, you should be comfortable with basic systems -programming and Rust. If you don't feel comfortable with these topics, you -should consider reading [The Book][trpl] first. That said, we won't assume you -have read it, and we will take care to occasionally give a refresher on the -basics where appropriate. You can skip straight to this book if you want; -just know that we won't be explaining everything from the ground up. - -This book exists primarily as a high-level companion to [The Reference][ref]. -Where The Reference exists to detail the syntax and semantics of every part of -the language, The Rustonomicon exists to describe how to use those pieces together, -and the issues that you will have in doing so. - -The Reference will tell you the syntax and semantics of references, destructors, and -unwinding, but it won't tell you how combining them can lead to exception-safety -issues, or how to deal with those issues. - -It should be noted that when The Rustonomicon was originally written, The -Reference was in a state of complete disrepair, and so many things that should -have been covered by The Reference were originally only documented here. Since -then, The Reference has been revitalized and is properly maintained, although -it is still far from complete. In general, if the two documents disagree, The -Reference should be assumed to be correct (it isn't yet considered normative, -it's just better maintained). - -Topics that are within the scope of this book include: the meaning of (un)safety, -unsafe primitives provided by the language and standard library, techniques for -creating safe abstractions with those unsafe primitives, subtyping and variance, -exception-safety (panic/unwind-safety), working with uninitialized memory, -type punning, concurrency, interoperating with other languages (FFI), -optimization tricks, how constructs lower to compiler/OS/hardware primitives, -how to **not** make the memory model people angry, how you're **going** to make the -memory model people angry, and more. - -The Rustonomicon is not a place to exhaustively describe the semantics and guarantees -of every single API in the standard library, nor is it a place to exhaustively describe -every feature of Rust. - -[trpl]: ../book/index.html -[ref]: ../reference/index.html diff --git a/src/doc/nomicon/src/SUMMARY.md b/src/doc/nomicon/src/SUMMARY.md index fbd9cc0b5d..f1d15a71dd 100644 --- a/src/doc/nomicon/src/SUMMARY.md +++ b/src/doc/nomicon/src/SUMMARY.md @@ -1,66 +1,66 @@ # Summary -[Introduction](README.md) +[Introduction](intro.md) * [Meet Safe and Unsafe](meet-safe-and-unsafe.md) - * [How Safe and Unsafe Interact](safe-unsafe-meaning.md) - * [What Unsafe Can Do](what-unsafe-does.md) - * [Working with Unsafe](working-with-unsafe.md) + * [How Safe and Unsafe Interact](safe-unsafe-meaning.md) + * [What Unsafe Can Do](what-unsafe-does.md) + * [Working with Unsafe](working-with-unsafe.md) * [Data Layout](data.md) - * [repr(Rust)](repr-rust.md) - * [Exotically Sized Types](exotic-sizes.md) - * [Other reprs](other-reprs.md) + * [repr(Rust)](repr-rust.md) + * [Exotically Sized Types](exotic-sizes.md) + * [Other reprs](other-reprs.md) * [Ownership](ownership.md) - * [References](references.md) - * [Aliasing](aliasing.md) - * [Lifetimes](lifetimes.md) - * [Limits of Lifetimes](lifetime-mismatch.md) - * [Lifetime Elision](lifetime-elision.md) - * [Unbounded Lifetimes](unbounded-lifetimes.md) - * [Higher-Rank Trait Bounds](hrtb.md) - * [Subtyping and Variance](subtyping.md) - * [Drop Check](dropck.md) - * [PhantomData](phantom-data.md) - * [Splitting Borrows](borrow-splitting.md) + * [References](references.md) + * [Aliasing](aliasing.md) + * [Lifetimes](lifetimes.md) + * [Limits of Lifetimes](lifetime-mismatch.md) + * [Lifetime Elision](lifetime-elision.md) + * [Unbounded Lifetimes](unbounded-lifetimes.md) + * [Higher-Rank Trait Bounds](hrtb.md) + * [Subtyping and Variance](subtyping.md) + * [Drop Check](dropck.md) + * [PhantomData](phantom-data.md) + * [Splitting Borrows](borrow-splitting.md) * [Type Conversions](conversions.md) - * [Coercions](coercions.md) - * [The Dot Operator](dot-operator.md) - * [Casts](casts.md) - * [Transmutes](transmutes.md) + * [Coercions](coercions.md) + * [The Dot Operator](dot-operator.md) + * [Casts](casts.md) + * [Transmutes](transmutes.md) * [Uninitialized Memory](uninitialized.md) - * [Checked](checked-uninit.md) - * [Drop Flags](drop-flags.md) - * [Unchecked](unchecked-uninit.md) + * [Checked](checked-uninit.md) + * [Drop Flags](drop-flags.md) + * [Unchecked](unchecked-uninit.md) * [Ownership Based Resource Management](obrm.md) - * [Constructors](constructors.md) - * [Destructors](destructors.md) - * [Leaking](leaking.md) + * [Constructors](constructors.md) + * [Destructors](destructors.md) + * [Leaking](leaking.md) * [Unwinding](unwinding.md) - * [Exception Safety](exception-safety.md) - * [Poisoning](poisoning.md) + * [Exception Safety](exception-safety.md) + * [Poisoning](poisoning.md) * [Concurrency](concurrency.md) - * [Races](races.md) - * [Send and Sync](send-and-sync.md) - * [Atomics](atomics.md) -* [Implementing Vec](vec.md) - * [Layout](vec-layout.md) - * [Allocating](vec-alloc.md) - * [Push and Pop](vec-push-pop.md) - * [Deallocating](vec-dealloc.md) - * [Deref](vec-deref.md) - * [Insert and Remove](vec-insert-remove.md) - * [IntoIter](vec-into-iter.md) - * [RawVec](vec-raw.md) - * [Drain](vec-drain.md) - * [Handling Zero-Sized Types](vec-zsts.md) - * [Final Code](vec-final.md) -* [Implementing Arc and Mutex](arc-and-mutex.md) - * [Arc](arc.md) - * [Layout](arc-layout.md) - * [Base Code](arc-base.md) - * [Cloning](arc-clone.md) - * [Dropping](arc-drop.md) - * [Final Code](arc-final.md) + * [Races](races.md) + * [Send and Sync](send-and-sync.md) + * [Atomics](atomics.md) +* [Implementing Vec](./vec/vec.md) + * [Layout](./vec/vec-layout.md) + * [Allocating](./vec/vec-alloc.md) + * [Push and Pop](./vec/vec-push-pop.md) + * [Deallocating](./vec/vec-dealloc.md) + * [Deref](./vec/vec-deref.md) + * [Insert and Remove](./vec/vec-insert-remove.md) + * [IntoIter](./vec/vec-into-iter.md) + * [RawVec](./vec/vec-raw.md) + * [Drain](./vec/vec-drain.md) + * [Handling Zero-Sized Types](./vec/vec-zsts.md) + * [Final Code](./vec/vec-final.md) +* [Implementing Arc and Mutex](./arc-mutex/arc-and-mutex.md) + * [Arc](./arc-mutex/arc.md) + * [Layout](./arc-mutex/arc-layout.md) + * [Base Code](./arc-mutex/arc-base.md) + * [Cloning](./arc-mutex/arc-clone.md) + * [Dropping](./arc-mutex/arc-drop.md) + * [Final Code](./arc-mutex/arc-final.md) * [FFI](ffi.md) * [Beneath `std`](beneath-std.md) - * [#[panic_handler]](panic-handler.md) + * [#[panic_handler]](panic-handler.md) diff --git a/src/doc/nomicon/src/aliasing.md b/src/doc/nomicon/src/aliasing.md index ebdec9ab21..993afbaa63 100644 --- a/src/doc/nomicon/src/aliasing.md +++ b/src/doc/nomicon/src/aliasing.md @@ -14,10 +14,7 @@ don't happen unless you tell it otherwise. For more details, see the With that said, here's our working definition: variables and pointers *alias* if they refer to overlapping regions of memory. - - - -# Why Aliasing Matters +## Why Aliasing Matters So why should we care about aliasing? @@ -31,6 +28,7 @@ fn compute(input: &u32, output: &mut u32) { if *input > 5 { *output *= 2; } + // remember that `output` will be `2` if `input > 10` } ``` @@ -38,9 +36,12 @@ We would *like* to be able to optimize it to the following function: ```rust fn compute(input: &u32, output: &mut u32) { - let cached_input = *input; // keep *input in a register + let cached_input = *input; // keep `*input` in a register if cached_input > 10 { - *output = 2; // x > 10 implies x > 5, so double and exit immediately + // If the input is greater than 10, the previous code would set the output to 1 and then double it, + // resulting in an output of 2 (because `>10` implies `>5`). + // Here, we avoid the double assignment and just set it directly to 2. + *output = 2; } else if cached_input > 5 { *output *= 2; } @@ -55,6 +56,7 @@ and `output` overlap, such as `compute(&x, &mut x)`. With that input, we could get this execution: + ```rust,ignore // input == output == 0xabad1dea // *input == *output == 20 @@ -130,6 +132,3 @@ Of course, a full aliasing model for Rust must also take into consideration thin function calls (which may mutate things we don't see), raw pointers (which have no aliasing requirements on their own), and UnsafeCell (which lets the referent of an `&` be mutated). - - - diff --git a/src/doc/nomicon/src/arc-and-mutex.md b/src/doc/nomicon/src/arc-mutex/arc-and-mutex.md similarity index 62% rename from src/doc/nomicon/src/arc-and-mutex.md rename to src/doc/nomicon/src/arc-mutex/arc-and-mutex.md index f6c15830e3..41a4d7c7bd 100644 --- a/src/doc/nomicon/src/arc-and-mutex.md +++ b/src/doc/nomicon/src/arc-mutex/arc-and-mutex.md @@ -2,6 +2,6 @@ Knowing the theory is all fine and good, but the *best* way to understand something is to use it. To better understand atomics and interior mutability, -we'll be implementing versions of the standard library's Arc and Mutex types. +we'll be implementing versions of the standard library's `Arc` and `Mutex` types. -TODO: Mutex +TODO: Write `Mutex` chapters. diff --git a/src/doc/nomicon/src/arc-base.md b/src/doc/nomicon/src/arc-mutex/arc-base.md similarity index 94% rename from src/doc/nomicon/src/arc-base.md rename to src/doc/nomicon/src/arc-mutex/arc-base.md index 7dd6baefda..ee35d86761 100644 --- a/src/doc/nomicon/src/arc-base.md +++ b/src/doc/nomicon/src/arc-mutex/arc-base.md @@ -10,6 +10,7 @@ We'll first need a way to construct an `Arc`. This is pretty simple, as we just need to box the `ArcInner` and get a `NonNull` pointer to it. + ```rust,ignore impl Arc { pub fn new(data: T) -> Arc { @@ -34,13 +35,14 @@ impl Arc { Since we're building a concurrency primitive, we'll need to be able to send it across threads. Thus, we can implement the `Send` and `Sync` marker traits. For more information on these, see [the section on `Send` and -`Sync`](send-and-sync.md). +`Sync`](../send-and-sync.md). This is okay because: * You can only get a mutable reference to the value inside an `Arc` if and only if it is the only `Arc` referencing that data (which only happens in `Drop`) * We use atomics for the shared mutable reference counting + ```rust,ignore unsafe impl Send for Arc {} unsafe impl Sync for Arc {} @@ -61,6 +63,8 @@ as `Rc` is not thread-safe. To dereference the `NonNull` pointer into a `&T`, we can call `NonNull::as_ref`. This is unsafe, unlike the typical `as_ref` function, so we must call it like this: + + ```rust,ignore unsafe { self.ptr.as_ref() } ``` @@ -79,11 +83,15 @@ to the data inside? What we need now is an implementation of `Deref`. We'll need to import the trait: + + ```rust,ignore use std::ops::Deref; ``` And here's the implementation: + + ```rust,ignore impl Deref for Arc { type Target = T; @@ -101,6 +109,8 @@ Pretty simple, eh? This simply dereferences the `NonNull` pointer to the ## Code Here's all the code from this section: + + ```rust,ignore use std::ops::Deref; diff --git a/src/doc/nomicon/src/arc-clone.md b/src/doc/nomicon/src/arc-mutex/arc-clone.md similarity index 91% rename from src/doc/nomicon/src/arc-clone.md rename to src/doc/nomicon/src/arc-mutex/arc-clone.md index ad98800502..1adc6c9e64 100644 --- a/src/doc/nomicon/src/arc-clone.md +++ b/src/doc/nomicon/src/arc-mutex/arc-clone.md @@ -3,15 +3,20 @@ Now that we've got some basic code set up, we'll need a way to clone the `Arc`. Basically, we need to: + 1. Increment the atomic reference count 2. Construct a new instance of the `Arc` from the inner pointer First, we need to get access to the `ArcInner`: + + ```rust,ignore let inner = unsafe { self.ptr.as_ref() }; ``` We can update the atomic reference count as follows: + + ```rust,ignore let old_rc = inner.rc.fetch_add(1, Ordering::???); ``` @@ -23,15 +28,18 @@ happens-before relationship but is atomic. When `Drop`ping the Arc, however, we'll need to atomically synchronize when decrementing the reference count. This is described more in [the section on the `Drop` implementation for `Arc`](arc-drop.md). For more information on atomic relationships and Relaxed -ordering, see [the section on atomics](atomics.md). +ordering, see [the section on atomics](../atomics.md). Thus, the code becomes this: + + ```rust,ignore let old_rc = inner.rc.fetch_add(1, Ordering::Relaxed); ``` We'll need to add another import to use `Ordering`: -```rust,ignore + +```rust use std::sync::atomic::Ordering; ``` @@ -54,7 +62,9 @@ probably incredibly degenerate) if the reference count reaches `isize::MAX` probably not about 2 billion threads (or about **9 quintillion** on some 64-bit machines) incrementing the reference count at once. This is what we'll do. -It's pretty simple to implement this behaviour: +It's pretty simple to implement this behavior: + + ```rust,ignore if old_rc >= isize::MAX as usize { std::process::abort(); @@ -62,6 +72,8 @@ if old_rc >= isize::MAX as usize { ``` Then, we need to return a new instance of the `Arc`: + + ```rust,ignore Self { ptr: self.ptr, @@ -70,6 +82,8 @@ Self { ``` Now, let's wrap this all up inside the `Clone` implementation: + + ```rust,ignore use std::sync::atomic::Ordering; diff --git a/src/doc/nomicon/src/arc-drop.md b/src/doc/nomicon/src/arc-mutex/arc-drop.md similarity index 94% rename from src/doc/nomicon/src/arc-drop.md rename to src/doc/nomicon/src/arc-mutex/arc-drop.md index 0b3cfe5a90..4ed371fc99 100644 --- a/src/doc/nomicon/src/arc-drop.md +++ b/src/doc/nomicon/src/arc-mutex/arc-drop.md @@ -6,13 +6,16 @@ low enough, otherwise the data will live forever on the heap. To do this, we can implement `Drop`. Basically, we need to: + 1. Decrement the reference count 2. If there is only one reference remaining to the data, then: 3. Atomically fence the data to prevent reordering of the use and deletion of the data -4. Drop the inner data +4. Drop the inner data First, we'll need to get access to the `ArcInner`: + + ```rust,ignore let inner = unsafe { self.ptr.as_ref() }; ``` @@ -21,6 +24,8 @@ Now, we need to decrement the reference count. To streamline our code, we can also return if the returned value from `fetch_sub` (the value of the reference count before decrementing it) is not equal to `1` (which happens when we are not the last reference to the data). + + ```rust,ignore if inner.rc.fetch_sub(1, Ordering::Relaxed) != 1 { return; @@ -53,25 +58,24 @@ implementation of `Arc`][3]: > Also note that the Acquire fence here could probably be replaced with an > Acquire load, which could improve performance in highly-contended situations. > See [2]. -> +> > [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html > [2]: https://github.com/rust-lang/rust/pull/41714 [3]: https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/alloc/src/sync.rs#L1440-L1467 To do this, we do the following: -```rust,ignore -atomic::fence(Ordering::Acquire); -``` -We'll need to import `std::sync::atomic` itself: -```rust,ignore +```rust +# use std::sync::atomic::Ordering; use std::sync::atomic; +atomic::fence(Ordering::Acquire); ``` Finally, we can drop the data itself. We use `Box::from_raw` to drop the boxed `ArcInner` and its data. This takes a `*mut T` and not a `NonNull`, so we must convert using `NonNull::as_ptr`. + ```rust,ignore unsafe { Box::from_raw(self.ptr.as_ptr()); } ``` @@ -80,6 +84,8 @@ This is safe as we know we have the last pointer to the `ArcInner` and that its pointer is valid. Now, let's wrap this all up inside the `Drop` implementation: + + ```rust,ignore impl Drop for Arc { fn drop(&mut self) { diff --git a/src/doc/nomicon/src/arc-final.md b/src/doc/nomicon/src/arc-mutex/arc-final.md similarity index 99% rename from src/doc/nomicon/src/arc-final.md rename to src/doc/nomicon/src/arc-mutex/arc-final.md index 4fcc274c31..b9c362d13f 100644 --- a/src/doc/nomicon/src/arc-final.md +++ b/src/doc/nomicon/src/arc-mutex/arc-final.md @@ -1,6 +1,7 @@ # Final Code Here's the final code, with some added comments and re-ordered imports: + ```rust use std::marker::PhantomData; use std::ops::Deref; diff --git a/src/doc/nomicon/src/arc-layout.md b/src/doc/nomicon/src/arc-mutex/arc-layout.md similarity index 93% rename from src/doc/nomicon/src/arc-layout.md rename to src/doc/nomicon/src/arc-mutex/arc-layout.md index 55d4793fc1..3dae2cd25b 100644 --- a/src/doc/nomicon/src/arc-layout.md +++ b/src/doc/nomicon/src/arc-mutex/arc-layout.md @@ -21,7 +21,8 @@ pointer to the T's allocation, we might as well put the reference count in that same allocation. Naively, it would look something like this: -```rust,ignore + +```rust use std::sync::atomic; pub struct Arc { @@ -30,7 +31,7 @@ pub struct Arc { pub struct ArcInner { rc: atomic::AtomicUsize, - data: T + data: T, } ``` @@ -40,11 +41,12 @@ be used where an `Arc<&'a str>` was expected. More importantly, it will give incorrect ownership information to the drop checker, as it will assume we don't own any values of type `T`. As this is a structure providing shared ownership of a value, at some point there will be an instance of this structure that entirely -owns its data. See [the chapter on ownership and lifetimes](ownership.md) for +owns its data. See [the chapter on ownership and lifetimes](../ownership.md) for all the details on variance and drop check. To fix the first problem, we can use `NonNull`. Note that `NonNull` is a wrapper around a raw pointer that declares that: + * We are variant over `T` * Our pointer is never null @@ -53,18 +55,19 @@ To fix the second problem, we can include a `PhantomData` marker containing an ownership of a value of `ArcInner` (which itself contains some `T`). With these changes we get our final structure: -```rust,ignore + +```rust use std::marker::PhantomData; use std::ptr::NonNull; use std::sync::atomic::AtomicUsize; pub struct Arc { ptr: NonNull>, - phantom: PhantomData> + phantom: PhantomData>, } pub struct ArcInner { rc: AtomicUsize, - data: T + data: T, } ``` diff --git a/src/doc/nomicon/src/arc.md b/src/doc/nomicon/src/arc-mutex/arc.md similarity index 86% rename from src/doc/nomicon/src/arc.md rename to src/doc/nomicon/src/arc-mutex/arc.md index 580e6620f1..fd7800f5e1 100644 --- a/src/doc/nomicon/src/arc.md +++ b/src/doc/nomicon/src/arc-mutex/arc.md @@ -1,7 +1,7 @@ # Implementing Arc In this section, we'll be implementing a simpler version of `std::sync::Arc`. -Similarly to [the implementation of `Vec` we made earlier](vec.md), we won't be +Similarly to [the implementation of `Vec` we made earlier](../vec/vec.md), we won't be taking advantage of as many optimizations, intrinsics, or unstable code as the standard library may. diff --git a/src/doc/nomicon/src/atomics.md b/src/doc/nomicon/src/atomics.md index 2883107474..6aef6aee6d 100644 --- a/src/doc/nomicon/src/atomics.md +++ b/src/doc/nomicon/src/atomics.md @@ -22,24 +22,23 @@ semantics we want, the optimizations compilers want, and the inconsistent chaos our hardware wants. *We* would like to just write programs and have them do exactly what we said but, you know, fast. Wouldn't that be great? - - - -# Compiler Reordering +## Compiler Reordering Compilers fundamentally want to be able to do all sorts of complicated transformations to reduce data dependencies and eliminate dead code. In particular, they may radically change the actual order of events, or make events -never occur! If we write something like +never occur! If we write something like: + ```rust,ignore x = 1; y = 3; x = 2; ``` -The compiler may conclude that it would be best if your program did +The compiler may conclude that it would be best if your program did: + ```rust,ignore x = 2; y = 3; @@ -54,10 +53,7 @@ able to make these kinds of optimizations, because they can seriously improve performance. On the other hand, we'd also like to be able to depend on our program *doing the thing we said*. - - - -# Hardware Reordering +## Hardware Reordering On the other hand, even if the compiler totally understood what we wanted and respected our wishes, our hardware might instead get us in trouble. Trouble @@ -110,11 +106,7 @@ programming: incorrect. If possible, concurrent algorithms should be tested on weakly-ordered hardware. - - - - -# Data Accesses +## Data Accesses The C++ memory model attempts to bridge the gap by allowing us to talk about the *causality* of our program. Generally, this is by establishing a *happens @@ -156,9 +148,7 @@ propagated to other threads. The set of orderings Rust exposes are: TODO: negative reasoning vs positive reasoning? TODO: "can't forget to synchronize" - - -# Sequentially Consistent +## Sequentially Consistent Sequentially Consistent is the most powerful of all, implying the restrictions of all other orderings. Intuitively, a sequentially consistent operation @@ -182,10 +172,7 @@ mechanically trivial to downgrade atomic operations to have a weaker consistency later on. Just change `SeqCst` to `Relaxed` and you're done! Of course, proving that this transformation is *correct* is a whole other matter. - - - -# Acquire-Release +## Acquire-Release Acquire and Release are largely intended to be paired. Their names hint at their use case: they're perfectly suited for acquiring and releasing locks, and @@ -200,8 +187,8 @@ reordered to occur before it. When thread A releases a location in memory and then thread B subsequently acquires *the same* location in memory, causality is established. Every write (including non-atomic and relaxed atomic writes) that happened before A's -release will be observed by B after its acquisition. However no causality is -established with any other threads. Similarly, no causality is established +release will be observed by B after its acquisition. However no causality is +established with any other threads. Similarly, no causality is established if A and B access *different* locations in memory. Basic use of release-acquire is therefore simple: you acquire a location of @@ -233,10 +220,7 @@ On strongly-ordered platforms most accesses have release or acquire semantics, making release and acquire often totally free. This is not the case on weakly-ordered platforms. - - - -# Relaxed +## Relaxed Relaxed accesses are the absolute weakest. They can be freely re-ordered and provide no happens-before relationship. Still, relaxed operations are still @@ -251,9 +235,5 @@ There's rarely a benefit in making an operation relaxed on strongly-ordered platforms, since they usually provide release-acquire semantics anyway. However relaxed operations can be cheaper on weakly-ordered platforms. - - - - [C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf [C++-model]: https://en.cppreference.com/w/cpp/atomic/memory_order diff --git a/src/doc/nomicon/src/beneath-std.md b/src/doc/nomicon/src/beneath-std.md index 2c759f0c19..6f05182b25 100644 --- a/src/doc/nomicon/src/beneath-std.md +++ b/src/doc/nomicon/src/beneath-std.md @@ -4,7 +4,7 @@ This section documents (or will document) features that are provided by the stan that `#![no_std]` developers have to deal with (i.e. provide) to build `#![no_std]` binary crates. A (likely incomplete) list of such features is shown below: -- #[lang = "eh_personality"] -- #[lang = "start"] -- #[lang = "termination"] -- #[panic_implementation] +- `#[lang = "eh_personality"]` +- `#[lang = "start"]` +- `#[lang = "termination"]` +- `#[panic_implementation]` diff --git a/src/doc/nomicon/src/casts.md b/src/doc/nomicon/src/casts.md index 014c100c9f..e944809cc1 100644 --- a/src/doc/nomicon/src/casts.md +++ b/src/doc/nomicon/src/casts.md @@ -1,64 +1,34 @@ # Casts -Casts are a superset of coercions: every coercion can be explicitly -invoked via a cast. However some conversions require a cast. -While coercions are pervasive and largely harmless, these "true casts" -are rare and potentially dangerous. As such, casts must be explicitly invoked -using the `as` keyword: `expr as Type`. +Casts are a superset of coercions: every coercion can be explicitly invoked via a cast. +However some conversions require a cast. +While coercions are pervasive and largely harmless, these "true casts" are rare and potentially dangerous. +As such, casts must be explicitly invoked using the `as` keyword: `expr as Type`. -True casts generally revolve around raw pointers and the primitive numeric -types. Even though they're dangerous, these casts are infallible at runtime. -If a cast triggers some subtle corner case no indication will be given that -this occurred. The cast will simply succeed. That said, casts must be valid -at the type level, or else they will be prevented statically. For instance, -`7u8 as bool` will not compile. +You can find an exhaustive list of [all the true casts][cast list] and [casting semantics][semantics list] on the reference. -That said, casts aren't `unsafe` because they generally can't violate memory -safety *on their own*. For instance, converting an integer to a raw pointer can -very easily lead to terrible things. However the act of creating the pointer -itself is safe, because actually using a raw pointer is already marked as -`unsafe`. +## Safety of casting -Here's an exhaustive list of all the true casts. For brevity, we will use `*` -to denote either a `*const` or `*mut`, and `integer` to denote any integral -primitive: +True casts generally revolve around raw pointers and the primitive numeric types. +Even though they're dangerous, these casts are infallible at runtime. +If a cast triggers some subtle corner case no indication will be given that this occurred. +The cast will simply succeed. +That said, casts must be valid at the type level, or else they will be prevented statically. +For instance, `7u8 as bool` will not compile. - * `*T as *U` where `T, U: Sized` - * `*T as *U` TODO: explain unsized situation - * `*T as integer` - * `integer as *T` - * `number as number` - * `field-less enum as integer` - * `bool as integer` - * `char as integer` - * `u8 as char` - * `&[T; n] as *const T` - * `fn as *T` where `T: Sized` - * `fn as integer` +That said, casts aren't `unsafe` because they generally can't violate memory safety *on their own*. +For instance, converting an integer to a raw pointer can very easily lead to terrible things. +However the act of creating the pointer itself is safe, because actually using a raw pointer is already marked as `unsafe`. -Note that lengths are not adjusted when casting raw slices - -`*const [u16] as *const [u8]` creates a slice that only includes -half of the original memory. +## Some notes about casting -Casting is not transitive, that is, even if `e as U1 as U2` is a valid -expression, `e as U2` is not necessarily so. +### Lengths when casting raw slices -For numeric casts, there are quite a few cases to consider: +Note that lengths are not adjusted when casting raw slices; `*const [u16] as *const [u8]` creates a slice that only includes half of the original memory. -* casting between two integers of the same size (e.g. i32 -> u32) is a no-op -* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will - truncate -* casting from a smaller integer to a larger integer (e.g. u8 -> u32) will - * zero-extend if the source is unsigned - * sign-extend if the source is signed -* casting from a float to an integer will round the float towards zero and - produces a "saturating cast" when the float is outside the integer's range - * floats that are too big turn into the largest possible integer - * floats that are too small produce the smallest possible integer - * NaN produces zero -* casting from an integer to float will produce the floating point - representation of the integer, rounded if necessary (rounding to - nearest, ties to even) -* casting from an f32 to an f64 is perfect and lossless -* casting from an f64 to an f32 will produce the closest possible value - (rounding to nearest, ties to even) +### Transitivity + +Casting is not transitive, that is, even if `e as U1 as U2` is a valid expression, `e as U2` is not necessarily so. + +[cast list]: ../reference/expressions/operator-expr.html#type-cast-expressions +[semantics list]: ../reference/expressions/operator-expr.html#semantics diff --git a/src/doc/nomicon/src/coercions.md b/src/doc/nomicon/src/coercions.md index 065a9e1ba2..ffff83f8ec 100644 --- a/src/doc/nomicon/src/coercions.md +++ b/src/doc/nomicon/src/coercions.md @@ -1,58 +1,14 @@ # Coercions -Types can implicitly be coerced to change in certain contexts. These changes are -generally just *weakening* of types, largely focused around pointers and -lifetimes. They mostly exist to make Rust "just work" in more cases, and are -largely harmless. +Types can implicitly be coerced to change in certain contexts. +These changes are generally just *weakening* of types, largely focused around pointers and lifetimes. +They mostly exist to make Rust "just work" in more cases, and are largely harmless. -Here's all the kinds of coercion: +For an exhaustive list of all the types of coercions, see the [Coercion types] section on the reference. -Coercion is allowed between the following types: - -* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to - `T_3` -* Pointer Weakening: - * `&mut T` to `&T` - * `*mut T` to `*const T` - * `&T` to `*const T` - * `&mut T` to `*mut T` -* Unsizing: `T` to `U` if `T` implements `CoerceUnsized` -* Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref`) -* Non-capturing closure to a function pointer ([RFC 1558], e.g. `|| 8usize` to `fn() -> usize`) - -[RFC 1558]: https://rust-lang.github.io/rfcs/1558-closure-to-fn-coercion.html - -`CoerceUnsized> for Pointer where T: Unsize` is implemented -for all pointer types (including smart pointers like Box and Rc). Unsize is -only implemented automatically, and enables the following transformations: - -* `[T; n]` => `[T]` -* `T` => `dyn Trait` where `T: Trait` -* `Foo<..., T, ...>` => `Foo<..., U, ...>` where: - * `T: Unsize` - * `Foo` is a struct - * Only the last field of `Foo` has type involving `T` - * `T` is not part of the type of any other fields - * `Bar: Unsize>`, if the last field of `Foo` has type `Bar` - -Coercions occur at a *coercion site*. Any location that is explicitly typed -will cause a coercion to its type. If inference is necessary, the coercion will -not be performed. Exhaustively, the coercion sites for an expression `e` to -type `U` are: - -* let statements, statics, and consts: `let x: U = e` -* Arguments to functions: `takes_a_U(e)` -* Any expression that will be returned: `fn foo() -> U { e }` -* Struct literals: `Foo { some_u: e }` -* Array literals: `let x: [U; 10] = [e, ..]` -* Tuple literals: `let x: (U, ..) = (e, ..)` -* The last expression in a block: `let x: U = { ..; e }` - -Note that we do not perform coercions when matching traits (except for -receivers, see below). If there is an impl for some type `U` and `T` coerces to -`U`, that does not constitute an implementation for `T`. For example, the -following will not type check, even though it is OK to coerce `t` to `&T` and -there is an impl for `&T`: +Note that we do not perform coercions when matching traits (except for receivers, see the [next page][dot-operator]). +If there is an `impl` for some type `U` and `T` coerces to `U`, that does not constitute an implementation for `T`. +For example, the following will not type check, even though it is OK to coerce `t` to `&T` and there is an `impl` for `&T`: ```rust,compile_fail trait Trait {} @@ -67,20 +23,22 @@ fn main() { } ``` +which fails like as follows: + ```text error[E0277]: the trait bound `&mut i32: Trait` is not satisfied - --> src/main.rs:9:5 + --> src/main.rs:9:9 | +3 | fn foo(t: X) {} + | ----- required by this bound in `foo` +... 9 | foo(t); - | ^^^ the trait `Trait` is not implemented for `&mut i32` + | ^ the trait `Trait` is not implemented for `&mut i32` | = help: the following implementations were found: <&'a i32 as Trait> -note: required by `foo` - --> src/main.rs:3:1 - | -3 | fn foo(t: X) {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error + = note: `Trait` is implemented for `&i32`, but not for `&mut i32` ``` + +[Coercion types]: ../reference/type-coercions.html#coercion-types +[dot-operator]: ./dot-operator.html diff --git a/src/doc/nomicon/src/conversions.md b/src/doc/nomicon/src/conversions.md index 388d003d9b..4c29fd8b26 100644 --- a/src/doc/nomicon/src/conversions.md +++ b/src/doc/nomicon/src/conversions.md @@ -31,4 +31,3 @@ fn reinterpret(foo: Foo) -> Bar { But this is, at best, annoying. For common conversions, Rust provides more ergonomic alternatives. - diff --git a/src/doc/nomicon/src/destructors.md b/src/doc/nomicon/src/destructors.md index 524c401f82..3d99961389 100644 --- a/src/doc/nomicon/src/destructors.md +++ b/src/doc/nomicon/src/destructors.md @@ -3,6 +3,7 @@ What the language *does* provide is full-blown automatic destructors through the `Drop` trait, which provides the following method: + ```rust,ignore fn drop(&mut self); ``` diff --git a/src/doc/nomicon/src/dropck.md b/src/doc/nomicon/src/dropck.md index 41c5afc3c2..28b65c1d3e 100644 --- a/src/doc/nomicon/src/dropck.md +++ b/src/doc/nomicon/src/dropck.md @@ -8,11 +8,15 @@ when we talked about `'a: 'b`, it was ok for `'a` to live _exactly_ as long as gets dropped at the same time as another, right? This is why we used the following desugaring of `let` statements: + ```rust,ignore let x; let y; ``` +desugaring to: + + ```rust,ignore { let x; @@ -29,6 +33,7 @@ definition. There are some more details about order of drop in [RFC 1857][rfc185 Let's do this: + ```rust,ignore let tuple = (vec![], vec![]); ``` @@ -203,7 +208,7 @@ of an inspector's destructor might access that borrowed data. Therefore, the drop checker forces all borrowed data in a value to strictly outlive that value. -# An Escape Hatch +## An Escape Hatch The precise rules that govern drop checking may be less restrictive in the future. @@ -259,7 +264,8 @@ lifetime `'b` and that the only uses of `T` will be moves or drops, but omit the attribute from `'a` and `U`, because we do access data with that lifetime and that type: -```rust,ignore +```rust +#![feature(dropck_eyepatch)] use std::fmt::Display; struct Inspector<'a, 'b, T, U: Display>(&'a u8, &'b u8, T, U); @@ -283,7 +289,7 @@ other avenues for such indirect access.) Here is an example of invoking a callback: -```rust,ignore +```rust struct Inspector(T, &'static str, Box fn(&'r T) -> String>); impl Drop for Inspector { @@ -297,7 +303,7 @@ impl Drop for Inspector { Here is an example of a trait method call: -```rust,ignore +```rust use std::fmt; struct Inspector(T, &'static str); @@ -318,17 +324,17 @@ directly within it. In all of the above cases where the `&'a u8` is accessed in the destructor, adding the `#[may_dangle]` -attribute makes the type vulnerable to misuse that the borrower +attribute makes the type vulnerable to misuse that the borrow checker will not catch, inviting havoc. It is better to avoid adding the attribute. -# A related side note about drop order +## A related side note about drop order While the drop order of fields inside a struct is defined, relying on it is fragile and subtle. When the order matters, it is better to use the [`ManuallyDrop`] wrapper. -# Is that all about drop checker? +## Is that all about drop checker? It turns out that when writing unsafe code, we generally don't need to worry at all about doing the right thing for the drop checker. However there diff --git a/src/doc/nomicon/src/exception-safety.md b/src/doc/nomicon/src/exception-safety.md index 0a63764aaf..3f92e64108 100644 --- a/src/doc/nomicon/src/exception-safety.md +++ b/src/doc/nomicon/src/exception-safety.md @@ -30,15 +30,12 @@ it is not uncommon for Unsafe code to work with arrays of temporarily uninitialized data while repeatedly invoking caller-provided code. Such code needs to be careful and consider exception safety. - - - - ## Vec::push_all `Vec::push_all` is a temporary hack to get extending a Vec by a slice reliably efficient without specialization. Here's a simple implementation: + ```rust,ignore impl Vec { fn push_all(&mut self, to_push: &[T]) { @@ -69,10 +66,6 @@ we *did* clone are dropped, we can set the `len` every loop iteration. If we just want to guarantee that uninitialized memory can't be observed, we can set the `len` after the loop. - - - - ## BinaryHeap::sift_up Bubbling an element up a heap is a bit more complicated than extending a Vec. @@ -83,7 +76,6 @@ bubble_up(heap, index): while index != 0 && heap[index] < heap[parent(index)]: heap.swap(index, parent(index)) index = parent(index) - ``` A literal transcription of this code to Rust is totally fine, but has an annoying @@ -155,6 +147,7 @@ way to do this is to store the algorithm's state in a separate struct with a destructor for the "finally" logic. Whether we panic or not, that destructor will run and clean up after us. + ```rust,ignore struct Hole<'a, T: 'a> { data: &'a mut [T], diff --git a/src/doc/nomicon/src/exotic-sizes.md b/src/doc/nomicon/src/exotic-sizes.md index fa997c0e13..8ada0fb7c7 100644 --- a/src/doc/nomicon/src/exotic-sizes.md +++ b/src/doc/nomicon/src/exotic-sizes.md @@ -3,11 +3,7 @@ Most of the time, we expect types to have a statically known and positive size. This isn't always the case in Rust. - - - - -# Dynamically Sized Types (DSTs) +## Dynamically Sized Types (DSTs) Rust supports Dynamically Sized Types (DSTs): types without a statically known size or alignment. On the surface, this is a bit nonsensical: Rust *must* @@ -69,11 +65,7 @@ fn main() { (Yes, custom DSTs are a largely half-baked feature for now.) - - - - -# Zero Sized Types (ZSTs) +## Zero Sized Types (ZSTs) Rust also allows types to be specified that occupy no space: @@ -121,9 +113,7 @@ type. [alloc]: ../std/alloc/trait.GlobalAlloc.html#tymethod.alloc [ub]: what-unsafe-does.html - - -# Empty Types +## Empty Types Rust also enables types to be declared that *cannot even be instantiated*. These types can only be talked about at the type level, and never at the value level. @@ -149,7 +139,7 @@ other is still UB). The following *could* also compile: -```rust,ignore +```rust,compile_fail enum Void {} let res: Result = Ok(0); @@ -177,22 +167,15 @@ into a reference without any safety problems. It still doesn't prevent you from trying to read or write values, but at least it compiles to a no-op instead of UB. - - - - -# Extern Types +## Extern Types There is [an accepted RFC][extern-types] to add proper types with an unknown size, called *extern types*, which would let Rust developers model things like C's `void*` and other "declared but never defined" types more accurately. However as of -Rust 2018, the feature is stuck in limbo over how `size_of::()` -should behave. - - - +Rust 2018, [the feature is stuck in limbo over how `size_of_val::()` +should behave][extern-types-issue]. -[dst-issue]: https://github.com/rust-lang/rust/issues/26403 [extern-types]: https://github.com/rust-lang/rfcs/blob/master/text/1861-extern-types.md +[extern-types-issue]: https://github.com/rust-lang/rust/issues/43467 [`str`]: ../std/primitive.str.html [slice]: ../std/primitive.slice.html diff --git a/src/doc/nomicon/src/ffi.md b/src/doc/nomicon/src/ffi.md index a8383d6300..8012bbc4c6 100644 --- a/src/doc/nomicon/src/ffi.md +++ b/src/doc/nomicon/src/ffi.md @@ -1,6 +1,6 @@ # Foreign Function Interface -# Introduction +## Introduction This guide will use the [snappy](https://github.com/google/snappy) compression/decompression library as an introduction to writing bindings for @@ -28,6 +28,7 @@ and add `extern crate libc;` to your crate root. The following is a minimal example of calling a foreign function which will compile if snappy is installed: + ```rust,ignore extern crate libc; use libc::size_t; @@ -61,6 +62,7 @@ of keeping the binding correct at runtime. The `extern` block can be extended to cover the entire snappy API: + ```rust,ignore extern crate libc; use libc::{c_int, size_t}; @@ -85,7 +87,7 @@ extern { # fn main() {} ``` -# Creating a safe interface +## Creating a safe interface The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe @@ -96,6 +98,7 @@ vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous length is the number of elements currently contained, and the capacity is the total size in elements of the allocated memory. The length is less than or equal to the capacity. + ```rust,ignore # extern crate libc; # use libc::{c_int, size_t}; @@ -120,6 +123,7 @@ required capacity to hold the compressed output. The vector can then be passed t `snappy_compress` function as an output parameter. An output parameter is also passed to retrieve the true length after compression for setting the length. + ```rust,ignore # extern crate libc; # use libc::{size_t, c_int}; @@ -146,6 +150,7 @@ pub fn compress(src: &[u8]) -> Vec { Decompression is similar, because snappy stores the uncompressed size as part of the compression format and `snappy_uncompressed_length` will retrieve the exact buffer size required. + ```rust,ignore # extern crate libc; # use libc::{size_t, c_int}; @@ -180,6 +185,7 @@ pub fn uncompress(src: &[u8]) -> Option> { Then, we can add some tests to show how to use them. + ```rust,ignore # extern crate libc; # use libc::{c_int, size_t}; @@ -234,7 +240,7 @@ mod tests { } ``` -# Destructors +## Destructors Foreign libraries often hand off ownership of resources to the calling code. When this occurs, we must use Rust's destructors to provide safety and guarantee @@ -242,7 +248,7 @@ the release of these resources (especially in the case of panic). For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html). -# Callbacks from C code to Rust functions +## Callbacks from C code to Rust functions Some external libraries require the usage of callbacks to report back their current state or intermediate data to the caller. @@ -295,7 +301,6 @@ void trigger_callback() { In this example Rust's `main()` will call `trigger_callback()` in C, which would, in turn, call back to `callback()` in Rust. - ## Targeting callbacks to Rust objects The former example showed how a global function can be called from C code. @@ -311,7 +316,6 @@ referenced Rust object. Rust code: ```rust,no_run -#[repr(C)] struct RustObject { a: i32, // Other members... @@ -384,7 +388,7 @@ This can be achieved by unregistering the callback in the object's destructor and designing the library in a way that guarantees that no callback will be performed after deregistration. -# Linking +## Linking The `link` attribute on `extern` blocks provides the basic building block for instructing rustc how it will link to native libraries. There are two accepted @@ -433,7 +437,7 @@ A few examples of how this model can be used are: On macOS, frameworks behave with the same semantics as a dynamic library. -# Unsafe blocks +## Unsafe blocks Some operations, like dereferencing raw pointers or calling functions that have been marked unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to @@ -448,12 +452,13 @@ unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr } This function can only be called from an `unsafe` block or another `unsafe` function. -# Accessing foreign globals +## Accessing foreign globals Foreign APIs often export a global variable which could do something like track global state. In order to access these variables, you declare them in `extern` blocks with the `static` keyword: + ```rust,ignore extern crate libc; @@ -472,6 +477,7 @@ Alternatively, you may need to alter global state provided by a foreign interface. To do this, statics can be declared with `mut` so we can mutate them. + ```rust,ignore extern crate libc; @@ -498,12 +504,13 @@ fn main() { Note that all interaction with a `static mut` is unsafe, both reading and writing. Dealing with global mutable state requires a great deal of care. -# Foreign calling conventions +## Foreign calling conventions Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when calling foreign functions. Some foreign functions, most notably the Windows API, use other calling conventions. Rust provides a way to tell the compiler which convention to use: + ```rust,ignore extern crate libc; @@ -540,7 +547,7 @@ however, windows uses the `C` calling convention, so `C` would be used. This means that in our previous example, we could have used `extern "system" { ... }` to define a block for all windows systems, not only x86 ones. -# Interoperability with foreign code +## Interoperability with foreign code Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C only if the `#[repr(C)]` attribute is applied to it. @@ -565,7 +572,7 @@ The [`libc` crate on crates.io][libc] includes type aliases and function definitions for the C standard library in the `libc` module, and Rust links against `libc` and `libm` by default. -# Variadic functions +## Variadic functions In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can be achieved in Rust by specifying `...` within the argument list of a foreign function declaration: @@ -584,13 +591,13 @@ fn main() { Normal Rust functions can *not* be variadic: -```ignore +```rust,compile_fail // This will not compile -fn foo(x: i32, ...) { } +fn foo(x: i32, ...) {} ``` -# The "nullable pointer optimization" +## The "nullable pointer optimization" Certain Rust types are defined to never be `null`. This includes references (`&T`, `&mut T`), boxes (`Box`), and function pointers (`extern "abi" fn()`). When @@ -615,6 +622,7 @@ callback, which gets called in certain situations. The callback is passed a func and an integer and it is supposed to run the function with the integer as a parameter. So we have function pointers flying across the FFI boundary in both directions. + ```rust,ignore extern crate libc; use libc::c_int; @@ -655,7 +663,7 @@ void register(void (*f)(int (*)(int), int)) { No `transmute` required! -# Calling Rust code from C +## Calling Rust code from C You may wish to compile Rust code in a way so that it can be called from C. This is fairly easy, but requires a few things: @@ -673,7 +681,7 @@ discussed above in "[Foreign Calling Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` attribute turns off Rust's name mangling, so that it is easier to link to. -# FFI and panics +## FFI and panics It’s important to be mindful of `panic!`s when working with FFI. A `panic!` across an FFI boundary is undefined behavior. If you’re writing code that may @@ -702,11 +710,10 @@ for more information. [`catch_unwind`]: ../std/panic/fn.catch_unwind.html -# Representing opaque structs +## Representing opaque structs -Sometimes, a C library wants to provide a pointer to something, but not let you -know the internal details of the thing it wants. The simplest way is to use a -`void *` argument: +Sometimes, a C library wants to provide a pointer to something, but not let you know the internal details of the thing it wants. +A stable and simple way is to use a `void *` argument: ```c void foo(void *arg); @@ -715,6 +722,7 @@ void bar(void *arg); We can represent this in Rust with the `c_void` type: + ```rust,ignore extern crate libc; @@ -775,3 +783,9 @@ Notice that it is a really bad idea to use an empty enum as FFI type. The compiler relies on empty enums being uninhabited, so handling values of type `&Empty` is a huge footgun and can lead to buggy program behavior (by triggering undefined behavior). + +> **NOTE:** The simplest way would use "extern types". +But it's currently (as of June 2021) unstable and has some unresolved questions, see the [RFC page][extern-type-rfc] and the [tracking issue][extern-type-issue] for more details. + +[extern-type-issue]: https://github.com/rust-lang/rust/issues/43467 +[extern-type-rfc]: https://rust-lang.github.io/rfcs/1861-extern-types.html diff --git a/src/doc/nomicon/src/hrtb.md b/src/doc/nomicon/src/hrtb.md index 645986af13..be5a55bbe6 100644 --- a/src/doc/nomicon/src/hrtb.md +++ b/src/doc/nomicon/src/hrtb.md @@ -28,6 +28,7 @@ fn main() { If we try to naively desugar this code in the same way that we did in the lifetimes section, we run into some trouble: + ```rust,ignore struct Closure { data: (u8, u16), @@ -60,6 +61,7 @@ named until we enter the body of `call`! Also, that isn't some fixed lifetime; This job requires The Magic of Higher-Rank Trait Bounds (HRTBs). The way we desugar this is as follows: + ```rust,ignore where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, ``` diff --git a/src/doc/nomicon/src/intro.md b/src/doc/nomicon/src/intro.md new file mode 100644 index 0000000000..5ada80e7be --- /dev/null +++ b/src/doc/nomicon/src/intro.md @@ -0,0 +1,43 @@ +# The Rustonomicon + +
+ +Warning: +This book is incomplete. +Documenting everything and rewriting outdated parts take a while. +See the [issue tracker] to check what's missing/outdated, and if there are any mistakes or ideas that haven't been reported, feel free to open a new issue there. + +
+ +[issue tracker]: https://github.com/rust-lang/nomicon/issues + +## The Dark Arts of Unsafe Rust + +> THE KNOWLEDGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF UNLEASHING INDESCRIBABLE HORRORS THAT SHATTER YOUR PSYCHE AND SET YOUR MIND ADRIFT IN THE UNKNOWABLY INFINITE COSMOS. + +The Rustonomicon digs into all the awful details that you need to understand when writing Unsafe Rust programs. + +Should you wish a long and happy career of writing Rust programs, you should turn back now and forget you ever saw this book. +It is not necessary. +However if you intend to write unsafe code — or just want to dig into the guts of the language — this book contains lots of useful information. + +Unlike *[The Rust Programming Language][trpl]*, we will be assuming considerable prior knowledge. +In particular, you should be comfortable with basic systems programming and Rust. +If you don't feel comfortable with these topics, you should consider reading [The Book][trpl] first. +That said, we won't assume you have read it, and we will take care to occasionally give a refresher on the basics where appropriate. +You can skip straight to this book if you want; just know that we won't be explaining everything from the ground up. + +This book exists primarily as a high-level companion to [The Reference][ref]. +Where The Reference exists to detail the syntax and semantics of every part of the language, The Rustonomicon exists to describe how to use those pieces together, and the issues that you will have in doing so. + +The Reference will tell you the syntax and semantics of references, destructors, and unwinding, but it won't tell you how combining them can lead to exception-safety issues, or how to deal with those issues. + +It should be noted that we haven't synced The Rustnomicon and The Reference well, so they may have a duplicate content. +In general, if the two documents disagree, The Reference should be assumed to be correct (it isn't yet considered normative, it's just better maintained). + +Topics that are within the scope of this book include: the meaning of (un)safety, unsafe primitives provided by the language and standard library, techniques for creating safe abstractions with those unsafe primitives, subtyping and variance, exception-safety (panic/unwind-safety), working with uninitialized memory, type punning, concurrency, interoperating with other languages (FFI), optimization tricks, how constructs lower to compiler/OS/hardware primitives, how to **not** make the memory model people angry, how you're **going** to make the memory model people angry, and more. + +The Rustonomicon is not a place to exhaustively describe the semantics and guarantees of every single API in the standard library, nor is it a place to exhaustively describe every feature of Rust. + +[trpl]: ../book/index.html +[ref]: ../reference/index.html diff --git a/src/doc/nomicon/src/leaking.md b/src/doc/nomicon/src/leaking.md index 3b04e2833c..e46be7dfcf 100644 --- a/src/doc/nomicon/src/leaking.md +++ b/src/doc/nomicon/src/leaking.md @@ -49,8 +49,6 @@ library: * `Rc` * `thread::scoped::JoinGuard` - - ## Drain `drain` is a collections API that moves data out of the container without @@ -71,6 +69,7 @@ unwinding-safe! Easy! Now consider the following: + ```rust,ignore let mut vec = vec![Box::new(0); 4]; @@ -105,9 +104,6 @@ mem::forget us in the middle of the iteration, all that does is *leak even more* Since we've accepted that mem::forget is safe, this is definitely safe. We call leaks causing more leaks a *leak amplification*. - - - ## Rc Rc is an interesting case because at first glance it doesn't appear to be a @@ -121,6 +117,7 @@ Nope. Let's consider a simplified implementation of Rc: + ```rust,ignore struct Rc { ptr: *mut RcBox, @@ -177,9 +174,6 @@ This can be solved by just checking the `ref_count` and doing *something*. The standard library's stance is to just abort, because your program has become horribly degenerate. Also *oh my gosh* it's such a ridiculous corner case. - - - ## thread::scoped::JoinGuard The thread::scoped API intended to allow threads to be spawned that reference @@ -187,6 +181,7 @@ data on their parent's stack without any synchronization over that data by ensuring the parent joins the thread before any of the shared data goes out of scope. + ```rust,ignore pub fn scoped<'a, F>(f: F) -> JoinGuard<'a> where F: FnOnce() + Send + 'a @@ -204,6 +199,7 @@ of the closed-over data goes out of scope in the parent. Usage looked like: + ```rust,ignore let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; { @@ -232,6 +228,7 @@ let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; In principle, this totally works! Rust's ownership system perfectly ensures it! ...except it relies on a destructor being called to be safe. + ```rust,ignore let mut data = Box::new(0); { diff --git a/src/doc/nomicon/src/lifetime-elision.md b/src/doc/nomicon/src/lifetime-elision.md index 76283516ce..c65a15759b 100644 --- a/src/doc/nomicon/src/lifetime-elision.md +++ b/src/doc/nomicon/src/lifetime-elision.md @@ -5,6 +5,7 @@ In order to make common patterns more ergonomic, Rust allows lifetimes to be A *lifetime position* is anywhere you can write a lifetime in a type: + ```rust,ignore &'a T &'a mut T @@ -38,6 +39,7 @@ Elision rules are as follows: Examples: + ```rust,ignore fn print(s: &str); // elided fn print<'a>(s: &'a str); // expanded @@ -60,5 +62,4 @@ fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // ex fn new(buf: &mut [u8]) -> BufWriter; // elided fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded - ``` diff --git a/src/doc/nomicon/src/lifetime-mismatch.md b/src/doc/nomicon/src/lifetime-mismatch.md index c53648c53f..18082a4345 100644 --- a/src/doc/nomicon/src/lifetime-mismatch.md +++ b/src/doc/nomicon/src/lifetime-mismatch.md @@ -2,7 +2,7 @@ Given the following code: -```rust,edition2018,compile_fail +```rust,compile_fail #[derive(Debug)] struct Foo; @@ -40,6 +40,7 @@ What happened? Well, we got the exact same reasoning as we did for [Example 2 in the previous section][ex2]. We desugar the program and we get the following: + ```rust,ignore struct Foo; @@ -70,15 +71,13 @@ blows up in our face! This program is clearly correct according to the reference semantics we actually care about, but the lifetime system is too coarse-grained to handle that. - - -# Improperly reduced borrows +## Improperly reduced borrows The following code fails to compile, because Rust doesn't understand that the borrow is no longer needed and conservatively falls back to using a whole scope for it. This will eventually get fixed. -```rust,edition2018,compile_fail +```rust,compile_fail # use std::collections::HashMap; # use std::hash::Hash; fn get_default<'m, K, V>(map: &'m mut HashMap, key: K) -> &'m mut V @@ -120,5 +119,4 @@ error[E0499]: cannot borrow `*map` as mutable more than once at a time | |_____- returning this value requires that `*map` is borrowed for `'m` ``` - [ex2]: lifetimes.html#example-aliasing-a-mutable-reference diff --git a/src/doc/nomicon/src/lifetimes.md b/src/doc/nomicon/src/lifetimes.md index c6c0e8462f..0a68a28739 100644 --- a/src/doc/nomicon/src/lifetimes.md +++ b/src/doc/nomicon/src/lifetimes.md @@ -45,6 +45,7 @@ let z = &y; The borrow checker always tries to minimize the extent of a lifetime, so it will likely desugar to the following: + ```rust,ignore // NOTE: `'a: {` and `&'b x` is not valid syntax! 'a: { @@ -72,6 +73,7 @@ let y = &x; z = y; ``` + ```rust,ignore 'a: { let x: i32 = 0; @@ -87,9 +89,7 @@ z = y; } ``` - - -# Example: references that outlive referents +## Example: references that outlive referents Alright, let's look at some of those examples from before: @@ -102,6 +102,7 @@ fn as_str(data: &u32) -> &str { desugars to: + ```rust,ignore fn as_str<'a>(data: &'a u32) -> &'a str { 'b: { @@ -129,6 +130,7 @@ up in our face. To make this more clear, we can expand the example: + ```rust,ignore fn as_str<'a>(data: &'a u32) -> &'a str { 'b: { @@ -169,11 +171,7 @@ we could have returned an `&'a str` would have been if it was in a field of the can be considered to reside at the bottom of the stack; though this limits our implementation *just a bit*.) - - - - -# Example: aliasing a mutable reference +## Example: aliasing a mutable reference How about the other example: @@ -184,6 +182,7 @@ data.push(4); println!("{}", x); ``` + ```rust,ignore 'a: { let mut data: Vec = vec![1, 2, 3]; @@ -222,11 +221,9 @@ to the compiler. However it does mean that several programs that are totally correct with respect to Rust's *true* semantics are rejected because lifetimes are too dumb. +## The area covered by a lifetime - -# The area covered by a lifetime - -The lifetime (sometimes called a *borrow*) is *alive* from the place it is +A reference (sometimes called a *borrow*) is *alive* from the place it is created to its last use. The borrowed thing needs to outlive only borrows that are alive. This looks simple, but there are few subtleties. @@ -234,7 +231,7 @@ The following snippet compiles, because after printing `x`, it is no longer needed, so it doesn't matter if it is dangling or aliased (even though the variable `x` *technically* exists to the very end of the scope). -```rust,edition2018 +```rust let mut data = vec![1, 2, 3]; let x = &data[0]; println!("{}", x); @@ -246,7 +243,7 @@ However, if the value has a destructor, the destructor is run at the end of the scope. And running the destructor is considered a use ‒ obviously the last one. So, this will *not* compile. -```rust,edition2018,compile_fail +```rust,compile_fail #[derive(Debug)] struct X<'a>(&'a i32); @@ -266,7 +263,7 @@ One way to convince the compiler that `x` is no longer valid is by using `drop(x Furthermore, there might be multiple possible last uses of the borrow, for example in each branch of a condition. -```rust,edition2018 +```rust # fn some_condition() -> bool { true } let mut data = vec![1, 2, 3]; let x = &data[0]; @@ -286,7 +283,7 @@ borrows just being tied to the same local variable. This often happens around loops (writing a new value of a variable at the end of the loop and using it for the last time at the top of the next iteration). -```rust,edition2018 +```rust let mut data = vec![1, 2, 3]; // This mut allows us to change where the reference points to let mut x = &data[0]; diff --git a/src/doc/nomicon/src/other-reprs.md b/src/doc/nomicon/src/other-reprs.md index a7cc675c1b..2b5a430405 100644 --- a/src/doc/nomicon/src/other-reprs.md +++ b/src/doc/nomicon/src/other-reprs.md @@ -3,10 +3,7 @@ Rust allows you to specify alternative data layout strategies from the default. There's also the [unsafe code guidelines] (note that it's **NOT** normative). - - - -# repr(C) +## repr(C) This is the most important `repr`. It has fairly simple intent: do what C does. The order, size, and alignment of fields is exactly what you would expect from C @@ -15,10 +12,10 @@ or C++. Any type you expect to pass through an FFI boundary should have necessary to soundly do more elaborate tricks with data layout such as reinterpreting values as a different type. -We strongly recommend using [rust-bindgen][] and/or [cbindgen][] to manage your FFI +We strongly recommend using [rust-bindgen] and/or [cbindgen] to manage your FFI boundaries for you. The Rust team works closely with those projects to ensure that they work robustly and are compatible with current and future guarantees -about type layouts and reprs. +about type layouts and `repr`s. The interaction of `repr(C)` with Rust's more exotic data layout features must be kept in mind. Due to its dual purpose as "for FFI" and "for layout control", @@ -57,9 +54,7 @@ construct an instance of an enum that does not match one of its variants. (This allows exhaustive matches to continue to be written and compiled as normal.) - - -# repr(transparent) +## repr(transparent) This can only be used on structs with a single non-zero-sized field (there may be additional zero-sized fields). The effect is that the layout and ABI of the @@ -75,9 +70,7 @@ Foo(f32)` to always have the same ABI as `f32`. More details are in the [RFC][rfc-transparent]. - - -# repr(u*), repr(i*) +## repr(u*), repr(i*) These specify the size to make a fieldless enum. If the discriminant overflows the integer it has to fit in, it will produce a compile-time error. You can @@ -96,15 +89,28 @@ in that there is a defined layout of the type. This makes it possible to pass the enum to C code, or access the type's raw representation and directly manipulate its tag and fields. See [the RFC][really-tagged] for details. -Adding an explicit `repr` to an enum suppresses the null-pointer -optimization. +These `repr`s have no effect on a struct. -These reprs have no effect on a struct. +Adding an explicit `repr(u*)`, `repr(i*)`, or `repr(C)` to an enum suppresses the null-pointer optimization, like: +```rust +# use std::mem::size_of; +enum MyOption { + Some(T), + None, +} +#[repr(u8)] +enum MyReprOption { + Some(T), + None, +} +assert_eq!(8, size_of::>()); +assert_eq!(16, size_of::>()); +``` -# repr(packed) +## repr(packed) `repr(packed)` forces Rust to strip any padding, and only align the type to a byte. This may improve the memory footprint, but will likely have other negative @@ -117,17 +123,15 @@ compiler might be able to paper over alignment issues with shifts and masks. However if you take a reference to a packed field, it's unlikely that the compiler will be able to emit code to avoid an unaligned load. -**[As of Rust 2018, this still can cause undefined behavior.][ub loads]** +[As this can cause undefined behavior][ub loads], the lint has been implemented +and it will become a hard error. `repr(packed)` is not to be used lightly. Unless you have extreme requirements, this should not be used. This repr is a modifier on `repr(C)` and `repr(Rust)`. - - - -# repr(align(n)) +## repr(align(n)) `repr(align(n))` (where `n` is a power of two) forces the type to have an alignment of *at least* n. @@ -139,10 +143,6 @@ kinds of concurrent code). This is a modifier on `repr(C)` and `repr(Rust)`. It is incompatible with `repr(packed)`. - - - - [unsafe code guidelines]: https://rust-lang.github.io/unsafe-code-guidelines/layout.html [drop flags]: drop-flags.html [ub loads]: https://github.com/rust-lang/rust/issues/27060 diff --git a/src/doc/nomicon/src/ownership.md b/src/doc/nomicon/src/ownership.md index dd9e9db244..4cfac68c43 100644 --- a/src/doc/nomicon/src/ownership.md +++ b/src/doc/nomicon/src/ownership.md @@ -17,7 +17,7 @@ issue...). This is a pervasive problem that C and C++ programs need to deal with. Consider this simple mistake that all of us who have used a non-GC'd language have made at one point: -```rust,ignore +```rust,compile_fail fn as_str(data: &u32) -> &str { // compute the string let s = format!("{}", data); @@ -46,7 +46,7 @@ verifying that references don't escape the scope of their referent. That's because ensuring pointers are always valid is much more complicated than this. For instance in this code, -```rust,ignore +```rust,compile_fail let mut data = vec![1, 2, 3]; // get an internal reference let x = &data[0]; @@ -63,4 +63,3 @@ naive scope analysis would be insufficient to prevent this bug, because `data` does in fact live as long as we needed. However it was *changed* while we had a reference into it. This is why Rust requires any references to freeze the referent and its owners. - diff --git a/src/doc/nomicon/src/panic-handler.md b/src/doc/nomicon/src/panic-handler.md index b06707bf35..3b48dba7ae 100644 --- a/src/doc/nomicon/src/panic-handler.md +++ b/src/doc/nomicon/src/panic-handler.md @@ -1,4 +1,4 @@ -## #[panic_handler] +# #[panic_handler] `#[panic_handler]` is used to define the behavior of `panic!` in `#![no_std]` applications. The `#[panic_handler]` attribute must be applied to a function with signature `fn(&PanicInfo) @@ -17,9 +17,10 @@ Below is shown an example where an application has a different panicking behavio whether is compiled using the dev profile (`cargo build`) or using the release profile (`cargo build --release`). -``` rust, ignore -// crate: panic-semihosting -- log panic messages to the host stderr using semihosting +`panic-semihosting` crate -- log panic messages to the host stderr using semihosting: + +```rust,ignore #![no_std] use core::fmt::{Write, self}; @@ -49,8 +50,10 @@ fn panic(info: &PanicInfo) -> ! { } ``` -``` rust, ignore -// crate: panic-halt -- halt the thread on panic; messages are discarded +`panic-halt` crate -- halt the thread on panic; messages are discarded: + + +```rust,ignore #![no_std] @@ -62,8 +65,10 @@ fn panic(_info: &PanicInfo) -> ! { } ``` -``` rust, ignore -// crate: app +`app` crate: + + +```rust,ignore #![no_std] diff --git a/src/doc/nomicon/src/phantom-data.md b/src/doc/nomicon/src/phantom-data.md index 4c9a880520..68ddb8f06f 100644 --- a/src/doc/nomicon/src/phantom-data.md +++ b/src/doc/nomicon/src/phantom-data.md @@ -13,10 +13,12 @@ struct Iter<'a, T: 'a> { ``` However because `'a` is unused within the struct's body, it's *unbounded*. -Because of the troubles this has historically caused, unbounded lifetimes and -types are *forbidden* in struct definitions. Therefore we must somehow refer -to these types in the body. Correctly doing this is necessary to have -correct variance and drop checking. +[Because of the troubles this has historically caused][unused-param], +unbounded lifetimes and types are *forbidden* in struct definitions. +Therefore we must somehow refer to these types in the body. +Correctly doing this is necessary to have correct variance and drop checking. + +[unused-param]: https://rust-lang.github.io/rfcs/0738-variance.html#the-corner-case-unused-parameters-and-parameters-that-are-only-used-unsafely We do this using `PhantomData`, which is a special marker type. `PhantomData` consumes no space, but simulates a field of the given type for the purpose of @@ -25,7 +27,7 @@ the type-system the kind of variance that you want, while also providing other useful things such as the information needed by drop check. Iter logically contains a bunch of `&'a T`s, so this is exactly what we tell -the PhantomData to simulate: +the `PhantomData` to simulate: ```rust use std::marker; @@ -63,7 +65,7 @@ soundness. This will in turn allow people to create unsoundness using Vec's destructor. In order to tell dropck that we *do* own values of type T, and therefore may -drop some T's when *we* drop, we must add an extra PhantomData saying exactly +drop some T's when *we* drop, we must add an extra `PhantomData` saying exactly that: ```rust diff --git a/src/doc/nomicon/src/repr-rust.md b/src/doc/nomicon/src/repr-rust.md index 7baed6ee69..5275b2327f 100644 --- a/src/doc/nomicon/src/repr-rust.md +++ b/src/doc/nomicon/src/repr-rust.md @@ -104,6 +104,7 @@ Rust lays out the fields in the order specified, we expect it to pad the values in the struct to satisfy their alignment requirements. So if Rust didn't reorder fields, we would expect it to produce the following: + ```rust,ignore struct Foo { count: u16, diff --git a/src/doc/nomicon/src/subtyping.md b/src/doc/nomicon/src/subtyping.md index 79b6408350..8ac7c1ab51 100644 --- a/src/doc/nomicon/src/subtyping.md +++ b/src/doc/nomicon/src/subtyping.md @@ -15,7 +15,6 @@ we will then relate it back to how subtyping actually occurs in Rust. So here's our simple extension, *Objective Rust*, featuring three new types: - ```rust trait Animal { fn snuggle(&self); @@ -35,6 +34,7 @@ But unlike normal traits, we can use them as concrete and sized types, just like Now, say we have a very simple function that takes an Animal, like this: + ```rust,ignore fn love(pet: Animal) { pet.snuggle(); @@ -44,6 +44,7 @@ fn love(pet: Animal) { By default, static types must match *exactly* for a program to compile. As such, this code won't compile: + ```rust,ignore let mr_snuggles: Cat = ...; love(mr_snuggles); // ERROR: expected Animal, found Cat @@ -79,6 +80,7 @@ of our static type system, making it worse than useless (and leading to Undefine Here's a simple example of this happening when we apply subtyping in a completely naive "find and replace" way. + ```rust,ignore fn evil_feeder(pet: &mut Animal) { let spike: Dog = ...; @@ -133,10 +135,7 @@ because nothing ever has type `'a`. Lifetimes only occur as part of some larger like `&'a u32` or `IterMut<'a, u32>`. To apply lifetime subtyping, we need to know how to compose subtyping. Once again, we need *variance*. - - - -# Variance +## Variance Variance is where things get a bit complicated. @@ -188,6 +187,10 @@ some sense "fundamental". All the others can be understood by analogy to the oth * `*const T` follows the logic of `&T` * `*mut T` follows the logic of `&mut T` (or `UnsafeCell`) +For more types, see the ["Variance" section][variance-table] on the reference. + +[variance-table]: ../reference/subtyping.html#variance + > NOTE: the *only* source of contravariance in the language is the arguments to > a function, which is why it really doesn't come up much in practice. Invoking > contravariance involves higher-order programming with function pointers that @@ -199,6 +202,7 @@ and look at some examples. First off, let's revisit the meowing dog example: + ```rust,ignore fn evil_feeder(pet: &mut Animal) { let spike: Dog = ...; @@ -265,7 +269,7 @@ enough into the place expecting something long-lived. Here it is: -```rust,ignore +```rust,compile_fail fn evil_feeder(input: &mut T, val: T) { *input = val; } @@ -285,15 +289,16 @@ And what do we get when we run this? ```text error[E0597]: `spike` does not live long enough - --> src/main.rs:9:32 + --> src/main.rs:9:31 | -9 | let spike_str: &str = &spike; - | ^^^^^ borrowed value does not live long enough -10 | evil_feeder(&mut mr_snuggles, spike_str); +6 | let mut mr_snuggles: &'static str = "meow! :3"; // mr. snuggles forever!! + | ------------ type annotation requires that `spike` is borrowed for `'static` +... +9 | let spike_str: &str = &spike; // Only lives for the block + | ^^^^^^ borrowed value does not live long enough +10 | evil_feeder(&mut mr_snuggles, spike_str); // EVIL! 11 | } - | - borrowed value only lives until here - | - = note: borrowed value must be valid for the static lifetime... + | - `spike` dropped here while still borrowed ``` Good, it doesn't compile! Let's break down what's happening here in detail. @@ -343,6 +348,7 @@ are guaranteed to be the only one with access to it. Consider the following code: + ```rust,ignore let mr_snuggles: Box = ..; let spike: Box = ..; @@ -368,6 +374,7 @@ Only one thing left to explain: function pointers. To see why `fn(T) -> U` should be covariant over `U`, consider the following signature: + ```rust,ignore fn get_animal() -> Animal; ``` @@ -375,6 +382,7 @@ fn get_animal() -> Animal; This function claims to produce an Animal. As such, it is perfectly valid to provide a function with the following signature instead: + ```rust,ignore fn get_animal() -> Cat; ``` @@ -387,12 +395,14 @@ just forget that fact. However, the same logic does not apply to *arguments*. Consider trying to satisfy: + ```rust,ignore fn handle_animal(Animal); ``` -with +with: + ```rust,ignore fn handle_animal(Cat); ``` @@ -442,4 +452,3 @@ struct MyType<'a, 'b, A: 'a, B: 'b, C, D, E, F, G, H, In, Out, Mixed> { k2: Mixed, // invariant over Mixed, because invariance wins all conflicts } ``` - diff --git a/src/doc/nomicon/src/transmutes.md b/src/doc/nomicon/src/transmutes.md index 3733c13796..1b2d6997bd 100644 --- a/src/doc/nomicon/src/transmutes.md +++ b/src/doc/nomicon/src/transmutes.md @@ -20,9 +20,9 @@ boggling. it may produce a surprising type to satisfy inference. * Transmuting an `&` to `&mut` is UB. - * Transmuting an `&` to `&mut` is *always* UB. - * No you can't do it. - * No you're not special. + * Transmuting an `&` to `&mut` is *always* UB. + * No you can't do it. + * No you're not special. * Transmuting to a reference without an explicitly provided lifetime produces an [unbounded lifetime]. @@ -50,7 +50,6 @@ Also of course you can get all of the functionality of these functions using raw pointer casts or `union`s, but without any of the lints or other basic sanity checks. Raw pointer casts and `union`s do not magically avoid the above rules. - [unbounded lifetime]: ./unbounded-lifetimes.md [transmute]: ../std/mem/fn.transmute.html [transmute_copy]: ../std/mem/fn.transmute_copy.html diff --git a/src/doc/nomicon/src/unbounded-lifetimes.md b/src/doc/nomicon/src/unbounded-lifetimes.md index b41cf8b4ed..03febd6ad5 100644 --- a/src/doc/nomicon/src/unbounded-lifetimes.md +++ b/src/doc/nomicon/src/unbounded-lifetimes.md @@ -17,6 +17,7 @@ boundaries. Given a function, any output lifetimes that don't derive from inputs are unbounded. For instance: + ```rust,ignore fn get_str<'a>() -> &'a str; ``` @@ -33,4 +34,3 @@ way to bound a lifetime is to return it from a function with a bound lifetime. However if this is unacceptable, the reference can be placed in a location with a specific lifetime. Unfortunately it's impossible to name all lifetimes involved in a function. - diff --git a/src/doc/nomicon/src/unchecked-uninit.md b/src/doc/nomicon/src/unchecked-uninit.md index 29e1b6a360..7c07521329 100644 --- a/src/doc/nomicon/src/unchecked-uninit.md +++ b/src/doc/nomicon/src/unchecked-uninit.md @@ -79,11 +79,14 @@ This code proceeds in three steps: acknowledge that by providing appropriate methods). It's worth spending a bit more time on the loop in the middle, and in particular -the assignment operator and its interaction with `drop`. If we would have -written something like +the assignment operator and its interaction with `drop`. If we would have +written something like: + + ```rust,ignore *x[i].as_mut_ptr() = Box::new(i as u32); // WRONG! ``` + we would actually overwrite a `Box`, leading to `drop` of uninitialized data, which will cause much sadness and pain. @@ -126,6 +129,7 @@ Note that, to use the `ptr` methods, you need to first obtain a *raw pointer* to the data you want to initialize. It is illegal to construct a *reference* to uninitialized data, which implies that you have to be careful when obtaining said raw pointer: + * For an array of `T`, you can use `base_ptr.add(idx)` where `base_ptr: *mut T` to compute the address of array index `idx`. This relies on how arrays are laid out in memory. @@ -133,9 +137,9 @@ how arrays are laid out in memory. also cannot use `&mut base_ptr.field` as that would be creating a reference. Thus, it is currently not possible to create a raw pointer to a field of a partially initialized struct, and also not possible to initialize a single -field of a partially initialized struct. (A -[solution to this problem](https://github.com/rust-lang/rfcs/pull/2582) is being -worked on.) +field of a partially initialized struct. (a +[solution to this problem](https://github.com/rust-lang/rust/issues/64490) is being +worked on). One last remark: when reading old Rust code, you might stumble upon the deprecated `mem::uninitialized` function. That function used to be the only way diff --git a/src/doc/nomicon/src/vec-alloc.md b/src/doc/nomicon/src/vec/vec-alloc.md similarity index 96% rename from src/doc/nomicon/src/vec-alloc.md rename to src/doc/nomicon/src/vec/vec-alloc.md index cf3844bdfd..b301fc6643 100644 --- a/src/doc/nomicon/src/vec-alloc.md +++ b/src/doc/nomicon/src/vec/vec-alloc.md @@ -17,6 +17,7 @@ want to use `dangling` because there's no real allocation to talk about but So: + ```rust,ignore use std::mem; @@ -83,6 +84,7 @@ compiler to be able to reason about data dependencies and aliasing. As a simple example, consider the following fragment of code: + ```rust,ignore *x *= 7; *y *= 3; @@ -162,6 +164,7 @@ such we will guard against this case explicitly. Ok with all the nonsense out of the way, let's actually allocate some memory: + ```rust,ignore use std::alloc::{self, Layout}; @@ -202,9 +205,9 @@ impl Vec { # fn main() {} ``` -[Global]: ../std/alloc/struct.Global.html -[handle_alloc_error]: ../alloc/alloc/fn.handle_alloc_error.html -[alloc]: ../alloc/alloc/fn.alloc.html -[realloc]: ../alloc/alloc/fn.realloc.html -[dealloc]: ../alloc/alloc/fn.dealloc.html -[std_alloc]: ../alloc/alloc/index.html +[Global]: ../../std/alloc/struct.Global.html +[handle_alloc_error]: ../../alloc/alloc/fn.handle_alloc_error.html +[alloc]: ../../alloc/alloc/fn.alloc.html +[realloc]: ../../alloc/alloc/fn.realloc.html +[dealloc]: ../../alloc/alloc/fn.dealloc.html +[std_alloc]: ../../alloc/alloc/index.html diff --git a/src/doc/nomicon/src/vec-dealloc.md b/src/doc/nomicon/src/vec/vec-dealloc.md similarity index 96% rename from src/doc/nomicon/src/vec-dealloc.md rename to src/doc/nomicon/src/vec/vec-dealloc.md index 45fe9412d3..d403f92d29 100644 --- a/src/doc/nomicon/src/vec-dealloc.md +++ b/src/doc/nomicon/src/vec/vec-dealloc.md @@ -10,6 +10,7 @@ wouldn't bother unless you notice it's not being stripped (in this case it is). We must not call `alloc::dealloc` when `self.cap == 0`, as in this case we haven't actually allocated any memory. + ```rust,ignore impl Drop for Vec { fn drop(&mut self) { diff --git a/src/doc/nomicon/src/vec-deref.md b/src/doc/nomicon/src/vec/vec-deref.md similarity index 94% rename from src/doc/nomicon/src/vec-deref.md rename to src/doc/nomicon/src/vec/vec-deref.md index 68d64f7ba4..3021cb08b7 100644 --- a/src/doc/nomicon/src/vec-deref.md +++ b/src/doc/nomicon/src/vec/vec-deref.md @@ -11,6 +11,7 @@ All we need is `slice::from_raw_parts`. It will correctly handle empty slices for us. Later once we set up zero-sized type support it will also Just Work for those too. + ```rust,ignore use std::ops::Deref; @@ -26,6 +27,7 @@ impl Deref for Vec { And let's do DerefMut too: + ```rust,ignore use std::ops::DerefMut; diff --git a/src/doc/nomicon/src/vec-drain.md b/src/doc/nomicon/src/vec/vec-drain.md similarity index 96% rename from src/doc/nomicon/src/vec-drain.md rename to src/doc/nomicon/src/vec/vec-drain.md index 9b38dfff63..fbc8edd037 100644 --- a/src/doc/nomicon/src/vec-drain.md +++ b/src/doc/nomicon/src/vec/vec-drain.md @@ -4,6 +4,7 @@ Let's move on to Drain. Drain is largely the same as IntoIter, except that instead of consuming the Vec, it borrows the Vec and leaves its allocation untouched. For now we'll only implement the "basic" full-range version. + ```rust,ignore use std::marker::PhantomData; @@ -26,6 +27,7 @@ impl<'a, T> Iterator for Drain<'a, T> { -- wait, this is seeming familiar. Let's do some more compression. Both IntoIter and Drain have the exact same structure, let's just factor it out. + ```rust,ignore struct RawValIter { start: *const T, @@ -57,6 +59,7 @@ impl RawValIter { And IntoIter becomes the following: + ```rust,ignore pub struct IntoIter { _buf: RawVec, // we don't actually care about this. Just need it to live. @@ -103,6 +106,7 @@ We also take a slice to simplify Drain initialization. Alright, now Drain is really easy: + ```rust,ignore use std::marker::PhantomData; @@ -149,4 +153,4 @@ impl Vec { For more details on the `mem::forget` problem, see the [section on leaks][leaks]. -[leaks]: leaking.html +[leaks]: ../leaking.html diff --git a/src/doc/nomicon/src/vec-final.md b/src/doc/nomicon/src/vec/vec-final.md similarity index 100% rename from src/doc/nomicon/src/vec-final.md rename to src/doc/nomicon/src/vec/vec-final.md diff --git a/src/doc/nomicon/src/vec-insert-remove.md b/src/doc/nomicon/src/vec/vec-insert-remove.md similarity index 96% rename from src/doc/nomicon/src/vec-insert-remove.md rename to src/doc/nomicon/src/vec/vec-insert-remove.md index 9138b3ec35..57283f990f 100644 --- a/src/doc/nomicon/src/vec-insert-remove.md +++ b/src/doc/nomicon/src/vec/vec-insert-remove.md @@ -12,6 +12,7 @@ definitely happen here). If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` using the old len. + ```rust,ignore pub fn insert(&mut self, index: usize, elem: T) { // Note: `<=` because it's valid to insert after everything @@ -33,6 +34,7 @@ pub fn insert(&mut self, index: usize, elem: T) { Remove behaves in the opposite manner. We need to shift all the elements from `[i+1 .. len + 1]` to `[i .. len]` using the *new* len. + ```rust,ignore pub fn remove(&mut self, index: usize) -> T { // Note: `<` because it's *not* valid to remove after everything diff --git a/src/doc/nomicon/src/vec-into-iter.md b/src/doc/nomicon/src/vec/vec-into-iter.md similarity index 96% rename from src/doc/nomicon/src/vec-into-iter.md rename to src/doc/nomicon/src/vec/vec-into-iter.md index 03c2a9d3e8..33327e8f31 100644 --- a/src/doc/nomicon/src/vec-into-iter.md +++ b/src/doc/nomicon/src/vec/vec-into-iter.md @@ -42,6 +42,7 @@ dropped. So we're going to use the following struct: + ```rust,ignore pub struct IntoIter { buf: NonNull, @@ -54,6 +55,7 @@ pub struct IntoIter { And this is what we end up with for initialization: + ```rust,ignore impl Vec { pub fn into_iter(self) -> IntoIter { @@ -85,6 +87,7 @@ impl Vec { Here's iterating forward: + ```rust,ignore impl Iterator for IntoIter { type Item = T; @@ -110,6 +113,7 @@ impl Iterator for IntoIter { And here's iterating backwards. + ```rust,ignore impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { @@ -129,7 +133,7 @@ Because IntoIter takes ownership of its allocation, it needs to implement Drop to free it. However it also wants to implement Drop to drop any elements it contains that weren't yielded. - + ```rust,ignore impl Drop for IntoIter { fn drop(&mut self) { diff --git a/src/doc/nomicon/src/vec-layout.md b/src/doc/nomicon/src/vec/vec-layout.md similarity index 94% rename from src/doc/nomicon/src/vec-layout.md rename to src/doc/nomicon/src/vec/vec-layout.md index 20e23065ed..c1c1afcc7a 100644 --- a/src/doc/nomicon/src/vec-layout.md +++ b/src/doc/nomicon/src/vec/vec-layout.md @@ -6,6 +6,7 @@ elements that have been initialized. Naively, this means we just want this design: + ```rust,ignore pub struct Vec { ptr: *mut T, @@ -56,5 +57,5 @@ unsafe impl Sync for Vec {} # fn main() {} ``` -[ownership]: ownership.html -[NonNull]: ../std/ptr/struct.NonNull.html +[ownership]: ../ownership.html +[NonNull]: ../../std/ptr/struct.NonNull.html diff --git a/src/doc/nomicon/src/vec-push-pop.md b/src/doc/nomicon/src/vec/vec-push-pop.md similarity index 96% rename from src/doc/nomicon/src/vec-push-pop.md rename to src/doc/nomicon/src/vec/vec-push-pop.md index 2366e36d7d..2a4e016421 100644 --- a/src/doc/nomicon/src/vec-push-pop.md +++ b/src/doc/nomicon/src/vec/vec-push-pop.md @@ -17,6 +17,7 @@ target address with the bits of the value we provide. No evaluation involved. For `push`, if the old len (before push was called) is 0, then we want to write to the 0th index. So we should offset by the old len. + ```rust,ignore pub fn push(&mut self, elem: T) { if self.len == self.cap { self.grow(); } @@ -41,6 +42,7 @@ of T there. For `pop`, if the old len is 1, we want to read out of the 0th index. So we should offset by the new len. + ```rust,ignore pub fn pop(&mut self) -> Option { if self.len == 0 { diff --git a/src/doc/nomicon/src/vec-raw.md b/src/doc/nomicon/src/vec/vec-raw.md similarity index 97% rename from src/doc/nomicon/src/vec-raw.md rename to src/doc/nomicon/src/vec/vec-raw.md index 3fb62b72cc..f4421db3df 100644 --- a/src/doc/nomicon/src/vec-raw.md +++ b/src/doc/nomicon/src/vec/vec-raw.md @@ -8,6 +8,7 @@ time to perform some logic compression. We're going to abstract out the `(ptr, cap)` pair and give them the logic for allocating, growing, and freeing: + ```rust,ignore struct RawVec { ptr: NonNull, @@ -76,6 +77,7 @@ impl Drop for RawVec { And change Vec as follows: + ```rust,ignore pub struct Vec { buf: RawVec, @@ -114,6 +116,7 @@ impl Drop for Vec { And finally we can really simplify IntoIter: + ```rust,ignore pub struct IntoIter { _buf: RawVec, // we don't actually care about this. Just need it to live. diff --git a/src/doc/nomicon/src/vec-zsts.md b/src/doc/nomicon/src/vec/vec-zsts.md similarity index 98% rename from src/doc/nomicon/src/vec-zsts.md rename to src/doc/nomicon/src/vec/vec-zsts.md index d1b8fe85e7..3469f0c9ff 100644 --- a/src/doc/nomicon/src/vec-zsts.md +++ b/src/doc/nomicon/src/vec/vec-zsts.md @@ -13,9 +13,6 @@ zero-sized types. We need to be careful of two things: Thankfully we abstracted out pointer-iterators and allocating handling into `RawValIter` and `RawVec` respectively. How mysteriously convenient. - - - ## Allocating Zero-Sized Types So if the allocator API doesn't support zero-sized allocations, what on earth @@ -32,6 +29,7 @@ overflow for zero-sized types. Due to our current architecture, all this means is writing 3 guards, one in each method of `RawVec`. + ```rust,ignore impl RawVec { fn new() -> Self { @@ -103,9 +101,6 @@ impl Drop for RawVec { That's it. We support pushing and popping zero-sized types now. Our iterators (that aren't provided by slice Deref) are still busted, though. - - - ## Iterating Zero-Sized Types Zero-sized offsets are no-ops. This means that our current design will always @@ -113,6 +108,7 @@ initialize `start` and `end` as the same value, and our iterators will yield nothing. The current solution to this is to cast the pointers to integers, increment, and then cast them back: + ```rust,ignore impl RawValIter { unsafe fn new(slice: &[T]) -> Self { @@ -136,6 +132,7 @@ Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll basically be treating the two pointers as if they point to bytes, we'll just map size 0 to divide by 1. + ```rust,ignore impl Iterator for RawValIter { type Item = T; diff --git a/src/doc/nomicon/src/vec.md b/src/doc/nomicon/src/vec/vec.md similarity index 100% rename from src/doc/nomicon/src/vec.md rename to src/doc/nomicon/src/vec/vec.md diff --git a/src/doc/nomicon/src/what-unsafe-does.md b/src/doc/nomicon/src/what-unsafe-does.md index c82c70c678..6a3c79f3e7 100644 --- a/src/doc/nomicon/src/what-unsafe-does.md +++ b/src/doc/nomicon/src/what-unsafe-does.md @@ -24,22 +24,22 @@ language cares about is preventing the following things: not support * Producing invalid values (either alone or as a field of a compound type such as `enum`/`struct`/array/tuple): - * a `bool` that isn't 0 or 1 - * an `enum` with an invalid discriminant - * a null `fn` pointer - * a `char` outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF] - * a `!` (all values are invalid for this type) - * an integer (`i*`/`u*`), floating point value (`f*`), or raw pointer read from - [uninitialized memory][], or uninitialized memory in a `str`. - * a reference/`Box` that is dangling, unaligned, or points to an invalid value. - * a wide reference, `Box`, or raw pointer that has invalid metadata: - * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for - `Trait` that matches the actual dynamic trait the pointer or reference points to - * slice metadata is invalid if the length is not a valid `usize` - (i.e., it must not be read from uninitialized memory) - * a type with custom invalid values that is one of those values, such as a - [`NonNull`] that is null. (Requesting custom invalid values is an unstable - feature, but some stable libstd types, like `NonNull`, make use of it.) + * a `bool` that isn't 0 or 1 + * an `enum` with an invalid discriminant + * a null `fn` pointer + * a `char` outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF] + * a `!` (all values are invalid for this type) + * an integer (`i*`/`u*`), floating point value (`f*`), or raw pointer read from + [uninitialized memory][], or uninitialized memory in a `str`. + * a reference/`Box` that is dangling, unaligned, or points to an invalid value. + * a wide reference, `Box`, or raw pointer that has invalid metadata: + * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for + `Trait` that matches the actual dynamic trait the pointer or reference points to + * slice metadata is invalid if the length is not a valid `usize` + (i.e., it must not be read from uninitialized memory) + * a type with custom invalid values that is one of those values, such as a + [`NonNull`] that is null. (Requesting custom invalid values is an unstable + feature, but some stable libstd types, like `NonNull`, make use of it.) "Producing" a value happens any time a value is assigned, passed to a function/primitive operation or returned from a function/primitive operation. diff --git a/src/doc/nomicon/src/working-with-unsafe.md b/src/doc/nomicon/src/working-with-unsafe.md index 935ce580c2..b4b47a1729 100644 --- a/src/doc/nomicon/src/working-with-unsafe.md +++ b/src/doc/nomicon/src/working-with-unsafe.md @@ -84,6 +84,7 @@ impl Vec { This code is simple enough to reasonably audit and informally verify. Now consider adding the following method: + ```rust,ignore fn make_room(&mut self) { // grow the capacity @@ -117,4 +118,3 @@ it prevents us from having to trust all the safe code in the universe from messi with our trusted state. Safety lives! - diff --git a/src/doc/nomicon/theme/nomicon.css b/src/doc/nomicon/theme/nomicon.css new file mode 100644 index 0000000000..1b8c77f4d9 --- /dev/null +++ b/src/doc/nomicon/theme/nomicon.css @@ -0,0 +1,40 @@ +/* +Taken from the reference. +Warnings and notes: +Write the
s on their own line. E.g. +
+Warning: This is bad! +
+*/ +main .warning p { + padding: 10px 20px; + margin: 20px 0; +} + +main .warning p::before { + content: "⚠️ "; +} + +.light main .warning p, +.rust main .warning p { + border: 2px solid red; + background: #ffcece; +} + +.rust main .warning p { + /* overrides previous declaration */ + border-color: #961717; +} + +.coal main .warning p, +.navy main .warning p, +.ayu main .warning p { + background: #542626 +} + +/* Make the links higher contrast on dark themes */ +.coal main .warning p a, +.navy main .warning p a, +.ayu main .warning p a { + color: #80d0d0 +} diff --git a/src/doc/reference.md b/src/doc/reference.md index fdeea17ed1..5e09cdc5cf 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1,4 +1,4 @@ % The Rust Reference has moved We've split up the reference into chapters. Please find it at its new -home [here](reference/index.html). +home [here](https://doc.rust-lang.org/stable/reference/introduction.html). diff --git a/src/doc/reference/book.toml b/src/doc/reference/book.toml index d57c9a1707..b2def92d5c 100644 --- a/src/doc/reference/book.toml +++ b/src/doc/reference/book.toml @@ -8,4 +8,7 @@ additional-css = ["theme/reference.css"] git-repository-url = "https://github.com/rust-lang/reference/" [output.html.redirect] -"/expressions/enum-variant-expr.html" = "struct-expr.html" \ No newline at end of file +"/expressions/enum-variant-expr.html" = "struct-expr.html" + +[rust] +edition = "2018" diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md index a68e466262..37713c0c96 100644 --- a/src/doc/reference/src/attributes/codegen.md +++ b/src/doc/reference/src/attributes/codegen.md @@ -47,7 +47,7 @@ assumed to exist. ## The `target_feature` attribute -The *`target_feature` [attribute]* may be applied to an [unsafe function] to +The *`target_feature` [attribute]* may be applied to a function to enable code generation of that function for specific platform architecture features. It uses the [_MetaListNameValueStr_] syntax with a single key of `enable` whose value is a string of comma-separated feature names to enable. @@ -75,6 +75,9 @@ The following is a list of the available feature names. #### `x86` or `x86_64` +This platform requires that `#[target_feature]` is only applied to [`unsafe` +functions][unsafe function]. + Feature | Implicitly Enables | Description ------------|--------------------|------------------- `aes` | `sse2` | [AES] — Advanced Encryption Standard @@ -128,6 +131,17 @@ Feature | Implicitly Enables | Description [`xsaveopt`]: https://www.felixcloutier.com/x86/xsaveopt [`xsaves`]: https://www.felixcloutier.com/x86/xsaves +#### `wasm32` or `wasm64` + +This platform allows `#[target_feature]` to be applied to both safe and +[`unsafe` functions][unsafe function]. + +Feature | Description +------------|------------------- +`simd128` | [WebAssembly simd proposal][simd128] + +[simd128]: https://github.com/webassembly/simd + ### Additional information See the [`target_feature` conditional compilation option] for selectively diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md index 89f3dfd65d..82ca73cddc 100644 --- a/src/doc/reference/src/destructors.md +++ b/src/doc/reference/src/destructors.md @@ -110,7 +110,7 @@ dropped after any bindings introduced in that parameter's pattern. # println!("drop({})", self.0); # } # } -// Drops the second parameter, then `y`, then the first parameter, then `x` +// Drops `y`, then the second parameter, then `x`, then the first parameter fn patterns_in_parameters( (x, _): (PrintOnDrop, PrintOnDrop), (_, y): (PrintOnDrop, PrintOnDrop), diff --git a/src/doc/reference/src/dynamically-sized-types.md b/src/doc/reference/src/dynamically-sized-types.md index ca40dfec46..1a5fae7270 100644 --- a/src/doc/reference/src/dynamically-sized-types.md +++ b/src/doc/reference/src/dynamically-sized-types.md @@ -11,11 +11,12 @@ types">DSTs. Such types can only be used in certain cases: * Pointers to slices also store the number of elements of the slice. * Pointers to trait objects also store a pointer to a vtable. * DSTs can be provided as - type arguments when a bound of `?Sized`. By default any type parameter - has a `Sized` bound. + type arguments to generic type parameters having the special `?Sized` bound. + They can also be used for associated type definitions when the corresponding associated type declaration has a `?Sized` bound. + By default, any type parameter or associated type has a `Sized` bound, unless it is relaxed using `?Sized`. * Traits may be implemented for DSTs. Unlike type parameters `Self: ?Sized` by default in trait - definitions. + types">DSTs. + Unlike with generic type parameters, `Self: ?Sized` is the default in trait definitions. * Structs may contain a DST as the last field, this makes the struct itself a DST. diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md index aaa25af037..35e7916149 100644 --- a/src/doc/reference/src/expressions.md +++ b/src/doc/reference/src/expressions.md @@ -140,7 +140,7 @@ assert_eq!( ## Place Expressions and Value Expressions Expressions are divided into two main categories: place expressions and -value expressions. Likewise within each expression, operands may occur +value expressions. Likewise, within each expression, operands may occur in either place context or value context. The evaluation of an expression depends both on its own category and the context it occurs within. @@ -173,7 +173,7 @@ The following contexts are *place expression* contexts: 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 +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. @@ -183,7 +183,7 @@ move the value. Only the following place expressions may be moved out of: * The result of [dereferencing][deref] an expression with type [`Box`] and that can also be moved out of. -Moving out of a place expression that evaluates to a local variable, the +When 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. @@ -191,30 +191,30 @@ 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 +[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 [variables] which are not currently borrowed. * [Mutable `static` items]. * [Temporary values]. -* [Fields][field], this evaluates the subexpression in a mutable place +* [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 +* Dereferences of a type that implements `DerefMut`: this then requires that the value being dereferenced is evaluated is a mutable place expression context. -* [Array indexing] of a type that implements `IndexMut`, this +* [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 initialized to that value and the expression +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. @@ -222,7 +222,7 @@ evaluates to that location instead, except if [promoted] to a `static`. The 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 it's operands: +equality directly, because the `==` operator implicitly borrows its operands: ```rust # let c = [1, 2, 3]; diff --git a/src/doc/reference/src/expressions/array-expr.md b/src/doc/reference/src/expressions/array-expr.md index 5f50f09cb4..65b3e24917 100644 --- a/src/doc/reference/src/expressions/array-expr.md +++ b/src/doc/reference/src/expressions/array-expr.md @@ -4,7 +4,7 @@ > **Syntax**\ > _ArrayExpression_ :\ ->    `[` [_InnerAttribute_]\* _ArrayElements_? `]` +>    `[` _ArrayElements_? `]` > > _ArrayElements_ :\ >       [_Expression_] ( `,` [_Expression_] )\* `,`?\ @@ -46,10 +46,6 @@ const EMPTY: Vec = Vec::new(); [EMPTY; 2]; ``` -### Array expression attributes - -[Inner attributes] are allowed directly after the opening bracket of an array expression in the same expression contexts as [attributes on block expressions]. - ## Array and slice indexing expressions > **Syntax**\ @@ -89,11 +85,8 @@ The array index expression can be implemented for types other than arrays and sl [`Copy`]: ../special-types-and-traits.md#copy [IndexMut]: ../../std/ops/trait.IndexMut.html [Index]: ../../std/ops/trait.Index.html -[Inner attributes]: ../attributes.md [_Expression_]: ../expressions.md -[_InnerAttribute_]: ../attributes.md [array]: ../types/array.md -[attributes on block expressions]: block-expr.md#attributes-on-block-expressions [constant expression]: ../const_eval.md#constant-expressions [constant item]: ../items/constant-items.md [literal]: ../tokens.md#literals diff --git a/src/doc/reference/src/expressions/block-expr.md b/src/doc/reference/src/expressions/block-expr.md index deece94caf..a68b27e569 100644 --- a/src/doc/reference/src/expressions/block-expr.md +++ b/src/doc/reference/src/expressions/block-expr.md @@ -109,7 +109,7 @@ Similarly, if `?` propagates an error, that error is propagated as the res Finally, the `break` and `continue` keywords cannot be used to branch out from an async block. Therefore the following is illegal: -```rust,edition2018,compile_fail +```rust,compile_fail loop { async move { break; // This would break out of the loop. diff --git a/src/doc/reference/src/expressions/grouped-expr.md b/src/doc/reference/src/expressions/grouped-expr.md index d76e9a1e07..0ff7e2c90b 100644 --- a/src/doc/reference/src/expressions/grouped-expr.md +++ b/src/doc/reference/src/expressions/grouped-expr.md @@ -2,7 +2,7 @@ > **Syntax**\ > _GroupedExpression_ :\ ->    `(` [_InnerAttribute_]\* [_Expression_] `)` +>    `(` [_Expression_] `)` A *parenthesized expression* wraps a single expression, evaluating to that expression. The syntax for a parenthesized expression is a `(`, then an expression, called the *enclosed operand*, and then a `)`. @@ -39,12 +39,5 @@ assert_eq!( a.f (), "The method f"); assert_eq!((a.f)(), "The field f"); ``` -## Group expression attributes - -[Inner attributes] are allowed directly after the opening parenthesis of a group expression in the same expression contexts as [attributes on block expressions]. - -[Inner attributes]: ../attributes.md [_Expression_]: ../expressions.md -[_InnerAttribute_]: ../attributes.md -[attributes on block expressions]: block-expr.md#attributes-on-block-expressions [place]: ../expressions.md#place-expressions-and-value-expressions diff --git a/src/doc/reference/src/expressions/if-expr.md b/src/doc/reference/src/expressions/if-expr.md index 87b088f784..591437fc98 100644 --- a/src/doc/reference/src/expressions/if-expr.md +++ b/src/doc/reference/src/expressions/if-expr.md @@ -41,7 +41,7 @@ assert_eq!(y, "Bigger"); > **Syntax**\ > _IfLetExpression_ :\ ->    `if` `let` [_Pattern_] `=` [_Expression_]_except struct or lazy boolean operator expression_ +>    `if` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_ > [_BlockExpression_]\ >    (`else` ( > [_BlockExpression_] @@ -148,6 +148,7 @@ if let PAT = ( EXPR || EXPR ) { .. } [_Expression_]: ../expressions.md [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators [_Pattern_]: ../patterns.md +[_Scrutinee_]: match-expr.md [_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018 [`match` expression]: match-expr.md [boolean type]: ../types/boolean.md diff --git a/src/doc/reference/src/expressions/loop-expr.md b/src/doc/reference/src/expressions/loop-expr.md index 8c9ad28024..1ca62095c4 100644 --- a/src/doc/reference/src/expressions/loop-expr.md +++ b/src/doc/reference/src/expressions/loop-expr.md @@ -62,9 +62,10 @@ while i < 10 { > **Syntax**\ > [_PredicatePatternLoopExpression_] :\ ->    `while` `let` [_Pattern_] `=` [_Expression_]_except struct or lazy boolean operator expression_ +>    `while` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_ > [_BlockExpression_] + A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression. If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement. Otherwise, the while expression completes. @@ -264,6 +265,7 @@ In the case a `loop` has an associated `break`, it is not considered diverging, [_BlockExpression_]: block-expr.md [_Expression_]: ../expressions.md [_Pattern_]: ../patterns.md +[_Scrutinee_]: match-expr.md [`match` expression]: match-expr.md [boolean]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee diff --git a/src/doc/reference/src/expressions/match-expr.md b/src/doc/reference/src/expressions/match-expr.md index 53455fa9ac..febf60cc37 100644 --- a/src/doc/reference/src/expressions/match-expr.md +++ b/src/doc/reference/src/expressions/match-expr.md @@ -2,11 +2,14 @@ > **Syntax**\ > _MatchExpression_ :\ ->    `match` [_Expression_]_except struct expression_ `{`\ +>    `match` _Scrutinee_ `{`\ >       [_InnerAttribute_]\*\ >       _MatchArms_?\ >    `}` > +>_Scrutinee_ :\ +>    [_Expression_]_except struct expression_ +> > _MatchArms_ :\ >    ( _MatchArm_ `=>` > ( [_ExpressionWithoutBlock_][_Expression_] `,` diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md index be7c5f12e5..61df3bd64d 100644 --- a/src/doc/reference/src/expressions/operator-expr.md +++ b/src/doc/reference/src/expressions/operator-expr.md @@ -25,6 +25,7 @@ The following things are considered to be overflow: * When `+`, `*` or `-` create a value greater than the maximum value, or less than the minimum value that can be stored. This includes unary `-` on the smallest value of any signed integer type. * Using `/` or `%`, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is `-1`. + These checks occur even when `-C overflow-checks` is disabled, for legacy reasons. * Using `<<` or `>>` where the right-hand argument is greater than or equal to the number of bits in the type of the left-hand argument, or is negative. ## Borrow operators @@ -191,16 +192,18 @@ The operands of all of these operators are evaluated in [value expression contex | `-` | Subtraction | | Subtraction | `std::ops::Sub` | `std::ops::SubAssign` | | `*` | Multiplication | | Multiplication | `std::ops::Mul` | `std::ops::MulAssign` | | `/` | Division* | | Division | `std::ops::Div` | `std::ops::DivAssign` | -| `%` | Remainder | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | +| `%` | Remainder** | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | | `&` | Bitwise AND | [Logical AND] | | `std::ops::BitAnd` | `std::ops::BitAndAssign` | | | | Bitwise OR | [Logical OR] | | `std::ops::BitOr` | `std::ops::BitOrAssign` | | `^` | Bitwise XOR | [Logical XOR] | | `std::ops::BitXor` | `std::ops::BitXorAssign` | | `<<` | Left Shift | | | `std::ops::Shl` | `std::ops::ShlAssign` | -| `>>` | Right Shift** | | | `std::ops::Shr` | `std::ops::ShrAssign` | +| `>>` | Right Shift*** | | | `std::ops::Shr` | `std::ops::ShrAssign` | \* Integer division rounds towards zero. -\*\* Arithmetic right shift on signed integer types, logical right shift on +\*\* Rust uses a remainder defined with [truncating division](https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition). Given `remainder = dividend % divisor`, the remainder will have the same sign as the dividend. + +\*\*\* Arithmetic right shift on signed integer types, logical right shift on unsigned integer types. Here are examples of these operators being used. @@ -340,6 +343,7 @@ reference types and `mut` or `const` in pointer types. #### Numeric cast * Casting between two integers of the same size (e.g. i32 -> u32) is a no-op + (Rust uses 2's complement for negative values of fixed integers) * Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will truncate * Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will @@ -347,10 +351,8 @@ reference types and `mut` or `const` in pointer types. * sign-extend if the source is signed * Casting from a float to an integer will round the float towards zero * `NaN` will return `0` - * Values larger than the maximum integer value will saturate to the - maximum value of the integer type. - * Values smaller than the minimum integer value will saturate to the - minimum value of the integer type. + * Values larger than the maximum integer value, including `INFINITY`, will saturate to the maximum value of the integer type. + * Values smaller than the minimum integer value, including `NEG_INFINITY`, will saturate to the minimum value of the integer type. * Casting from an integer to float will produce the closest possible float \* * if necessary, rounding is according to `roundTiesToEven` mode \*\*\* * on overflow, infinity (of the same sign as the input) is produced diff --git a/src/doc/reference/src/expressions/struct-expr.md b/src/doc/reference/src/expressions/struct-expr.md index ad9fb76f8e..a6958e1f00 100644 --- a/src/doc/reference/src/expressions/struct-expr.md +++ b/src/doc/reference/src/expressions/struct-expr.md @@ -7,7 +7,7 @@ >    | _StructExprUnit_ > > _StructExprStruct_ :\ ->    [_PathInExpression_] `{` [_InnerAttribute_]\* (_StructExprFields_ | _StructBase_)? `}` +>    [_PathInExpression_] `{` (_StructExprFields_ | _StructBase_)? `}` > > _StructExprFields_ :\ >    _StructExprField_ (`,` _StructExprField_)\* (`,` _StructBase_ | `,`?) @@ -21,7 +21,6 @@ > > _StructExprTuple_ :\ >    [_PathInExpression_] `(`\ ->       [_InnerAttribute_]\*\ >       ( [_Expression_] (`,` [_Expression_])\* `,`? )?\ >    `)` > @@ -122,17 +121,10 @@ let a = Gamma; // Gamma unit value. let b = Gamma{}; // Exact same value as `a`. ``` -## Struct expression attributes - -[Inner attributes] are allowed directly after the opening brace or parenthesis of a struct expression in the same expression contexts as [attributes on block expressions]. - [IDENTIFIER]: ../identifiers.md -[Inner attributes]: ../attributes.md [TUPLE_INDEX]: ../tokens.md#tuple-index [_Expression_]: ../expressions.md -[_InnerAttribute_]: ../attributes.md [_PathInExpression_]: ../paths.md#paths-in-expressions -[attributes on block expressions]: block-expr.md#attributes-on-block-expressions [call expression]: call-expr.md [enum variant]: ../items/enumerations.md [if let]: if-expr.md#if-let-expressions diff --git a/src/doc/reference/src/expressions/tuple-expr.md b/src/doc/reference/src/expressions/tuple-expr.md index e9b1654c27..a6ac1c9628 100644 --- a/src/doc/reference/src/expressions/tuple-expr.md +++ b/src/doc/reference/src/expressions/tuple-expr.md @@ -4,7 +4,7 @@ > **Syntax**\ > _TupleExpression_ :\ ->    `(` [_InnerAttribute_]\* _TupleElements_? `)` +>    `(` _TupleElements_? `)` > > _TupleElements_ :\ >    ( [_Expression_] `,` )+ [_Expression_]? @@ -29,10 +29,6 @@ Examples of tuple expressions and their types: | `("x".to_string(), )` | `(String, )` | | `("a", 4usize, true)`| `(&'static str, usize, bool)` | -### Tuple expression attributes - -[Inner attributes] are allowed directly after the opening parenthesis of a tuple expression in the same expression contexts as [attributes on block expressions]. - ## Tuple indexing expressions > **Syntax**\ @@ -70,13 +66,10 @@ assert_eq!(point.1, 0.0); > **Note**: Although arrays and slices also have elements, you must use an [array or slice indexing expression] or a [slice pattern] to access their elements. [_Expression_]: ../expressions.md -[_InnerAttribute_]: ../attributes.md [array or slice indexing expression]: array-expr.md#array-and-slice-indexing-expressions -[attributes on block expressions]: block-expr.md#attributes-on-block-expressions [call expression]: ./call-expr.md [decimal literal]: ../tokens.md#integer-literals [field access expressions]: ./field-expr.html#field-access-expressions -[inner attributes]: ../attributes.md [operands]: ../expressions.md [parenthetical expression]: grouped-expr.md [place expression]: ../expressions.md#place-expressions-and-value-expressions diff --git a/src/doc/reference/src/introduction.md b/src/doc/reference/src/introduction.md index d794ab876c..9038efd8d5 100644 --- a/src/doc/reference/src/introduction.md +++ b/src/doc/reference/src/introduction.md @@ -109,6 +109,8 @@ These conventions are documented here. } ``` + All examples are written for the latest edition unless otherwise stated. + * The grammar and lexical structure is in blockquotes with either "Lexer" or "Syntax" in **bold superscript** as the first line. > **Syntax**\ diff --git a/src/doc/reference/src/items/associated-items.md b/src/doc/reference/src/items/associated-items.md index 0bd9a43fbd..afbcb5cd57 100644 --- a/src/doc/reference/src/items/associated-items.md +++ b/src/doc/reference/src/items/associated-items.md @@ -210,6 +210,7 @@ finally an optional list of trait bounds. 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]. @@ -344,6 +345,7 @@ fn main() { [`Box`]: ../special-types-and-traits.md#boxt [`Pin

`]: ../special-types-and-traits.md#pinp [`Rc`]: ../special-types-and-traits.md#rct +[`Sized`]: ../special-types-and-traits.md#sized [traits]: traits.md [type aliases]: type-aliases.md [inherent implementations]: implementations.md#inherent-implementations diff --git a/src/doc/reference/src/items/functions.md b/src/doc/reference/src/items/functions.md index 9d6ebcde34..f882a24634 100644 --- a/src/doc/reference/src/items/functions.md +++ b/src/doc/reference/src/items/functions.md @@ -227,7 +227,7 @@ use the [`extern` function qualifier](#extern-function-qualifier). Functions may be qualified as async, and this can also be combined with the `unsafe` qualifier: -```rust,edition2018 +```rust async fn regular_example() { } async unsafe fn unsafe_example() { } ``` @@ -240,7 +240,7 @@ An async function is roughly equivalent to a function that returns [`impl Future`] and with an [`async move` block][async-blocks] as its body: -```rust,edition2018 +```rust // Source async fn example(x: &str) -> usize { x.len() @@ -249,7 +249,7 @@ async fn example(x: &str) -> usize { is roughly equivalent to: -```rust,edition2018 +```rust # use std::future::Future; // Desugared fn example<'a>(x: &'a str) -> impl Future + 'a { @@ -285,7 +285,7 @@ resulting function is unsafe to call and (like any async function) returns a future. This future is just an ordinary future and thus an `unsafe` context is not required to "await" it: -```rust,edition2018 +```rust // Returns a future that, when awaited, dereferences `x`. // // Soundness condition: `x` must be safe to dereference until diff --git a/src/doc/reference/src/items/generics.md b/src/doc/reference/src/items/generics.md index 686b6661dd..e9c11ffcfa 100644 --- a/src/doc/reference/src/items/generics.md +++ b/src/doc/reference/src/items/generics.md @@ -230,23 +230,13 @@ parameters. The `for` keyword can be used to introduce [higher-ranked lifetimes]. It only allows [_LifetimeParam_] parameters. -Bounds that don't use the item's parameters or [higher-ranked lifetimes] are -checked when the item is defined. It is an error for such a bound to be false. - -[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic -types when defining the item. It is an error to have `Copy` or `Clone` as a -bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a -bound on a trait object or slice. - -```rust,compile_fail +```rust struct A where T: Iterator, // Could use A instead - T::Item: Copy, - String: PartialEq, + T::Item: Copy, // Bound on an associated type + String: PartialEq, // Bound on `String`, using the type parameter i32: Default, // Allowed, but not useful - i32: Iterator, // Error: the trait bound is not satisfied - [T]: Copy, // Error: the trait bound is not satisfied { f: T, } @@ -303,9 +293,6 @@ struct Foo<#[my_flexible_clone(unbounded)] H> { [path expression]: ../expressions/path-expr.md [raw pointers]: ../types/pointer.md#raw-pointers-const-and-mut [references]: ../types/pointer.md#shared-references- -[`Clone`]: ../special-types-and-traits.md#clone -[`Copy`]: ../special-types-and-traits.md#copy -[`Sized`]: ../special-types-and-traits.md#sized [structs]: structs.md [tuples]: ../types/tuple.md [trait object]: ../types/trait-object.md diff --git a/src/doc/reference/src/items/static-items.md b/src/doc/reference/src/items/static-items.md index 284e78e281..e543b4fa63 100644 --- a/src/doc/reference/src/items/static-items.md +++ b/src/doc/reference/src/items/static-items.md @@ -26,6 +26,54 @@ statics: The initializer expression must be omitted in an [external block], and must be provided for free static items. +## Statics & generics + +A static item defined in a generic scope (for example in a blanket or default +implementation) will result in exactly one static item being defined, as if +the static definition was pulled out of the current scope into the module. +There will *not* be one item per monomorphization. + +This code: + +```rust +use std::sync::atomic::{AtomicUsize, Ordering}; + +trait Tr { + fn default_impl() { + static COUNTER: AtomicUsize = AtomicUsize::new(0); + println!("default_impl: counter was {}", COUNTER.fetch_add(1, Ordering::Relaxed)); + } + + fn blanket_impl(); +} + +struct Ty1 {} +struct Ty2 {} + +impl Tr for T { + fn blanket_impl() { + static COUNTER: AtomicUsize = AtomicUsize::new(0); + println!("blanket_impl: counter was {}", COUNTER.fetch_add(1, Ordering::Relaxed)); + } +} + +fn main() { + ::default_impl(); + ::default_impl(); + ::blanket_impl(); + ::blanket_impl(); +} +``` + +prints + +```text +default_impl: counter was 0 +default_impl: counter was 1 +blanket_impl: counter was 0 +blanket_impl: counter was 1 +``` + ## Mutable statics If a static item is declared with the `mut` keyword, then it is allowed to be diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md index a4b68815b0..26870a0fc3 100644 --- a/src/doc/reference/src/items/traits.md +++ b/src/doc/reference/src/items/traits.md @@ -251,7 +251,8 @@ allowed, but it is deprecated and will become a hard error in the future. In the 2015 edition, the pattern for a trait function or method parameter is optional: -```rust +```rust,edition2015 +// 2015 Edition trait T { fn f(i32); // Parameter identifiers are not required. } @@ -269,7 +270,7 @@ Beginning in the 2018 edition, function or method parameter patterns are no longer optional. Also, all irrefutable patterns are allowed as long as there is a body. Without a body, the limitations listed above are still in effect. -```rust,edition2018 +```rust trait T { fn f1((a, b): (i32, i32)) {} fn f2(_: (i32, i32)); // Cannot use tuple pattern without a body. diff --git a/src/doc/reference/src/items/type-aliases.md b/src/doc/reference/src/items/type-aliases.md index 3d555d5630..ff0cc75f7b 100644 --- a/src/doc/reference/src/items/type-aliases.md +++ b/src/doc/reference/src/items/type-aliases.md @@ -3,6 +3,7 @@ > **Syntax**\ > _TypeAlias_ :\ >    `type` [IDENTIFIER] [_GenericParams_]? +> ( `:` [_TypeParamBounds_] )? > [_WhereClause_]? ( `=` [_Type_] )? `;` A _type alias_ defines a new name for an existing [type]. Type aliases are @@ -20,7 +21,7 @@ let p: Point = (41, 68); A type alias to a tuple-struct or unit-struct cannot be used to qualify that type's constructor: -```rust,edition2018,compile_fail +```rust,compile_fail struct MyStruct(u32); use MyStruct as UseAlias; @@ -33,8 +34,12 @@ 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 with [_TypeParamBounds_] may only specified when used as +an [associated type] in a [trait]. + [IDENTIFIER]: ../identifiers.md [_GenericParams_]: generics.md +[_TypeParamBounds_]: ../trait-bounds.md [_WhereClause_]: generics.md#where-clauses [_Type_]: ../types.md#type-expressions [associated type]: associated-items.md#associated-types diff --git a/src/doc/reference/src/items/use-declarations.md b/src/doc/reference/src/items/use-declarations.md index b29ddcb183..f9695f5a29 100644 --- a/src/doc/reference/src/items/use-declarations.md +++ b/src/doc/reference/src/items/use-declarations.md @@ -144,7 +144,7 @@ fn main() {} > unambiguously select the crate name. This is to retain compatibility with > potential future changes. > -> ```rust,edition2018 +> ```rust > // use std::fs; // Error, this is ambiguous. > use ::std::fs; // Imports from the `std` crate, not the module below. > use self::std::fs as self_fs; // Imports the module below. diff --git a/src/doc/reference/src/macro-ambiguity.md b/src/doc/reference/src/macro-ambiguity.md index 52dc17d88f..01ae288a33 100644 --- a/src/doc/reference/src/macro-ambiguity.md +++ b/src/doc/reference/src/macro-ambiguity.md @@ -20,7 +20,7 @@ of this text is copied, and expanded upon in subsequent RFCs. character. - `simple NT`: a "meta-variable" non-terminal (further discussion below). - `complex NT`: a repetition matching non-terminal, specified via repetition - operators (`\*`, `+`, `?`). + operators (`*`, `+`, `?`). - `token`: an atomic element of a matcher; i.e. identifiers, operators, open/close delimiters, *and* simple NT's. - `token tree`: a tree structure formed from tokens (the leaves), complex @@ -46,12 +46,12 @@ macro_rules! i_am_an_mbe { } ``` -`(start $foo:expr $($i:ident),\* end)` is a matcher. The whole matcher is a +`(start $foo:expr $($i:ident),* end)` is a matcher. The whole matcher is a delimited sequence (with open- and close-delimiters `(` and `)`), and `$foo` and `$i` are simple NT's with `expr` and `ident` as their respective fragment specifiers. -`$(i:ident),\*` is *also* an NT; it is a complex NT that matches a +`$(i:ident),*` is *also* an NT; it is a complex NT that matches a comma-separated repetition of identifiers. The `,` is the separator token for the complex NT; it occurs in between each pair of elements (if any) of the matched fragment. @@ -72,7 +72,7 @@ its additional role as a fragment specifier; but it will be clear from context which interpretation is meant.) "SEP" will range over separator tokens, "OP" over the repetition operators -`\*`, `+`, and `?`, "OPEN"/"CLOSE" over matching token pairs surrounding a +`*`, `+`, and `?`, "OPEN"/"CLOSE" over matching token pairs surrounding a delimited sequence (e.g. `[` and `]`). Greek letters "α" "β" "γ" "δ" stand for potentially empty token-tree sequences. @@ -110,7 +110,7 @@ of FIRST and FOLLOW are described later. 1. For any separated complex NT in a matcher, `M = ... $(tt ...) SEP OP ...`, we must have `SEP` ∈ FOLLOW(`tt ...`). 1. For an unseparated complex NT in a matcher, `M = ... $(tt ...) OP ...`, if - OP = `\*` or `+`, we must have FOLLOW(`tt ...`) ⊇ FIRST(`tt ...`). + OP = `*` or `+`, we must have FOLLOW(`tt ...`) ⊇ FIRST(`tt ...`). The first invariant says that whatever actual token that comes after a matcher, if any, must be somewhere in the predetermined follow set. This ensures that a @@ -202,7 +202,7 @@ first token-tree (if any): * Let SEP\_SET(M) = { SEP } if SEP is present and ε ∈ FIRST(`tt ...`); otherwise SEP\_SET(M) = {}. - * Let ALPHA\_SET(M) = FIRST(`α`) if OP = `\*` or `?` and ALPHA\_SET(M) = {} if + * Let ALPHA\_SET(M) = FIRST(`α`) if OP = `*` or `?` and ALPHA\_SET(M) = {} if OP = `+`. * FIRST(M) = (FIRST(`tt ...`) \\ {ε}) ∪ SEP\_SET(M) ∪ ALPHA\_SET(M). @@ -211,7 +211,7 @@ the possibility that the separator could be a valid first token for M, which happens when there is a separator defined and the repeated fragment could be empty. ALPHA\_SET(M) defines the possibility that the complex NT could be empty, meaning that M's valid first tokens are those of the following token-tree -sequences `α`. This occurs when either `\*` or `?` is used, in which case there +sequences `α`. This occurs when either `*` or `?` is used, in which case there could be zero repetitions. In theory, this could also occur if `+` was used with a potentially-empty repeating fragment, but this is forbidden by the third invariant. @@ -339,7 +339,7 @@ represent simple nonterminals with the given fragment specifier. * FOLLOW(M), for any other M, is defined as the intersection, as t ranges over (LAST(M) \ {ε}), of FOLLOW(t). -The tokens that can begin a type are, as of this writing, {`(`, `[`, `!`, `\*`, +The tokens that can begin a type are, as of this writing, {`(`, `[`, `!`, `*`, `&`, `&&`, `?`, lifetimes, `>`, `>>`, `::`, any non-keyword identifier, `super`, `self`, `Self`, `extern`, `crate`, `$crate`, `_`, `for`, `impl`, `fn`, `unsafe`, `typeof`, `dyn`}, although this list may not be complete because people won't @@ -347,9 +347,9 @@ always remember to update the appendix when new ones are added. Examples of FOLLOW for complex M: - * FOLLOW(`$( $d:ident $e:expr )\*`) = FOLLOW(`$e:expr`) - * FOLLOW(`$( $d:ident $e:expr )\* $(;)\*`) = FOLLOW(`$e:expr`) ∩ ANYTOKEN = FOLLOW(`$e:expr`) - * FOLLOW(`$( $d:ident $e:expr )\* $(;)\* $( f |)+`) = ANYTOKEN + * FOLLOW(`$( $d:ident $e:expr )*`) = FOLLOW(`$e:expr`) + * FOLLOW(`$( $d:ident $e:expr )* $(;)*`) = FOLLOW(`$e:expr`) ∩ ANYTOKEN = FOLLOW(`$e:expr`) + * FOLLOW(`$( $d:ident $e:expr )* $(;)* $( f |)+`) = ANYTOKEN ### Examples of valid and invalid matchers diff --git a/src/doc/reference/src/macros.md b/src/doc/reference/src/macros.md index 65e43330d8..719b9afbcd 100644 --- a/src/doc/reference/src/macros.md +++ b/src/doc/reference/src/macros.md @@ -7,7 +7,8 @@ syntax: `some_extension!(...)`. There are two ways to define new macros: * [Macros by Example] define new syntax in a higher-level, declarative way. -* [Procedural Macros] can be used to implement custom derive. +* [Procedural Macros] define function-like macros, custom derives, and custom + attributes using functions that operate on input tokens. ## Macro Invocation @@ -28,7 +29,7 @@ There are two ways to define new macros: >    | [_SimplePath_] `!` `[` _TokenTree_\* `]` `;`\ >    | [_SimplePath_] `!` `{` _TokenTree_\* `}` -A macro invocation executes a macro at compile time and replaces the +A macro invocation expands a macro at compile time and replaces the invocation with the result of the macro. Macros may be invoked in the following situations: diff --git a/src/doc/reference/src/names/namespaces.md b/src/doc/reference/src/names/namespaces.md index 8d2419b39f..1b07d9ffdc 100644 --- a/src/doc/reference/src/names/namespaces.md +++ b/src/doc/reference/src/names/namespaces.md @@ -104,12 +104,25 @@ imported. +## Sub-namespaces + +The macro namespace is split into two sub-namespaces: one for [bang-style macros] and one for [attributes]. +When an attribute is resolved, any bang-style macros in scope will be ignored. +And conversely resolving a bang-style macro will ignore attribute macros in scope. +This prevents one style from shadowing another. + +For example, the [`cfg` attribute] and the [`cfg` macro] are two different entities with the same name in the macro namespace, but they can still be used in their respective context. + +It is still an error for a [`use` import] to shadow another macro, regardless of their sub-namespaces. + [^rustc-lifetime-shadow]: `rustc` currently warns about shadowing when using the same name for a label and lifetime in the same scope, but it still treats them independently. This is intended as a future-compatibility warning about a possible extension to the language. See [PR #24162](https://github.com/rust-lang/rust/pull/24162). +[`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute +[`cfg` macro]: ../conditional-compilation.md#the-cfg-macro [`for`]: ../expressions/loop-expr.md#iterator-loops [`if let`]: ../expressions/if-expr.md#if-let-expressions [`let`]: ../statements.md#let-statements @@ -117,11 +130,14 @@ imported. [`match`]: ../expressions/match-expr.md [`Self` constructors]: ../paths.md#self-1 [`Self` type]: ../paths.md#self-1 +[`use` import]: ../items/use-declarations.md [`while let`]: ../expressions/loop-expr.md#predicate-pattern-loops [Associated const declarations]: ../items/associated-items.md#associated-constants [Associated function declarations]: ../items/associated-items.md#associated-functions-and-methods [Associated type declarations]: ../items/associated-items.md#associated-types [Attribute macros]: ../procedural-macros.md#attribute-macros +[attributes]: ../attributes.md +[bang-style macros]: ../macros.md [boolean]: ../types/boolean.md [Built-in attributes]: ../attributes.md#built-in-attributes-index [closure parameters]: ../expressions/closure-expr.md diff --git a/src/doc/reference/src/paths.md b/src/doc/reference/src/paths.md index 2bf921c8d5..695252f5fa 100644 --- a/src/doc/reference/src/paths.md +++ b/src/doc/reference/src/paths.md @@ -172,6 +172,16 @@ the path must resolve to an item. > crates in the [extern prelude]. That is, they must be followed by the name of a crate. ```rust +pub fn foo() { + // In the 2018 edition, this accesses `std` via the extern prelude. + // In the 2015 edition, this accesses `std` via the crate root. + let now = ::std::time::Instant::now(); + println!("{:?}", now); +} +``` + +```rust,edition2015 +// 2015 Edition mod a { pub fn foo() {} } @@ -353,11 +363,11 @@ mod without { // ::without fn g(&self) {} // None } - impl OtherTrait for ::a::Struct { + impl OtherTrait for crate::a::Struct { fn g(&self) {} // None } - impl ::a::Trait for OtherStruct { + impl crate::a::Trait for OtherStruct { fn f(&self) {} // None } } diff --git a/src/doc/reference/src/special-types-and-traits.md b/src/doc/reference/src/special-types-and-traits.md index 810be00058..6d054aae2c 100644 --- a/src/doc/reference/src/special-types-and-traits.md +++ b/src/doc/reference/src/special-types-and-traits.md @@ -134,10 +134,10 @@ UnwindSafe>` is a valid type. ## `Sized` -The [`Sized`] trait indicates that the size of this type is known at -compile-time; that is, it's not a [dynamically sized type]. [Type parameters] -are `Sized` by default. `Sized` is always implemented automatically by the -compiler, not by [implementation items]. +The [`Sized`] trait indicates that the size of this type is known at compile-time; that is, it's not a [dynamically sized type]. +[Type parameters] are `Sized` by default, as are [associated types]. +`Sized` is always implemented automatically by the compiler, not by [implementation items]. +These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound. [`Arc`]: ../std/sync/struct.Arc.html [`Box`]: ../std/boxed/struct.Box.html @@ -160,6 +160,7 @@ compiler, not by [implementation items]. [`Unpin`]: ../std/marker/trait.Unpin.html [Arrays]: types/array.md +[associated types]: items/associated-items.md#associated-types [call expressions]: expressions/call-expr.md [deref coercions]: type-coercions.md#coercion-types [dereference operator]: expressions/operator-expr.md#the-dereference-operator diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md index 06cd9513e5..8d9c21d7db 100644 --- a/src/doc/reference/src/statements.md +++ b/src/doc/reference/src/statements.md @@ -62,7 +62,8 @@ 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. +from the point of declaration until the end of the enclosing block scope, +except when they are shadowed by another variable declaration. ## Expression statements diff --git a/src/doc/reference/src/trait-bounds.md b/src/doc/reference/src/trait-bounds.md index 4d1d5d345c..cc3f4a1bde 100644 --- a/src/doc/reference/src/trait-bounds.md +++ b/src/doc/reference/src/trait-bounds.md @@ -47,7 +47,7 @@ trait is implemented for a type. For example, given `Ty: Trait` ```rust # type Surface = i32; trait Shape { - fn draw(&self, Surface); + fn draw(&self, surface: Surface); fn name() -> &'static str; } @@ -73,19 +73,38 @@ fn name_figure( } ``` +Bounds that don't use the item's parameters or [higher-ranked lifetimes] are checked when the item is defined. +It is an error for such a bound to be false. + +[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic types when using the item, even if the use does not provide a concrete type. +It is an error to have `Copy` or `Clone` as a bound on a mutable reference, [trait object], or [slice]. +It is an error to have `Sized` as a bound on a trait object or slice. + +```rust,compile_fail +struct A<'a, T> +where + i32: Default, // Allowed, but not useful + i32: Iterator, // Error: `i32` is not an iterator + &'a mut T: Copy, // (at use) Error: the trait bound is not satisfied + [T]: Sized, // (at use) Error: size cannot be known at compilation +{ + f: &'a T, +} +struct UsesA<'a, T>(A<'a, T>); +``` + Trait and lifetime bounds are also used to name [trait objects]. ## `?Sized` -`?` is only used to declare that the [`Sized`] trait may not be -implemented for a type parameter or associated type. `?Sized` may -not be used as a bound for other types. +`?` is only used to relax the implicit [`Sized`] trait bound for [type parameters] or [associated types]. +`?Sized` may not be used as a bound for other types. ## Lifetime bounds -Lifetime bounds can be applied to types or other lifetimes. The bound `'a: 'b` -is usually read as `'a` *outlives* `'b`. `'a: 'b` means that `'a` lasts longer -than `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid. +Lifetime bounds can be applied to types or to other lifetimes. +The bound `'a: 'b` is usually read as `'a` *outlives* `'b`. +`'a: 'b` means that `'a` lasts at least as long as `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid. ```rust fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b { @@ -94,9 +113,8 @@ fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b { } ``` -`T: 'a` means that all lifetime parameters of `T` outlive `'a`. For example if -`'a` is an unconstrained lifetime parameter then `i32: 'static` and -`&'static str: 'a` are satisfied but `Vec<&'a ()>: 'static` is not. +`T: 'a` means that all lifetime parameters of `T` outlive `'a`. +For example, if `'a` is an unconstrained lifetime parameter, then `i32: 'static` and `&'static str: 'a` are satisfied, but `Vec<&'a ()>: 'static` is not. ## Higher-ranked trait bounds @@ -117,8 +135,7 @@ impl<'a> PartialEq for &'a T { and could then be used to compare a `&'a T` with any lifetime to an `i32`. -Only a higher-ranked bound can be used here as the lifetime of the reference is -shorter than a lifetime parameter on the function: +Only a higher-ranked bound can be used here, because the lifetime of the reference is shorter than any possible lifetime parameter on the function: ```rust fn call_on_ref_zero(f: F) where for<'a> F: Fn(&'a i32) { @@ -127,7 +144,7 @@ fn call_on_ref_zero(f: F) where for<'a> F: Fn(&'a i32) { } ``` -Higher-ranked lifetimes may also be specified just before the trait, the only +Higher-ranked lifetimes may also be specified just before the trait: the only difference is the scope of the lifetime parameter, which extends only to the end of the following trait instead of the whole bound. This function is equivalent to the last one. @@ -142,11 +159,18 @@ fn call_on_ref_zero(f: F) where F: for<'a> Fn(&'a i32) { [LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels [_GenericParams_]: items/generics.md [_TypePath_]: paths.md#paths-in-types +[`Clone`]: special-types-and-traits.md#clone +[`Copy`]: special-types-and-traits.md#copy [`Sized`]: special-types-and-traits.md#sized +[arrays]: types/array.md [associated types]: items/associated-items.md#associated-types [supertraits]: items/traits.md#supertraits [generic]: items/generics.md +[higher-ranked lifetimes]: #higher-ranked-trait-bounds +[slice]: types/slice.md [Trait]: items/traits.md#trait-bounds +[trait object]: types/trait-object.md [trait objects]: types/trait-object.md +[type parameters]: types/parameters.md [where clause]: items/generics.md#where-clauses diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index bacd478e3c..22b5752bb5 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -70,9 +70,9 @@ at least equal to the size and alignment of a pointer. ## Array Layout -Arrays are laid out so that the `nth` element of the array is offset from the -start of the array by `n * the size of the type` bytes. An array of `[T; n]` -has a size of `size_of::() * n` and the same alignment of `T`. +An array of `[T; N]` has a size of `size_of::() * N` and the same alignment +of `T`. Arrays are laid out so that the zero-based `nth` element of the array +is offset from the start of the array by `n * size_of::()` bytes. ## Slice Layout diff --git a/src/doc/reference/src/types/closure.md b/src/doc/reference/src/types/closure.md index dfdd4ea57f..7cfb3b059f 100644 --- a/src/doc/reference/src/types/closure.md +++ b/src/doc/reference/src/types/closure.md @@ -49,10 +49,10 @@ f(Closure{s: s, t: &t}); The compiler prefers to capture a closed-over variable by immutable borrow, followed by unique immutable borrow (see below), by mutable borrow, and finally -by move. It will pick the first choice of these that allows the closure to -compile. The choice is made only with regards to the contents of the closure -expression; the compiler does not take into account surrounding code, such as -the lifetimes of involved variables. +by move. It will pick the first choice of these that is compatible with how the +captured variable is used inside the closure body. The compiler does not take +surrounding code into account, such as the lifetimes of involved variables, or +of the closure itself. If the `move` keyword is used, then all captures are by move or, for `Copy` types, by copy, regardless of whether a borrow would work. The `move` keyword is diff --git a/src/doc/reference/src/visibility-and-privacy.md b/src/doc/reference/src/visibility-and-privacy.md index 84bb4fb86c..209b9bcf69 100644 --- a/src/doc/reference/src/visibility-and-privacy.md +++ b/src/doc/reference/src/visibility-and-privacy.md @@ -110,7 +110,7 @@ pub fn public_api() {} // Similarly to 'public_api', this module is public so external crates may look // inside of it. pub mod submodule { - use crate_helper_module; + use crate::crate_helper_module; pub fn my_method() { // Any item in the local crate may invoke the helper module's public @@ -161,7 +161,7 @@ to `pub(in self)` or not using `pub` at all. Here's an example: -```rust +```rust,edition2015 pub mod outer_mod { pub mod inner_mod { // This function is visible within `outer_mod` diff --git a/src/doc/rust-by-example/.github/workflows/rbe.yml b/src/doc/rust-by-example/.github/workflows/rbe.yml new file mode 100644 index 0000000000..7d3b19c546 --- /dev/null +++ b/src/doc/rust-by-example/.github/workflows/rbe.yml @@ -0,0 +1,42 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: Run tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + + - name: Update rustup + run: rustup self update + + - name: Install Rust + run: | + rustup set profile minimal + rustup toolchain install stable -c rust-docs + rustup default stable + + - name: Install mdbook + run: | + mkdir bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + echo "$(pwd)/bin" >> ${GITHUB_PATH} + + - name: Report versions + run: | + rustup --version + rustc -Vv + mdbook --version + + - name: Run tests + run: mdbook test + + - name: Build HTML + run: mdbook build + + - name: Upload Artifact + uses: actions/upload-artifact@v1 + with: + name: rust-by-example + path: book diff --git a/src/doc/rust-by-example/src/custom_types/structs.md b/src/doc/rust-by-example/src/custom_types/structs.md index 90dac52b6f..508cff2314 100644 --- a/src/doc/rust-by-example/src/custom_types/structs.md +++ b/src/doc/rust-by-example/src/custom_types/structs.md @@ -3,7 +3,8 @@ There are three types of structures ("structs") that can be created using the `struct` keyword: -* Tuple structs, which are, basically, named tuples. The classic [C structs][c_struct] +* Tuple structs, which are, basically, named tuples. +* The classic [C structs][c_struct] * Unit structs, which are field-less, are useful for generics. ```rust,editable diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md index 30ae68f95c..03f81427bd 100644 --- a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_tuple.md @@ -13,7 +13,7 @@ fn main() { // Destructure the second and third elements (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z), (1, ..) => println!("First is `1` and the rest doesn't matter"), - // `..` can be the used ignore the rest of the tuple + // `..` can be used to ignore the rest of the tuple _ => println!("It doesn't matter what they are"), // `_` means don't bind the value to a variable } diff --git a/src/doc/rust-by-example/src/fn/methods.md b/src/doc/rust-by-example/src/fn/methods.md index 8e8c10ced4..bd5d997f0d 100644 --- a/src/doc/rust-by-example/src/fn/methods.md +++ b/src/doc/rust-by-example/src/fn/methods.md @@ -1,8 +1,9 @@ -# Methods +# Associated functions & Methods -Methods are functions attached to objects. These methods have access to the -data of the object and its other methods via the `self` keyword. Methods are -defined under an `impl` block. +Some functions are connected to a particular type. These come in two forms: +associated functions, and methods. Associated functions are functions that +are defined on a type generally, while methods are associated functions that are +called on a particular instance of a type. ```rust,editable struct Point { @@ -10,16 +11,18 @@ struct Point { y: f64, } -// Implementation block, all `Point` methods go in here +// Implementation block, all `Point` associated functions & methods go in here impl Point { - // This is a static method - // Static methods don't need to be called by an instance - // These methods are generally used as constructors + // This is an "associated function" because this function is associated with + // a particular type, that is, Point. + // + // Associated functions don't need to be called with an instance. + // These functions are generally used like constructors. fn origin() -> Point { Point { x: 0.0, y: 0.0 } } - // Another static method, taking two arguments: + // Another associated function, taking two arguments: fn new(x: f64, y: f64) -> Point { Point { x: x, y: y } } @@ -31,7 +34,7 @@ struct Rectangle { } impl Rectangle { - // This is an instance method + // This is a method // `&self` is sugar for `self: &Self`, where `Self` is the type of the // caller object. In this case `Self` = `Rectangle` fn area(&self) -> f64 { @@ -80,12 +83,12 @@ impl Pair { fn main() { let rectangle = Rectangle { - // Static methods are called using double colons + // Associated functions are called using double colons p1: Point::origin(), p2: Point::new(3.0, 4.0), }; - // Instance methods are called using the dot operator + // Methods are called using the dot operator // Note that the first argument `&self` is implicitly passed, i.e. // `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)` println!("Rectangle perimeter: {}", rectangle.perimeter()); @@ -112,4 +115,4 @@ fn main() { //pair.destroy(); // TODO ^ Try uncommenting this line } -``` \ No newline at end of file +``` diff --git a/src/doc/rust-by-example/src/std_misc/file/create.md b/src/doc/rust-by-example/src/std_misc/file/create.md index 16eba89747..709213c9df 100644 --- a/src/doc/rust-by-example/src/std_misc/file/create.md +++ b/src/doc/rust-by-example/src/std_misc/file/create.md @@ -1,6 +1,6 @@ # `create` -The `create` static method opens a file in write-only mode. If the file +The `create` function opens a file in write-only mode. If the file already existed, the old content is destroyed. Otherwise, a new file is created. diff --git a/src/doc/rust-by-example/src/std_misc/file/open.md b/src/doc/rust-by-example/src/std_misc/file/open.md index 16fdb2c91c..77a5470fa3 100644 --- a/src/doc/rust-by-example/src/std_misc/file/open.md +++ b/src/doc/rust-by-example/src/std_misc/file/open.md @@ -1,6 +1,6 @@ # `open` -The `open` static method can be used to open a file in read-only mode. +The `open` function can be used to open a file in read-only mode. A `File` owns a resource, the file descriptor and takes care of closing the file when it is `drop`ed. 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 eb83df8e10..4b10cfa899 100644 --- a/src/doc/rust-by-example/src/std_misc/path.md +++ b/src/doc/rust-by-example/src/std_misc/path.md @@ -19,7 +19,7 @@ fn main() { // Create a `Path` from an `&'static str` let path = Path::new("."); - // The `display` method returns a `Show`able structure + // The `display` method returns a `Display`able structure let _display = path.display(); // `join` merges a path with a byte container using the OS specific diff --git a/src/doc/rust-by-example/src/testing/integration_testing.md b/src/doc/rust-by-example/src/testing/integration_testing.md index a4345ae945..0ac77588c3 100644 --- a/src/doc/rust-by-example/src/testing/integration_testing.md +++ b/src/doc/rust-by-example/src/testing/integration_testing.md @@ -47,8 +47,8 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` -Each Rust source file in `tests` directory is compiled as a separate crate. One -way of sharing some code between integration tests is making module with public +Each Rust source file in the `tests` directory is compiled as a separate crate. One +way of sharing some code between integration tests is making a module with public functions, importing and using it within tests. File `tests/common.rs`: diff --git a/src/doc/rust-by-example/src/trait.md b/src/doc/rust-by-example/src/trait.md index 7878d4742b..d4d4094683 100644 --- a/src/doc/rust-by-example/src/trait.md +++ b/src/doc/rust-by-example/src/trait.md @@ -12,10 +12,10 @@ methods from `Animal` with a `Sheep`. struct Sheep { naked: bool, name: &'static str } trait Animal { - // Static method signature; `Self` refers to the implementor type. + // Associated function signature; `Self` refers to the implementor type. fn new(name: &'static str) -> Self; - // Instance method signatures; these will return a string. + // Method signatures; these will return a string. fn name(&self) -> &'static str; fn noise(&self) -> &'static str; @@ -77,4 +77,4 @@ fn main() { dolly.shear(); dolly.talk(); } -``` \ No newline at end of file +``` diff --git a/src/doc/rust.css b/src/doc/rust.css index 06f4df9a9b..d33ab03260 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -1,68 +1,15 @@ -@font-face { - font-family: 'Fira Sans'; - font-style: normal; - font-weight: 400; - src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff'); - font-display: swap; -} -@font-face { - font-family: 'Fira Sans'; - font-style: normal; - font-weight: 500; - src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff'); - font-display: swap; -} -@font-face { - font-family: 'Source Serif Pro'; - font-style: normal; - font-weight: 400; - src: local('Source Serif Pro'), url("SourceSerifPro-Regular.ttf.woff") format('woff'); - font-display: swap; -} -@font-face { - font-family: 'Source Serif Pro'; - font-style: italic; - font-weight: 400; - src: url("SourceSerifPro-It.ttf.woff") format('woff'); - font-display: swap; -} -@font-face { - font-family: 'Source Serif Pro'; - font-style: normal; - font-weight: 700; - src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.ttf.woff") format('woff'); - font-display: swap; -} -@font-face { - font-family: 'Source Code Pro'; - font-style: normal; - font-weight: 400; - /* Avoid using locally installed font because bad versions are in circulation: - * see https://github.com/rust-lang/rust/issues/24355 */ - src: url("SourceCodePro-Regular.woff") format('woff'); - font-display: swap; -} - -*:not(body) { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - /* General structure */ body { - background-color: white; margin: 0 auto; padding: 0 15px; - font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif; font-size: 18px; color: #333; line-height: 1.428571429; - -webkit-font-feature-settings: "kern", "liga"; - -moz-font-feature-settings: "kern", "liga"; - font-feature-settings: "kern", "liga"; + -webkit-box-sizing: unset; + -moz-box-sizing: unset; + box-sizing: unset; } @media (min-width: 768px) { body { @@ -70,11 +17,7 @@ body { } } -h1, h2, h3, h4, h5, h6, nav, #versioninfo { - font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; -} -h1, h2, h3, h4, h5, h6 { - color: black; +h2, h3, h4, h5, h6 { font-weight: 400; line-height: 1.1; } @@ -84,6 +27,7 @@ h1, h2, h3 { } h1 { margin-bottom: 20px; + line-height: 1.1; } h4, h5, h6 { margin-top: 12px; @@ -91,6 +35,7 @@ h4, h5, h6 { padding: 5px 10px; } h5, h6 { + color: black; text-decoration: underline; } @@ -115,6 +60,7 @@ h3 { } h4 { font-size: 22px; + border-bottom: none; } h5 { font-size: 20px; @@ -185,19 +131,15 @@ a:hover, a:active { h1 a:link, h1 a:visited, h2 a:link, h2 a:visited, h3 a:link, h3 a:visited, h4 a:link, h4 a:visited, h5 a:link, h5 a:visited {color: black;} -h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, -h5 a:hover {text-decoration: none;} /* Code */ pre, code { - font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace; word-wrap: break-word; } pre { border-left: 2px solid #eee; white-space: pre-wrap; - padding: 14px; padding-right: 0; margin: 20px 0; font-size: 15px; @@ -221,19 +163,6 @@ a > code { color: #8D1A38; } -/* 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, pre.rust .attribute .ident { 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; } - -/* The rest */ - #versioninfo { text-align: center; margin: 0.5em; @@ -275,9 +204,6 @@ blockquote p:last-child { margin-bottom: 0; } -ul, ol { - padding-left: 25px; -} ul ul, ol ul, ul ol, ol ol { margin-bottom: 0; } @@ -332,22 +258,8 @@ table th { /* Code snippets */ -.example-wrap { position: relative; } -pre.rust { position: relative; } a.test-arrow { - background-color: rgba(78, 139, 202, 0.2); - display: inline-block; - position: absolute; - color: #f5f5f5; - padding: 5px 10px 5px 10px; - border-radius: 5px; - font-size: 130%; - top: 5px; - right: 5px; -} -a.test-arrow:hover{ - background-color: #4e8bca; - text-decoration: none; + color: #f5f5f5 } .unstable-feature { @@ -416,19 +328,6 @@ a.test-arrow:hover{ position: relative; } -.information { - position: absolute; - left: -25px; - margin-top: 7px; - z-index: 1; -} - -.tooltip { - position: relative; - display: inline-block; - cursor: pointer; -} - .tooltip .tooltiptext { width: 120px; display: none; diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index 99502bcc66..006ea3231b 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -14,6 +14,9 @@ for the docs you're looking for instead of reading them top to bottom. [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc +For documentation on developing the standard library, see +[`std-dev-guide`](https://std-dev-guide.rust-lang.org/). + ### Contributing to the guide The guide is useful today, but it has a lot of work still to go. diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 3f14c26421..5fa2676012 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -81,6 +81,7 @@ - [Panic Implementation](./panic-implementation.md) - [AST Validation](./ast-validation.md) - [Feature Gate Checking](./feature-gate-ck.md) + - [Lang Items](./lang-items.md) - [The HIR (High-level IR)](./hir.md) - [Lowering AST to HIR](./lowering.md) - [Debugging](./hir-debugging.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 d12f5a7a34..3fa397ae40 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -4,31 +4,31 @@ This guide is meant to help document how rustc – the Rust compiler – works, as well as to help new contributors get involved in rustc development. -There are six parts to this guide: +There are seven parts to this guide: 1. [Building and debugging `rustc`][p1]: Contains information that should be useful no matter how you are contributing, about building, debugging, profiling, etc. -2. [Contributing to `rustc`][p1-5]: Contains information that should be useful - no matter how you are contributing, about procedures for contribution, - stabilizing features, etc. -2. [High-Level Compiler Architecture][p2]: Discusses the high-level +2. [Contributing to `rustc`][p2]: Contains information that should be useful + no matter how you are contributing, about procedures for contribution, using git + and Github, stabilizing features, etc. +3. [High-Level Compiler Architecture][p3]: Discusses the high-level architecture of the compiler and stages of the compile process. -3. [Source Code Representation][p3]: Describes the process of taking raw source code from the user and +4. [Source Code Representation][p4]: Describes the process of taking raw source code from the user and transforming it into various forms that the compiler can work with easily. -4. [Analysis][p4]: discusses the analyses that the compiler uses to check various +5. [Analysis][p5]: discusses the analyses that the compiler uses to check various properties of the code and inform later stages of the compile process (e.g., type checking). -5. [From MIR to Binaries][p5]: How linked executable machine code is generated. -6. [Appendices][app] at the end with useful reference information. There are a +6. [From MIR to Binaries][p6]: How linked executable machine code is generated. +7. [Appendices][p7] at the end with useful reference information. There are a few of these with different information, including a glossary. [p1]: ./getting-started.md -[p1-5]: ./compiler-team.md -[p2]: ./part-2-intro.md -[p3]: ./part-3-intro.md -[p4]: ./part-4-intro.md -[p5]: ./part-5-intro.md -[app]: ./appendix/background.md +[p2]: ./contributing.md +[p3]: ./part-2-intro.md +[p4]: ./part-3-intro.md +[p5]: ./part-4-intro.md +[p6]: ./part-5-intro.md +[p7]: ./appendix/background.md ### Constant change @@ -60,8 +60,10 @@ You might also find the following sites useful: - [Forge] -- contains documentation about rust infrastructure, team procedures, and more - [compiler-team] -- the home-base for the rust compiler team, with description of the team procedures, active working groups, and the team calendar. +- [std-dev-guide] -- a similar guide for developing the standard library. [GitHub repository]: https://github.com/rust-lang/rustc-dev-guide/ [rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ [Forge]: https://forge.rust-lang.org/ [compiler-team]: https://github.com/rust-lang/compiler-team/ +[std-dev-guide]: https://std-dev-guide.rust-lang.org/ diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index eae5758f43..8e5d5b3947 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -1,94 +1,95 @@ # Glossary -Term | Meaning ------------------------------------------------|-------- -arena/arena allocation | An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info. -AST | The abstract syntax tree produced by the `rustc_ast` crate; reflects user syntax very closely. -binder | A "binder" is a place where a variable or type is declared; for example, the `` is a binder for the generic type parameter `T` in `fn foo(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound). -BodyId | An identifier that refers to a specific body (definition of a function or constant) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). -bound variable | A "bound variable" is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.md#free-vs-bound) -codegen | The code to translate MIR into LLVM IR. -codegen unit | When we produce LLVM IR, we group the Rust code into a number of codegen units (sometimes abbreviated as CGUs). Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. ([see more](../backend/codegen.md)) -completeness | A technical term in type theory, it means that every type-safe program also type-checks. Having both soundness and completeness is very hard, and usually soundness is more important. (see "soundness"). -control-flow graph | A representation of the control-flow of a program; see [the background chapter for more](./background.md#cfg) -CTFE | Short for Compile-Time Function Evaluation, this is the ability of the compiler to evaluate `const fn`s at compile time. This is part of the compiler's constant evaluation system. ([see more](../const-eval.md)) -cx | We tend to use "cx" as an abbreviation for context. See also `tcx`, `infcx`, etc. -ctxt | We also use "ctxt" as an abbreviation for context, e.g. [`TyCtxt`](#TyCtxt). See also [cx](#cx) or [tcx](#tcx). -DAG | A directed acyclic graph is used during compilation to keep track of dependencies between queries. ([see more](../queries/incremental-compilation.md)) -data-flow analysis | A static analysis that figures out what properties are true at each point in the control-flow of a program; see [the background chapter for more](./background.md#dataflow). -DeBruijn Index | A technique for describing which binder a variable is bound by using only integers. It has the benefit that it is invariant under variable renaming. ([see more](./background.md#what-is-a-debruijn-index)) -DefId | An index identifying a definition (see `rustc_middle/src/hir/def_id.rs`). Uniquely identifies a `DefPath`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). -discriminant | The underlying value associated with an enum variant or generator state to indicate it as "active" (but not to be confused with its ["variant index"](#variant-idx)). At runtime, the discriminant of the active variant is encoded in the [tag](#tag). -double pointer | A pointer with additional metadata. See "fat pointer" for more. -drop glue | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types. -DST | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`). -early-bound lifetime | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions)) -empty type | see "uninhabited type". -fat pointer | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers". -free variable | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound) -generics | The set of generic type parameters defined on a type or item. -HIR | The High-level IR, created by lowering and desugaring the AST. ([see more](../hir.md)) -HirId | Identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). -HIR map | The HIR map, accessible via `tcx.hir()`, allows you to quickly navigate the HIR and convert between various forms of identifiers. -ICE | Short for internal compiler error, this is when the compiler crashes. -ICH | Short for incremental compilation hash, these are used as fingerprints for things such as HIR and crate metadata, to check if changes have been made. This is useful in incremental compilation to see if part of a crate has changed and should be recompiled. -infcx | The type inference context (`InferCtxt`). (see `rustc_middle::infer`) -inference variable | 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. -intern | 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. -intrinsic | 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)) -IR | 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. -IRLO | `IRLO` or `irlo` is sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org). -item | A kind of "definition" in the language, such as a static, const, use statement, module, struct, etc. Concretely, this corresponds to the `Item` type. -lang item | Items that represent concepts intrinsic to the language itself, such as special built-in traits like `Sync` and `Send`; or traits representing operations such as `Add`; or functions that are called by the compiler. ([see more](https://doc.rust-lang.org/1.9.0/book/lang-items.html)) -late-bound lifetime | A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions)) -local crate | The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate. -LTO | Short for Link-Time Optimizations, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto]. -[LLVM] | (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. -memoization | 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. -MIR | The Mid-level IR that is created after type-checking for use by borrowck and codegen. ([see more](../mir/index.md)) -miri | An interpreter for MIR used for constant evaluation. ([see more](../miri.md)) -monomorphization | 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`, 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`, a copy for `Vec`, etc). -normalize | 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). -newtype | 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. -niche | Invalid bit patterns for a type *that can be used* for layout optimizations. Some types cannot have certain bit patterns. For example, the `NonZero*` integers or the reference `&T` cannot be represented by a 0 bitstring. This means the compiler can perform layout optimizations by taking advantage of the invalid "niche value". An example application for this is the [*Discriminant elision on `Option`-like enums*](https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html#discriminant-elision-on-option-like-enums), which allows using a type's niche as the ["tag"](#tag) for an `enum` without requiring a separate field. -NLL | Short for [non-lexical lifetimes](../borrow_check/region_inference.md), this is an extension to Rust's borrowing system to make it be based on the control-flow graph. -node-id or NodeId | An index identifying a particular node in the AST or HIR; gradually being phased out and replaced with `HirId`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). -obligation | Something that must be proven by the trait system. ([see more](../traits/resolution.md)) -placeholder | **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow_check/region_inference/placeholders_and_universes.md) for more details. -point | Used in the NLL analysis to refer to some particular location in the MIR; typically used to refer to a node in the control-flow graph. -polymorphize | An optimization that avoids unnecessary monomorphisation. ([see more](../backend/monomorph.md#polymorphization)) -projection | A general term for a "relative path", e.g. `x.f` is a "field projection", and `T::Item` is an ["associated type projection"](../traits/goals-and-clauses.md#trait-ref). -promoted constants | Constants extracted from a function and lifted to static scope; see [this section](../mir/index.md#promoted) for more details. -provider | The function that executes a query. ([see more](../query.md)) -quantified | In math or logic, existential and universal quantification are used to ask questions like "is there any type T for which is true?" or "is this true for all types T?"; see [the background chapter for more](./background.md#quantified). -query | A sub-computation during compilation. Query results can be cached in the current session or to disk for incremental compilation. ([see more](../query.md)) -recovery | Recovery refers to handling invalid syntax during parsing (e.g. a missing comma) and continuing to parse the AST. This avoid showing spurious errors to the user (e.g. showing 'missing field' errors when the struct definition contains errors). -region | Another term for "lifetime" often used in the literature and in the borrow checker. -rib | A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md)) -scrutinee

| A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee. -sess | The compiler session, which stores global data used throughout compilation -side tables | Because the AST and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node. -sigil | Like a keyword but composed entirely of non-alphanumeric tokens. For example, `&` is a sigil for references. -soundness | A technical term in type theory. Roughly, if a type system is sound, then a program that type-checks is type-safe. That is, one can never (in safe rust) force a value into a variable of the wrong type. (see "completeness"). -span | A location in the user's source code, used for error reporting primarily. These are like a file-name/line-number/column tuple on steroids: they carry a start/end point, and also track macro expansions and compiler desugaring. All while being packed into a few bytes (really, it's an index into a table). See the Span datatype for more. -substs | The substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap`). -sysroot | The directory for build artifacts that are loaded by the compiler at runtime. ([see more](../building/bootstrapping.html#what-is-a-sysroot)) -tag | The "tag" of an enum/generator encodes the [discriminant](#discriminant) of the active variant/state. Tags can either be "direct" (simply storing the discriminant in a field) or use a ["niche"](#niche). -tcx | The "typing context" (`TyCtxt`), main data structure of the compiler. ([see more](../ty.md)) -`'tcx` | The lifetime of the allocation arenas used by `TyCtxt`. Most data interned during a compilation session will use this lifetime with the exception of HIR data which uses the `'hir` lifetime. ([see more](../ty.md)) -token | The smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.md)). -[TLS] | Thread-Local Storage. Variables may be defined so that each thread has its own copy (rather than all threads sharing the variable). This has some interactions with LLVM. Not all platforms support TLS. -trait reference | The name of a trait along with a suitable set of input type/lifetimes. ([see more](../traits/goals-and-clauses.md#trait-ref)) -trans | Short for "translation", the code to translate MIR into LLVM IR. Renamed to codegen. -`Ty` | The internal representation of a type. ([see more](../ty.md)) -TyCtxt | The data structure often referred to as [tcx](#tcx) in code which provides access to session data and the query system. -UFCS | Short for Universal Function Call Syntax, this is an unambiguous syntax for calling a method. ([see more](../type-checking.md)) -uninhabited type | A type which has _no_ values. This is not the same as a ZST, which has exactly 1 value. An example of an uninhabited type is `enum Foo {}`, which has no variants, and so, can never be created. The compiler can treat code that deals with uninhabited types as dead code, since there is no such value to be manipulated. `!` (the never type) is an uninhabited type. Uninhabited types are also called "empty types". -upvar | A variable captured by a closure from outside the closure. -variance | Determines how changes to a generic type/lifetime parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec` is a subtype `Vec` because `Vec` is *covariant* in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance. -variant index | In an enum, identifies a variant by assigning them indices starting at 0. This is purely internal and not to be confused with the ["discrimiant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`). -wide pointer | A pointer with additional metadata. See "fat pointer" for more. -ZST | Zero-Sized Type. A type whose values have size 0 bytes. Since `2^0 = 1`, such types can have exactly one value. For example, `()` (unit) is a ZST. `struct Foo;` is also a ZST. The compiler can do some nice optimizations around ZSTs. + +Term | Meaning +------------------------------------------------------|-------- +arena/arena allocation   | An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info. +AST   | The abstract syntax tree produced by the `rustc_ast` crate; reflects user syntax very closely. +binder   | A "binder" is a place where a variable or type is declared; for example, the `` is a binder for the generic type parameter `T` in `fn foo(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound). +BodyId   | An identifier that refers to a specific body (definition of a function or constant) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). +bound variable   | A "bound variable" is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.md#free-vs-bound) +codegen   | The code to translate MIR into LLVM IR. +codegen unit   | When we produce LLVM IR, we group the Rust code into a number of codegen units (sometimes abbreviated as CGUs). Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. ([see more](../backend/codegen.md)) +completeness   | A technical term in type theory, it means that every type-safe program also type-checks. Having both soundness and completeness is very hard, and usually soundness is more important. (see "soundness"). +control-flow graph   | A representation of the control-flow of a program; see [the background chapter for more](./background.md#cfg) +CTFE   | Short for Compile-Time Function Evaluation, this is the ability of the compiler to evaluate `const fn`s at compile time. This is part of the compiler's constant evaluation system. ([see more](../const-eval.md)) +cx   | We tend to use "cx" as an abbreviation for context. See also `tcx`, `infcx`, etc. +ctxt   | We also use "ctxt" as an abbreviation for context, e.g. [`TyCtxt`](#TyCtxt). See also [cx](#cx) or [tcx](#tcx). +DAG   | A directed acyclic graph is used during compilation to keep track of dependencies between queries. ([see more](../queries/incremental-compilation.md)) +data-flow analysis   | A static analysis that figures out what properties are true at each point in the control-flow of a program; see [the background chapter for more](./background.md#dataflow). +DeBruijn Index   | A technique for describing which binder a variable is bound by using only integers. It has the benefit that it is invariant under variable renaming. ([see more](./background.md#what-is-a-debruijn-index)) +DefId   | An index identifying a definition (see `rustc_middle/src/hir/def_id.rs`). Uniquely identifies a `DefPath`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). +discriminant   | The underlying value associated with an enum variant or generator state to indicate it as "active" (but not to be confused with its ["variant index"](#variant-idx)). At runtime, the discriminant of the active variant is encoded in the [tag](#tag). +double pointer   | A pointer with additional metadata. See "fat pointer" for more. +drop glue   | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types. +DST   | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`). +early-bound lifetime   | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions)) +empty type   | see "uninhabited type". +fat pointer   | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers". +free variable   | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound) +generics   | The set of generic type parameters defined on a type or item. +HIR   | The High-level IR, created by lowering and desugaring the AST. ([see more](../hir.md)) +HirId   | Identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). +HIR map   | The HIR map, accessible via `tcx.hir()`, allows you to quickly navigate the HIR and convert between various forms of identifiers. +ICE   | Short for internal compiler error, this is when the compiler crashes. +ICH   | Short for incremental compilation hash, these are used as fingerprints for things such as HIR and crate metadata, to check if changes have been made. This is useful in incremental compilation to see if part of a crate has changed and should be recompiled. +infcx   | The type inference context (`InferCtxt`). (see `rustc_middle::infer`) +inference variable   | 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. +intern   | 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. +intrinsic   | 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)) +IR   | 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. +IRLO   | `IRLO` or `irlo` is sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org). +item   | A kind of "definition" in the language, such as a static, const, use statement, module, struct, etc. Concretely, this corresponds to the `Item` type. +lang item   | Items that represent concepts intrinsic to the language itself, such as special built-in traits like `Sync` and `Send`; or traits representing operations such as `Add`; or functions that are called by the compiler. ([see more](https://doc.rust-lang.org/1.9.0/book/lang-items.html)) +late-bound lifetime   | A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions)) +local crate   | The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate. +LTO   | Short for Link-Time Optimizations, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto]. +[LLVM]   | (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. +memoization   | 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. +MIR   | The Mid-level IR that is created after type-checking for use by borrowck and codegen. ([see more](../mir/index.md)) +miri   | An interpreter for MIR used for constant evaluation. ([see more](../miri.md)) +monomorphization   | 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`, 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`, a copy for `Vec`, etc). +normalize   | 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). +newtype   | 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. +niche   | Invalid bit patterns for a type *that can be used* for layout optimizations. Some types cannot have certain bit patterns. For example, the `NonZero*` integers or the reference `&T` cannot be represented by a 0 bitstring. This means the compiler can perform layout optimizations by taking advantage of the invalid "niche value". An example application for this is the [*Discriminant elision on `Option`-like enums*](https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html#discriminant-elision-on-option-like-enums), which allows using a type's niche as the ["tag"](#tag) for an `enum` without requiring a separate field. +NLL   | Short for [non-lexical lifetimes](../borrow_check/region_inference.md), this is an extension to Rust's borrowing system to make it be based on the control-flow graph. +node-id or NodeId   | An index identifying a particular node in the AST or HIR; gradually being phased out and replaced with `HirId`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). +obligation   | Something that must be proven by the trait system. ([see more](../traits/resolution.md)) +placeholder   | **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow_check/region_inference/placeholders_and_universes.md) for more details. +point   | Used in the NLL analysis to refer to some particular location in the MIR; typically used to refer to a node in the control-flow graph. +polymorphize   | An optimization that avoids unnecessary monomorphisation. ([see more](../backend/monomorph.md#polymorphization)) +projection   | A general term for a "relative path", e.g. `x.f` is a "field projection", and `T::Item` is an ["associated type projection"](../traits/goals-and-clauses.md#trait-ref). +promoted constants   | Constants extracted from a function and lifted to static scope; see [this section](../mir/index.md#promoted) for more details. +provider   | The function that executes a query. ([see more](../query.md)) +quantified   | In math or logic, existential and universal quantification are used to ask questions like "is there any type T for which is true?" or "is this true for all types T?"; see [the background chapter for more](./background.md#quantified). +query   | A sub-computation during compilation. Query results can be cached in the current session or to disk for incremental compilation. ([see more](../query.md)) +recovery   | Recovery refers to handling invalid syntax during parsing (e.g. a missing comma) and continuing to parse the AST. This avoid showing spurious errors to the user (e.g. showing 'missing field' errors when the struct definition contains errors). +region   | Another term for "lifetime" often used in the literature and in the borrow checker. +rib   | A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md)) +scrutinee   | A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee. +sess   | The compiler session, which stores global data used throughout compilation +side tables   | Because the AST and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node. +sigil   | Like a keyword but composed entirely of non-alphanumeric tokens. For example, `&` is a sigil for references. +soundness   | A technical term in type theory. Roughly, if a type system is sound, then a program that type-checks is type-safe. That is, one can never (in safe rust) force a value into a variable of the wrong type. (see "completeness"). +span   | A location in the user's source code, used for error reporting primarily. These are like a file-name/line-number/column tuple on steroids: they carry a start/end point, and also track macro expansions and compiler desugaring. All while being packed into a few bytes (really, it's an index into a table). See the Span datatype for more. +substs   | The substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap`). +sysroot   | The directory for build artifacts that are loaded by the compiler at runtime. ([see more](../building/bootstrapping.html#what-is-a-sysroot)) +tag   | The "tag" of an enum/generator encodes the [discriminant](#discriminant) of the active variant/state. Tags can either be "direct" (simply storing the discriminant in a field) or use a ["niche"](#niche). +tcx   | The "typing context" (`TyCtxt`), main data structure of the compiler. ([see more](../ty.md)) +`'tcx`   | The lifetime of the allocation arenas used by `TyCtxt`. Most data interned during a compilation session will use this lifetime with the exception of HIR data which uses the `'hir` lifetime. ([see more](../ty.md)) +token   | The smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.md)). +[TLS]   | Thread-Local Storage. Variables may be defined so that each thread has its own copy (rather than all threads sharing the variable). This has some interactions with LLVM. Not all platforms support TLS. +trait reference   | The name of a trait along with a suitable set of input type/lifetimes. ([see more](../traits/goals-and-clauses.md#trait-ref)) +trans   | Short for "translation", the code to translate MIR into LLVM IR. Renamed to codegen. +`Ty`   | The internal representation of a type. ([see more](../ty.md)) +TyCtxt   | The data structure often referred to as [tcx](#tcx) in code which provides access to session data and the query system. +UFCS   | Short for Universal Function Call Syntax, this is an unambiguous syntax for calling a method. ([see more](../type-checking.md)) +uninhabited type   | A type which has _no_ values. This is not the same as a ZST, which has exactly 1 value. An example of an uninhabited type is `enum Foo {}`, which has no variants, and so, can never be created. The compiler can treat code that deals with uninhabited types as dead code, since there is no such value to be manipulated. `!` (the never type) is an uninhabited type. Uninhabited types are also called "empty types". +upvar   | A variable captured by a closure from outside the closure. +variance   | Determines how changes to a generic type/lifetime parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec` is a subtype `Vec` because `Vec` is *covariant* in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance. +variant index   | In an enum, identifies a variant by assigning them indices starting at 0. This is purely internal and not to be confused with the ["discrimiant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`). +wide pointer   | A pointer with additional metadata. See "fat pointer" for more. +ZST   | Zero-Sized Type. A type whose values have size 0 bytes. Since `2^0 = 1`, such types can have exactly one value. For example, `()` (unit) is a ZST. `struct Foo;` is also a ZST. The compiler can do some nice optimizations around ZSTs. [LLVM]: https://llvm.org/ [lto]: https://llvm.org/docs/LinkTimeOptimization.html diff --git a/src/doc/rustc-dev-guide/src/ast-validation.md b/src/doc/rustc-dev-guide/src/ast-validation.md index 64e35bb93c..ff549ca624 100644 --- a/src/doc/rustc-dev-guide/src/ast-validation.md +++ b/src/doc/rustc-dev-guide/src/ast-validation.md @@ -3,4 +3,4 @@ AST validation is the process of checking various correctness properties about the AST after macro expansion. -**TODO**: write this chapter. +**TODO**: write this chapter. [#656](https://github.com/rust-lang/rustc-dev-guide/issues/656) diff --git a/src/doc/rustc-dev-guide/src/backend/inline-asm.md b/src/doc/rustc-dev-guide/src/backend/inline-asm.md index 0cae01ef39..f1a64b5ee1 100644 --- a/src/doc/rustc-dev-guide/src/backend/inline-asm.md +++ b/src/doc/rustc-dev-guide/src/backend/inline-asm.md @@ -1,4 +1,5 @@ # Inline Assembly -**TODO: You can find more info in -https://github.com/rust-lang/rust/pull/69171#issue-375572066** +**TODO**: You can find more info +[here](https://github.com/rust-lang/rust/pull/69171#issue-375572066) +[#1162](https://github.com/rust-lang/rustc-dev-guide/issues/1162) diff --git a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md index 91d8cb3aab..d2cf8b6929 100644 --- a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md +++ b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md @@ -72,8 +72,8 @@ Here are a few highlights of things it contains: from any other version. * The [Strict Version Hash](#strict-version-hash) (SVH). This helps ensure the correct dependency is loaded. -* The [Crate Disambiguator](#crate-disambiguator). This is a hash used - to disambiguate between different crates of the same name. +* The [Stable Crate Id](#stable-crate-id). This is a hash used + to identify crates. * Information about all the source files in the library. This can be used for a variety of things, such as diagnostics pointing to sources in a dependency. @@ -114,21 +114,22 @@ computed. [incremental compilation]: ../queries/incremental-compilation.md [`finalize_and_compute_crate_hash`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/collector/struct.NodeCollector.html#method.finalize_and_compute_crate_hash -### Crate Disambiguator +### Stable Crate Id -The [`CrateDisambiguator`] is a 128-bit hash used to distinguish between -different crates of the same name. It is a hash of all the [`-C metadata`] CLI -options computed in [`compute_crate_disambiguator`]. It is used in a variety -of places, such as symbol name mangling, crate loading, and much more. +The [`StableCrateId`] is a 64-bit hash used to identify different crates with +potentially the same name. It is a hash of the crate name and all the +[`-C metadata`] CLI options computed in [`StableCrateId::new`]. It is +used in a variety of places, such as symbol name mangling, crate loading, and +much more. -By default, all Rust symbols are mangled and incorporate the disambiguator -hash. This allows multiple versions of the same crate to be included together. -Cargo automatically generates `-C metadata` hashes based on a variety of -factors, like the package version, source, and the target kind (a lib and bin -can have the same crate name, so they need to be disambiguated). +By default, all Rust symbols are mangled and incorporate the stable crate id. +This allows multiple versions of the same crate to be included together. Cargo +automatically generates `-C metadata` hashes based on a variety of factors, +like the package version, source, and the target kind (a lib and test can have +the same crate name, so they need to be disambiguated). -[`CrateDisambiguator`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/crate_disambiguator/struct.CrateDisambiguator.html -[`compute_crate_disambiguator`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/util/fn.compute_crate_disambiguator.html +[`StableCrateId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html +[`StableCrateId::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html#method.new [`-C metadata`]: https://doc.rust-lang.org/rustc/codegen-options/index.html#metadata ## Crate loading diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index f27793140d..bb6badcd6e 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -43,6 +43,11 @@ you can write: in your `.vscode/settings.json` file. This will ask `rust-analyzer` to use `x.py check` to check the sources, and the stage 0 rustfmt to format them. +If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a +`.vim/coc-settings.json` and enter the same settings as above, but replacing +`editor.formatOnSave: true,` with +`"coc.preferences.formatOnSaveFiletypes": ["rust"],`. + If running `x.py check` on save is inconvenient, in VS Code you can use a [Build Task] instead: diff --git a/src/doc/rustc-dev-guide/src/compiler-src.md b/src/doc/rustc-dev-guide/src/compiler-src.md index 61af386522..b621dde7c2 100644 --- a/src/doc/rustc-dev-guide/src/compiler-src.md +++ b/src/doc/rustc-dev-guide/src/compiler-src.md @@ -2,15 +2,6 @@ -> **NOTE**: The structure of the repository is going through a lot of -> transitions. In particular, we want to get to a point eventually where the -> top-level directory has separate directories for the compiler, build-system, -> std libs, etc, rather than one huge `src/` directory. -> -> As of January 2021, the standard libraries have been -> moved to `library/` and the crates that make up the `rustc` compiler itself -> have been moved to `compiler/`. - Now that we have [seen what the compiler does](./overview.md), let's take a look at the structure of the contents of the rust-lang/rust repo. diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index cf049015d9..9df9b6dfc1 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -64,7 +64,8 @@ Pull requests (or PRs for short) are the primary mechanism we use to change Rust GitHub itself has some [great documentation][about-pull-requests] on using the Pull Request feature. We use the "fork and pull" model [described here][development-models], where contributors push changes to their personal fork and create pull requests to -bring those changes into the source repository. +bring those changes into the source repository. We have more info about how to use git +when contributing to Rust under [the git section](./git.md). [about-pull-requests]: https://help.github.com/articles/about-pull-requests/ [development-models]: https://help.github.com/articles/about-collaborative-development-models/ @@ -144,8 +145,7 @@ CI will also run tidy and will fail if tidy fails. Rust follows a _no merge-commit policy_, meaning, when you encounter merge conflicts you are expected to always rebase instead of merging. E.g. always use rebase when bringing the latest changes from the master branch to your feature -branch. Also, please make sure that fixup commits are squashed into other -related commits with meaningful commit messages. +branch. If you encounter merge conflicts or when a reviewer asks you to perform some changes, your PR will get marked as `S-waiting-on-author`. When you resolve diff --git a/src/doc/rustc-dev-guide/src/crates-io.md b/src/doc/rustc-dev-guide/src/crates-io.md index 6fbabdc914..bc59bfeeda 100644 --- a/src/doc/rustc-dev-guide/src/crates-io.md +++ b/src/doc/rustc-dev-guide/src/crates-io.md @@ -12,7 +12,9 @@ reasons: - The dependency may have transitive dependencies that have one of the above problems. -TODO: what is the vetting process? +As of July 2021, there is no official policy for vetting +new dependencies to the compiler. Generally, new dependencies are not added +to the compiler unless there is a good reason to do so. ## Permitted dependencies diff --git a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md index 5590311483..9d455084d0 100644 --- a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md +++ b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md @@ -314,8 +314,7 @@ Clang always embeds an MD5 checksum, though this does not appear in documentatio * New demangler in `libiberty` (gcc source tree). * New demangler in LLVM or LLDB. -**TODO**: Check the location of the demangler source. -[Question on Github](https://github.com/rust-lang/rustc-dev-guide/pull/316#discussion_r283062536). +**TODO**: Check the location of the demangler source. [#1157](https://github.com/rust-lang/rustc-dev-guide/issues/1157) #### Reuse Rust compiler for expressions diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index 38683f98db..385d7db60f 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -493,10 +493,11 @@ much faster to work on. [`rustc_lint_defs`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/index.html Every lint is implemented via a `struct` that implements the `LintPass` `trait` -(you also implement one of the more specific lint pass traits, either -`EarlyLintPass` or `LateLintPass`). The trait implementation allows you to -check certain syntactic constructs as the linter walks the source code. You can -then choose to emit lints in a very similar way to compile errors. +(you can also implement one of the more specific lint pass traits, either +`EarlyLintPass` or `LateLintPass` depending on when is best for your lint to run). +The trait implementation allows you to check certain syntactic constructs +as the linter walks the AST. You can then choose to emit lints in a +very similar way to compile errors. You also declare the metadata of a particular lint via the `declare_lint!` macro. This includes the name, the default level, a short description, and some @@ -566,7 +567,7 @@ impl EarlyLintPass for WhileTrue { } ``` -### Edition-gated Lints +### Edition-gated lints Sometimes we want to change the behavior of a lint in a new edition. To do this, we just add the transition to our invocation of `declare_lint!`: @@ -583,6 +584,24 @@ declare_lint! { This makes the `ANONYMOUS_PARAMETERS` lint allow-by-default in the 2015 edition but warn-by-default in the 2018 edition. +### Future-incompatible lints + +The use of the term `future-incompatible` within the compiler has a slightly +broader meaning than what rustc exposes to users of the compiler. + +Inside rustc, future-incompatible lints are for signalling to the user that code they have +written may not compile in the future. In general, future-incompatible code +exists for two reasons: +* the user has written unsound code that the compiler mistakenly accepted. While +it is within Rust's backwards compatibility guarantees to fix the soundness hole +(breaking the user's code), the lint is there to warn the user that this will happen +in some upcoming version of rustc *regardless of which edition the code uses*. This is the +meaning that rustc exclusively exposes to users as "future incompatible". +* the user has written code that will either no longer compiler *or* will change +meaning in an upcoming *edition*. These are often called "edition lints" and can be +typically seen in the various "edition compatibility" lint groups (e.g., `rust_2021_compatibility`) +that are used to lint against code that will break if the user updates the crate's edition. + A future-incompatible lint should be declared with the `@future_incompatible` additional "field": @@ -593,31 +612,34 @@ declare_lint! { "detects anonymous parameters", @future_incompatible = FutureIncompatibleInfo { reference: "issue #41686 ", - edition: Some(Edition::Edition2018), + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), }; } ``` -If you need a combination of options that's not supported by the `declare_lint!` -macro, you can always define your own static with a type of `&Lint` but this is -(as of January 2021) linted against in the compiler tree. +Notice the `reason` field which describes why the future incompatible change is happening. +This will change the diagnostic message the user receives as well as determine which +lint groups the lint is added to. In the example above, the lint is an "edition lint" +(since it's "reason" is `EditionError`) signifying to the user that the use of anonymous +parameters will no longer compile in Rust 2018 and beyond. -
-#### Guidelines for creating a future incompatibility lint +Inside [LintStore::register_lints][fi-lint-groupings], lints with `future_incompatible` +fields get placed into either edition-based lint groups (if their `reason` is tied to +an edition) or into the `future_incompatibility` lint group. -- Create a lint defaulting to warn as normal, with ideally the same error - message you would normally give. -- Add a suitable reference, typically an RFC or tracking issue. Go ahead - and include the full URL, sort items in ascending order of issue numbers. -- Later, change lint to error. -- Eventually, remove lint. +[fi-lint-groupings]: https://github.com/rust-lang/rust/blob/51fd129ac12d5bfeca7d216c47b0e337bf13e0c2/compiler/rustc_lint/src/context.rs#L212-L237 + +If you need a combination of options that's not supported by the +`declare_lint!` macro, you can always change the `declare_lint!` macro +to support this. ### Renaming or removing a lint -A lint can be renamed or removed, which will trigger a warning if a user tries +If it is determined that a lint is either improperly named or no longer needed, +the lint must be registered for renaming or removal, which will trigger a warning if a user tries to use the old lint name. To declare a rename/remove, add a line with [`store.register_renamed`] or [`store.register_removed`] to the code of the -[`register_builtins`] function. +[`rustc_lint::register_builtins`] function. ```rust,ignore store.register_renamed("single_use_lifetime", "single_use_lifetimes"); @@ -625,7 +647,7 @@ store.register_renamed("single_use_lifetime", "single_use_lifetimes"); [`store.register_renamed`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_renamed [`store.register_removed`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_removed -[`register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html +[`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html ### Lint Groups @@ -649,6 +671,14 @@ This defines the `nonstandard_style` group which turns on the listed lints. A user can turn on these lints with a `!#[warn(nonstandard_style)]` attribute in the source code, or by passing `-W nonstandard-style` on the command line. +Some lint groups are created automatically in `LintStore::register_lints`. For instance, +any lint declared with `FutureIncompatibleInfo` where the reason is +`FutureIncompatibilityReason::FutureReleaseError` (the default when +`@future_incompatible` is used in `declare_lint!`), will be added to +the `future_incompatible` lint group. Editions also have their own lint groups +(e.g., `rust_2021_compatibility`) automatically generated for any lints signaling +future-incompatible code that will break in the specified edition. + ### Linting early in the compiler On occasion, you may need to define a lint that runs before the linting system @@ -682,7 +712,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` or the RLS). It looks like this: ```console $ rustc json_error_demo.rs --error-format json diff --git a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md index 6a59cf2647..d2796c0704 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md @@ -3,7 +3,7 @@ This page documents some of the machinery around lint registration and how we run lints in the compiler. -The `LintStore` is the central piece of infrastructure, around which everything +The [`LintStore`] is the central piece of infrastructure, around which everything rotates. It's not available during the early parts of compilation (i.e., before TyCtxt) in most code, as we need to fill it in with all of the lints, which can only happen after plugin registration. @@ -17,10 +17,9 @@ First, we have the lint declarations themselves: this is where the name and defa other metadata come from. These are normally defined by way of the [`declare_lint!`] macro, which boils down to a static with type `&rustc_session::lint::Lint`. -As of January 2021, we lint against direct declarations +As of July 2021, we lint against direct declarations without the use of the macro today (although this may change in the future, as -the macro is somewhat unwieldy to add new fields to, like all macros by -example). +the macro is somewhat unwieldy to add new fields to, like all macros). Lint declarations don't carry any "state" - they are merely global identifers and descriptions of lints. We assert at runtime that they are not registered twice (by lint name). @@ -34,44 +33,57 @@ lint, and frequently lints are emitted as part of other work (e.g., type checkin ### High-level overview -The lint store is created and all lints are registered during plugin registration, in -[`rustc_interface::register_plugins`]. There are three 'sources' of lint: the internal lints, plugin -lints, and `rustc_interface::Config` [`register_lints`]. All are registered here, in -`register_plugins`. +In [`rustc_interface::register_plugins`] the [`LintStore`] is created and all lints are registered. +There are four 'sources' of lints: +* internal lints: lints only used by the rustc codebase +* builtin lints: lints built into the compiler and not provided by some outside source +* plugin lints: lints created by plugins through the plugin system. +* `rustc_interface::Config`[`register_lints`]: lints passed into the compiler during construction + +Lints are registered via the [`LintStore::register_lint`] function. This should +happen just once for any lint, or an ICE will occur. Once the registration is complete, we "freeze" the lint store by placing it in an `Lrc`. Later in the driver, it's passed into the `GlobalCtxt` constructor where it lives in an immutable form from then on. -Lints are registered via the [`LintStore::register_lint`] function. This should -happen just once for any lint, or an ICE will occur. - Lint passes are registered separately into one of the categories (pre-expansion, early, late, late module). Passes are registered as a closure -- i.e., `impl Fn() -> Box`, where `dyn X` is either an early or late lint pass trait object. When we run the lint passes, we run the closure and then invoke the lint -pass methods, which take `&mut self` -- lint passes can keep track of state +pass methods. The lint pass methods take `&mut self` so they can keep track of state internally. #### Internal lints -Note, these include both rustc-internal lints, and the traditional lints, like, for example the dead -code lint. +These are lints used just by the compiler or plugins like `clippy`. They can be found in +`rustc_lint::internal`. + +An example of such a lint is the check that lint passes are implemented using the +`declare_lint_pass!` macro and not by hand. This is accomplished with the +`LINT_PASS_IMPL_WITHOUT_MACRO` lint. + +Registration of these lints happens in the [`rustc_lint::register_internals`] function which is +called when constructing a new lint store inside [`rustc_lint::new_lint_store`]. + +### Builtin Lints These are primarily described in two places: `rustc_session::lint::builtin` and -`rustc_lint::builtin`. The first provides the definitions for the lints themselves, -and the latter provides the lint pass definitions (and implementations). +`rustc_lint::builtin`. Often the first provides the definitions for the lints themselves, +and the latter provides the lint pass definitions (and implementations), but this is not always +true. -The internal lint registration happens in the [`rustc_lint::register_builtins`] function, along with -the [`rustc_lint::register_internals`] function. More generally, the LintStore "constructor" -function which is *the* way to get a `LintStore` in the compiler (you should not construct it -directly) is [`rustc_lint::new_lint_store`]; it calls the registration functions. +The builtin lint registration happens in the [`rustc_lint::register_builtins`] function. Just like +with internal lints, this happens inside of [`rustc_lint::new_lint_store`]. #### Plugin lints -This is one of the primary use cases remaining for plugins/drivers. Plugins are given access to the -mutable `LintStore` during registration to call any functions they need on the `LintStore`, just -like rustc code. Plugins are intended to declare lints with the `plugin` field set to true (e.g., by +This is one of the primary use cases remaining for plugins/drivers. Plugins are given access +to the mutable `LintStore` during registration (which happens inside of +[`rustc_interface::register_plugins`]) and they can call any functions they need on +the `LintStore`, just like rustc code. + +Plugins are intended to declare lints with the `plugin` field set to true (e.g., by way of the [`declare_tool_lint!`] macro), but this is purely for diagnostics and help text; otherwise plugin lints are mostly just as first class as rustc builtin lints. @@ -86,18 +98,15 @@ within the callback they add. The best way for drivers to get access to this is Within the compiler, for performance reasons, we usually do not register dozens of lint passes. Instead, we have a single lint pass of each variety -(e.g. `BuiltinCombinedModuleLateLintPass`) which will internally call all of the +(e.g., `BuiltinCombinedModuleLateLintPass`) which will internally call all of the individual lint passes; this is because then we get the benefits of static over dynamic dispatch for each of the (often empty) trait methods. -Ideally, we'd not have to do this, since it certainly adds to the complexity of +Ideally, we'd not have to do this, since it adds to the complexity of understanding the code. However, with the current type-erased lint store approach, it is beneficial to do so for performance reasons. -New lints being added likely want to join one of the existing declarations like -`late_lint_mod_passes` in `rustc_lint/src/lib.rs`, which would then -auto-propagate into the other. - +[`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html [`LintStore::register_lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_lints [`rustc_interface::register_plugins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.register_plugins.html [`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html diff --git a/src/doc/rustc-dev-guide/src/feature-gate-ck.md b/src/doc/rustc-dev-guide/src/feature-gate-ck.md index 3b3a07a31a..c17747a11b 100644 --- a/src/doc/rustc-dev-guide/src/feature-gate-ck.md +++ b/src/doc/rustc-dev-guide/src/feature-gate-ck.md @@ -1,3 +1,3 @@ # Feature Gate Checking -**TODO**: this chapter +**TODO**: this chapter [#1158](https://github.com/rust-lang/rustc-dev-guide/issues/1158) diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md index db6c72ff81..229281f2f0 100644 --- a/src/doc/rustc-dev-guide/src/feature-gates.md +++ b/src/doc/rustc-dev-guide/src/feature-gates.md @@ -27,6 +27,14 @@ For example: (active, non_ascii_idents, "1.0.0", Some(55467), None), ``` +Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` lint] +by setting their type to `incomplete`: + +```rust,ignore +/// Allows unsized rvalues at arguments and parameters. +(incomplete, unsized_locals, "1.30.0", Some(48055), None), +``` + When added, the current version should be the one for the current nightly. Once the feature is moved to `accepted.rs`, the version is changed to that nightly version. @@ -99,4 +107,5 @@ updating the declaration! ["Stability in code"]: ./implementing_new_features.md#stability-in-code +[`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features ["Updating the feature-gate listing"]: ./stabilization_guide.md#updating-the-feature-gate-listing diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index e10f1d7050..1c311982ca 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -46,6 +46,10 @@ git remote add upstream git@github.com:rust-lang/rust.git if you're using SSH. +**NOTE:** This page is dedicated to workflows for `rust-lang/rust`, but will likely be +useful when contributing to other repositories in the Rust project. + + ## Standard Process Below is the normal procedure that you're likely to use for most minor changes @@ -53,7 +57,8 @@ and PRs: 1. Ensure that you're making your changes on top of master: `git checkout master`. - 2. Get the latest changes from the Rust repo: `git pull upstream master`. + 2. Get the latest changes from the Rust repo: `git pull upstream master --ff-only`. + (see [No-Merge Policy](#keeping-things-up-to-date) for more info about this). 3. Make a new branch for your change: `git checkout -b issue-12345-fix`. 4. Make some changes to the repo and test them. 5. Stage your changes via `git add src/changed/file.rs src/another/change.rs` @@ -62,11 +67,17 @@ and PRs: unintentionally commit changes that should not be committed, such as submodule updates. You can use `git status` to check if there are any files you forgot to stage. - 6. Push your changes to your fork: `git push --set-upstream origin issue-12345-fix`. - 7. [Open a PR][ghpullrequest] from your fork to rust-lang/rust's master branch. + 6. Push your changes to your fork: `git push --set-upstream origin issue-12345-fix` + (After adding commits, you can use `git push` and after rebasing or +pulling-and-rebasing, you can use `git push --force-with-lease`). + 7. [Open a PR][ghpullrequest] from your fork to `rust-lang/rust`'s master branch. [ghpullrequest]: https://guides.github.com/activities/forking/#making-a-pull-request +If you end up needing to rebase and are hitting conflicts, see [Rebasing](#rebasing). +If you want to track upstream while working on long-running feature/issue, see +[Keeping things up to date](#keeping-things-up-to-date). + If your reviewer requests changes, the procedure for those changes looks much the same, with some steps skipped: @@ -146,7 +157,7 @@ no changes added to commit (use "git add" and/or "git commit -a") These changes are not changes to files: they are changes to submodules (more on this [later](#git-submodules)). To get rid of those, run `git submodule update` (or run any `x.py` command, which will automatically update the submodules). -Note that there is (as of January 2021) a bug if you use +Note that there is (as of July 2021) a [bug][#77620] if you use worktrees, submodules, and x.py in a commit hook. If you run into an error like: @@ -156,11 +167,12 @@ error: failed to read `/home/joshua/rustc-worktree/src/tools/miri/cargo-miri/Car Caused by: No such file or directory (os error 2) ``` -it's not anything you did wrong. There is a workaround at [#77620]. +it's not anything you did wrong. There is a workaround in [the issue][#77620-workaround]. -[#77620]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229 +[#77620]: https://github.com/rust-lang/rust/issues/77620 +[#77620-workaround]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229 -## Conflicts +## Rebasing and Conflicts When you edit your code locally, you are making changes to the version of rust-lang/rust that existed when you created your feature branch. As such, when @@ -236,6 +248,34 @@ The advice this gives is incorrect! Because of Rust's will not be allowed in the final PR, in addition to defeating the point of the rebase! Use `git push --force-with-lease` instead. +### Keeping things up to date + +The above section on [Rebasing](#rebasing) is a specific +guide on rebasing work and dealing with merge conflicts. +Here is some general advice about how to keep your local repo +up-to-date with upstream changes: + +Using `git pull upstream master` while on your local master branch regularly +will keep it up-to-date. You will also want to rebase your feature branches +up-to-date as well. After pulling, you can checkout the feature branches +and rebase them: + +``` +git checkout master +git pull upstream master --ff-only # to make certain there are no merge commits +git checkout feature_branch +git rebase master +git push --force-with-lease (set origin to be the same as local) +``` + +To avoid merges as per the [No-Merge Policy][#no-merge-policy], you may want to use +`git config pull.ff only` (this will apply the config to the local repo). +to avoid merge conflicts while pulling, without needing +`--ff-only` or `--rebase` while `git pull`ing + +You can also `git push --force-with-lease` from master to keep your origin's master in sync with +upstream. + ## Advanced Rebasing If your branch contains multiple consecutive rewrites of the same code, or if @@ -330,6 +370,7 @@ that merge commits in PRs are not accepted. As a result, if you are running course, this is not always true; if your merge will just be a fast-forward, like the merges that `git pull` usually performs, then no merge commit is created and you have nothing to worry about. Running `git config merge.ff only` +(this will apply the config to the local repo). once will ensure that all the merges you perform are of this type, so that you cannot make a mistake. diff --git a/src/doc/rustc-dev-guide/src/hir-debugging.md b/src/doc/rustc-dev-guide/src/hir-debugging.md index 519ff26677..8788ad4de1 100644 --- a/src/doc/rustc-dev-guide/src/hir-debugging.md +++ b/src/doc/rustc-dev-guide/src/hir-debugging.md @@ -5,4 +5,4 @@ The `-Z unpretty=hir-tree` flag will dump out the HIR. If you are trying to correlate `NodeId`s or `DefId`s with source code, the `--pretty expanded,identified` flag may be useful. -TODO: anything else? +TODO: anything else? [#1159](https://github.com/rust-lang/rustc-dev-guide/issues/1159) diff --git a/src/doc/rustc-dev-guide/src/identifiers.md b/src/doc/rustc-dev-guide/src/identifiers.md index 50d0c76e2f..18a3efefcd 100644 --- a/src/doc/rustc-dev-guide/src/identifiers.md +++ b/src/doc/rustc-dev-guide/src/identifiers.md @@ -82,7 +82,7 @@ See the [HIR chapter][hir-map] for more detailed information. - [`Promoted`] identifies a promoted constant within another item (related to const evaluation). Note: it is unique only locally within the item, so it should be associated with a `DefId`. - [`GlobalId`] will give you a more specific identifier (TODO). + [`GlobalId`] will give you a more specific identifier. - [`GlobalId`] identifies a global variable: a `const`, a `static`, a `const fn` where all arguments are [zero-sized types], or a promoted constant. diff --git a/src/doc/rustc-dev-guide/src/lang-items.md b/src/doc/rustc-dev-guide/src/lang-items.md new file mode 100644 index 0000000000..c5774c43ba --- /dev/null +++ b/src/doc/rustc-dev-guide/src/lang-items.md @@ -0,0 +1,67 @@ +# Lang items + +The compiler has certain pluggable operations; that is, functionality that isn't hard-coded into +the language, but is implemented in libraries, with a special marker to tell the compiler it +exists. The marker is the attribute `#[lang = "..."]`, and there are various different values of +`...`, i.e. various different 'lang items'. + +Many such lang items can be implemented only in one sensible way, such as `add` (`trait +core::ops::Add`) or `future_trait` (`trait core::future::Future`). Others can be overriden to +achieve some specific goals; for example, you can control your binary's entrypoint. + +Features provided by lang items include: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereference (`*`), `+`, etc. operators are all + marked with lang items; those specific four are `eq`, `ord`, + `deref`, and `add` respectively. +- panicking and stack unwinding; the `eh_personality`, `panic` and + `panic_bounds_checks` lang items. +- the traits in `std::marker` used to indicate properties of types used by the compiler; + lang items `send`, `sync` and `copy`. +- the special marker types used for variance indicators found in + `core::marker`; lang item `phantom_data`. + +Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` +then there is no need to define functions for `exchange_malloc` and +`box_free`. `rustc` will emit an error when an item is needed but not found +in the current crate or any that it depends on. + +Most lang items are defined by the `core` library, but if you're trying to build an +executable with `#![no_std]`, you'll still need to define a few lang items that are +usually provided by `std`. + +## Retrieving a language item + +You can retrieve lang items by calling [`tcx.lang_items()`]. + +Here's a small example of retrieving the `trait Sized {}` language item: + +```rust +// Note that in case of `#![no_core]`, the trait is not available. +if let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() { + // do something with `sized_trait_def_id` +} +``` + +Note that `sized_trait()` returns an `Option`, not the `DefId` itself. +That's because language items are defined in the standard libray, so if someone compiles with +`#![no_core]` (or for some lang items, `#![no_std]`), the lang item may not be present. +You can either: + +- Give a hard error if the lang item is necessary to continue (don't panic, since this can happen in + user code). +- Proceed with limited functionality, by just omitting whatever you were going to do with the + `DefId`. + +[`tcx.lang_items()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.lang_items + +## List of all language items + +You can find language items in the following places: +- An exhaustive reference in the compiler documentation: [`rustc_hir::LangItem`] +- An auto-generated list with source locations by using ripgrep: `rg '#\[.*lang =' library/` + +Note that language items are explicitly unstable and may change in any new release. + +[`rustc_hir::LangItem`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/enum.LangItem.html diff --git a/src/doc/rustc-dev-guide/src/macro-expansion.md b/src/doc/rustc-dev-guide/src/macro-expansion.md index 7385cefb38..ce82852832 100644 --- a/src/doc/rustc-dev-guide/src/macro-expansion.md +++ b/src/doc/rustc-dev-guide/src/macro-expansion.md @@ -608,10 +608,10 @@ Because the Rust ABI is unstable, we use the C ABI for this conversion. [pm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/proc_macro/index.html [pms]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/proc_macro_server/index.html -TODO: more here. +TODO: more here. [#1160](https://github.com/rust-lang/rustc-dev-guide/issues/1160) ### Custom Derive Custom derives are a special type of proc macro. -TODO: more? +TODO: more? [#1160](https://github.com/rust-lang/rustc-dev-guide/issues/1160) diff --git a/src/doc/rustc-dev-guide/src/miri.md b/src/doc/rustc-dev-guide/src/miri.md index 18cd6ed392..c19ba64012 100644 --- a/src/doc/rustc-dev-guide/src/miri.md +++ b/src/doc/rustc-dev-guide/src/miri.md @@ -197,10 +197,9 @@ Miri'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`, -does not have to have a pointer *value*: it could be obtaining by casting or -transmuting an integer to a pointer (as of January 2021 -that is hard to do in const eval, but eventually `transmute` will be stable as a -`const fn`). And similarly, when casting or transmuting a reference to some +does not have to have a pointer *value*: it could be obtained by casting or +transmuting an integer to a pointer. +And similarly, when casting or transmuting a reference to some actual allocation to an integer, we end up with a pointer *value* (`Scalar::Ptr`) at integer *type* (`usize`). This is a problem because we cannot meaningfully perform integer operations such as division on pointer diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md index 2eb76384c0..1cef7d08fa 100644 --- a/src/doc/rustc-dev-guide/src/name-resolution.md +++ b/src/doc/rustc-dev-guide/src/name-resolution.md @@ -164,7 +164,7 @@ To tell the difference between speculative loads and loads initiated by the user, resolve passes around a `record_used` parameter, which is `false` when the load is speculative. -## TODO: +## TODO: [#16](https://github.com/rust-lang/rustc-dev-guide/issues/16) This is a result of the first pass of learning the code. It is definitely incomplete and not detailed enough. It also might be inaccurate in places. diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index 1aa79e7914..6c756e18ff 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -68,10 +68,14 @@ we'll talk about that later. - We then take the AST and [convert it to High-Level Intermediate Representation (HIR)][hir]. This is a compiler-friendly representation of the AST. This involves a lot of desugaring of things like loops and `async fn`. -- We use the HIR to do [type inference]. This is the process of automatic - detection of the type of an expression. -- **TODO: Maybe some other things are done here? I think initial type checking - happens here? And trait solving?** +- We use the HIR to do [type inference] (the process of automatic + detection of the type of an expression), [trait solving] (the process + of pairing up an impl with each reference to a trait), and [type + checking] (the process of converting the types found in the HIR + (`hir::Ty`), which represent the syntactic things that the user wrote, + into the internal representation used by the compiler (`Ty<'tcx>`), + and using that information to verify the type safety, correctness and + coherence of the types used in the program). - The HIR is then [lowered to Mid-Level Intermediate Representation (MIR)][mir]. - Along the way, we construct the THIR, which is an even more desugared HIR. THIR is used for pattern and exhaustiveness checking. It is also more @@ -111,6 +115,8 @@ we'll talk about that later. [parser]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html [hir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/index.html [type inference]: https://rustc-dev-guide.rust-lang.org/type-inference.html +[trait solving]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html +[type checking]: https://rustc-dev-guide.rust-lang.org/type-checking.html [mir]: https://rustc-dev-guide.rust-lang.org/mir/index.html [borrow checking]: https://rustc-dev-guide.rust-lang.org/borrow_check.html [mir-opt]: https://rustc-dev-guide.rust-lang.org/mir/optimizations.html diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md index 8be19e8dcf..eec8219a5b 100644 --- a/src/doc/rustc-dev-guide/src/parallel-rustc.md +++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md @@ -3,7 +3,7 @@ Most of the compiler is not parallel. This represents an opportunity for improving compiler performance. -As of January 2021, work on explicitly parallelizing the +As of July 2021, work on explicitly parallelizing the compiler has stalled. There is a lot of design and correctness work that needs to be done. diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index aa3a813283..20e547b1e3 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -1,7 +1,7 @@ # Queries: demand-driven compilation As described in [the high-level overview of the compiler][hl], the Rust compiler -is still (as of January 2021) transitioning from a +is still (as of July 2021) transitioning from a traditional "pass-based" setup to a "demand-driven" system. **The Compiler Query System is the key to our new demand-driven organization.** The idea is pretty simple. You have various queries that compute things about the input – for diff --git a/src/doc/rustc-dev-guide/src/salsa.md b/src/doc/rustc-dev-guide/src/salsa.md index bfe7538247..9bf93727a3 100644 --- a/src/doc/rustc-dev-guide/src/salsa.md +++ b/src/doc/rustc-dev-guide/src/salsa.md @@ -9,7 +9,7 @@ want to watch [Salsa In More Depth](https://www.youtube.com/watch?v=i_IhACacPRY), also by Niko Matsakis. -> As of January 2021, although Salsa is inspired by +> As of July 2021, although Salsa is inspired by > (among other things) rustc's query system, it is not used directly in rustc. > It _is_ used in chalk and extensively in `rust-analyzer`, but there are no > medium or long-term concrete plans to integrate it into the compiler. diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index cfb4efd891..7eff3e88bc 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -44,7 +44,7 @@ prevents breaking dependencies by leveraging Cargo's lint capping. [rustc bug]: https://github.com/rust-lang/rust/issues/15702 ## stable -The `#[stable(feature = "foo", "since = "1.420.69")]` attribute explicitly +The `#[stable(feature = "foo", since = "1.420.69")]` attribute explicitly marks an item as stabilized. Note that stable functions may use unstable things in their body. ## rustc_const_unstable @@ -60,7 +60,7 @@ there's no way to add `const` to functions in `extern` blocks for now. ## rustc_const_stable -The `#[rustc_const_stable(feature = "foo", "since = "1.420.69")]` attribute explicitly marks +The `#[rustc_const_stable(feature = "foo", since = "1.420.69")]` attribute explicitly marks a `const fn` as having its constness be `stable`. This attribute can make sense even on an `unstable` function, if that function is called from another `rustc_const_stable` function. @@ -85,28 +85,39 @@ To stabilize a feature, follow these steps: - Add the appropriate labels: `@rustbot modify labels: +T-libs`. - Link to the tracking issue and say "Closes #XXXXX". -You can see an example of stabilizing a feature at [#75132](https://github.com/rust-lang/rust/pull/75132). +You can see an example of stabilizing a feature with +[tracking issue #81656 with FCP](https://github.com/rust-lang/rust/issues/81656) +and the associated +[implementation PR #84642](https://github.com/rust-lang/rust/pull/84642). ## allow_internal_unstable -Macros, compiler desugarings and `const fn`s expose their bodies to the call +Macros and compiler desugarings expose their bodies to the call site. To work around not being able to use unstable things in the standard library's macros, there's the `#[allow_internal_unstable(feature1, feature2)]` -attribute that allows the given features to be used in stable macros or -`const fn`s. - -Note that `const fn`s are even more special in this regard. You can't just -allow any feature, the features need an implementation in -`qualify_min_const_fn.rs`. For example the `const_fn_union` feature gate allows -accessing fields of unions inside stable `const fn`s. The rules for when it's -ok to use such a feature gate are that behavior matches the runtime behavior of -the same code (see also [this blog post][blog]). This means that you may not -create a `const fn` that e.g. transmutes a memory address to an integer, +attribute that allows the given features to be used in stable macros. + +## rustc_allow_const_fn_unstable + +`const fn`, while not directly exposing their body to the world, are going to get +evaluated at compile time in stable crates. If their body does something const-unstable, +that could lock us into certain features indefinitely by accident. Thus no unstable const +features are allowed inside stable `const fn`. + +However, sometimes we do know that a feature will get +stabilized, just not when, or there is a stable (but e.g. runtime-slow) workaround, so we +could always fall back to some stable version if we scrapped the unstable feature. +In those cases, the rustc_allow_const_fn_unstable attribute can be used to allow some +unstable features in the body of a stable `const fn`. + +You also need to take care to uphold the `const fn` invariant that calling it at runtime and +compile-time needs to behave the same (see also [this blog post][blog]). This means that you +may not create a `const fn` that e.g. transmutes a memory address to an integer, because the addresses of things are nondeterministic and often unknown at compile-time. -Always ping @oli-obk, @RalfJung, and @Centril if you are adding more -`allow_internal_unstable` attributes to any `const fn` +Always ping @rust-lang/wg-const-eval if you are adding more +`rustc_allow_const_fn_unstable` attributes to any `const fn`. ## staged_api diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 874ef82746..34a44f9c24 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -92,6 +92,20 @@ tests for components you did not change at all. build; therefore, while the tests **usually** work fine with stage 1, there are some limitations. +## Run unit tests on the compiler/library + +You may want to run unit tests on a specific file with following: + +```bash +./x.py test compiler/rustc_data_structures/src/thin_vec/tests.rs +``` + +But unfortunately, it's impossible. You should invoke following instead: + +```bash +./x.py test compiler/rustc_data_structures/ --test-args thin_vec +``` + ## Running an individual test Another common thing that people want to do is to run an **individual diff --git a/src/doc/rustc-dev-guide/src/type-checking.md b/src/doc/rustc-dev-guide/src/type-checking.md index 797cd9487a..cd58faf22b 100644 --- a/src/doc/rustc-dev-guide/src/type-checking.md +++ b/src/doc/rustc-dev-guide/src/type-checking.md @@ -41,4 +41,4 @@ For more details, see the [`collect`][collect] module. [queries]: ./query.md [collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/collect/ -**TODO**: actually talk about type checking... +**TODO**: actually talk about type checking... [#1161](https://github.com/rust-lang/rustc-dev-guide/issues/1161) diff --git a/src/doc/rustc-dev-guide/src/type-inference.md b/src/doc/rustc-dev-guide/src/type-inference.md index 71c2b08b19..4be9211eee 100644 --- a/src/doc/rustc-dev-guide/src/type-inference.md +++ b/src/doc/rustc-dev-guide/src/type-inference.md @@ -71,8 +71,8 @@ inference works, or perhaps this blog post on [Unification in the Chalk project]: http://smallcultfollowing.com/babysteps/blog/2017/03/25/unification-in-chalk-part-1/ -All told, the inference context stores four kinds of inference variables -(as of January 2018): +All told, the inference context stores five kinds of inference variables +(as of June 2021): - Type variables, which come in three varieties: - General type variables (the most common). These can be unified with any @@ -82,6 +82,7 @@ All told, the inference context stores four kinds of inference variables - Float type variables, which can only be unified with a float type, and arise from a float literal expression like `22.0`. - Region variables, which represent lifetimes, and arise all over the place. +- Const variables, which represent constants. All the type variables work in much the same way: you can create a new type variable, and what you get is `Ty<'tcx>` representing an diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index b0d040942e..5841afe4f5 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -188,7 +188,7 @@ don't request anyone; the bot will assign someone automatically. The reviewer may request changes before they approve your PR. Feel free to ask questions or discuss things you don't understand or disagree with. However, -recognize that the PR won't be merged unless someone on the rust team approves +recognize that the PR won't be merged unless someone on the Rust team approves it. When your reviewer approves the PR, it will go into a queue for yet another bot diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 3225e95941..885010b039 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -248,6 +248,7 @@ target | std | host | notes `powerpc-wrs-vxworks-spe` | ? | | `powerpc-wrs-vxworks` | ? | | `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2) +`powerpc64le-unknown-freebsd` | | | PPC64LE FreeBSD `powerpc64-unknown-linux-musl` | ? | | `powerpc64-wrs-vxworks` | ? | | `powerpc64le-unknown-linux-musl` | ? | | diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index ae94527e2b..3fa91bb51f 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -10,5 +10,6 @@ - [Lints](lints.md) - [Advanced features](advanced-features.md) - [Unstable features](unstable-features.md) +- [Website features](website-features.md) - [Passes](passes.md) - [References](references.md) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 2e4016e24b..c8af369a96 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -417,3 +417,10 @@ This flag is **deprecated** and **has no effect**. Rustdoc only supports Rust source code and Markdown input formats. If the file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. Otherwise, it assumes that the input file is Rust. + +## `--nocapture` + +When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be +captured by rustdoc. Instead, the output will be directed to your terminal, +as if you had run the test executable manually. This is especially useful +for debugging your tests! diff --git a/src/doc/rustdoc/src/website-features.md b/src/doc/rustdoc/src/website-features.md new file mode 100644 index 0000000000..5fade4e84a --- /dev/null +++ b/src/doc/rustdoc/src/website-features.md @@ -0,0 +1,25 @@ +# Website features + +These features are about using the website generated by `rustdoc`. + +## Custom search engines + +If you find yourself often referencing online Rust docs you might enjoy using a custom search +engine. This allows you to use the navigation bar directly to search a `rustdoc` website. +Most browsers support this feature by letting you define a URL template containing `%s` +which will be substituted for the search term. As an example, for the standard library you could use +this template: + +```text +https://doc.rust-lang.org/stable/std/?search=%s +``` + +Note that this will take you to a results page listing all matches. If you want to navigate to the first +result right away (which is often the best match) use the following instead: + +```text +https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true +``` + +This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL +to automatically go to the first result. diff --git a/src/doc/unstable-book/src/compiler-flags/force-warns.md b/src/doc/unstable-book/src/compiler-flags/force-warn.md similarity index 70% rename from src/doc/unstable-book/src/compiler-flags/force-warns.md rename to src/doc/unstable-book/src/compiler-flags/force-warn.md index 0a205be096..052de0f379 100644 --- a/src/doc/unstable-book/src/compiler-flags/force-warns.md +++ b/src/doc/unstable-book/src/compiler-flags/force-warn.md @@ -1,10 +1,10 @@ -# `force-warns` +# `force-warn` The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512). ------------------------ -This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warns` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`. +This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warn` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`. ## Example @@ -18,4 +18,4 @@ fn dead_function() {} fn main() {} ``` -We can force a warning to be produced by providing `--force-warns dead_code` to rustc. +We can force a warning to be produced by providing `--force-warn dead_code` to rustc. diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md new file mode 100644 index 0000000000..d26512703f --- /dev/null +++ b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md @@ -0,0 +1,26 @@ +# `exclusive_range_pattern` + +The tracking issue for this feature is: [#37854]. + + +[#67264]: https://github.com/rust-lang/rust/issues/67264 +[#37854]: https://github.com/rust-lang/rust/issues/37854 +----- + +The `exclusive_range_pattern` feature allows non-inclusive range +patterns (`0..10`) to be used in appropriate pattern matching +contexts. It also can be combined with `#![feature(half_open_range_patterns]` +to be able to use RangeTo patterns (`..10`). + +It also enabled RangeFrom patterns but that has since been +stabilized. + +```rust +#![feature(exclusive_range_pattern)] + let x = 5; + match x { + 0..10 => println!("single digit"), + 10 => println!("ten isn't part of the above range"), + _ => println!("nor is everything else.") + } +``` 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 new file mode 100644 index 0000000000..3b16dd049c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md @@ -0,0 +1,27 @@ +# `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/impl-trait-in-bindings.md b/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md deleted file mode 100644 index 5c6aa912c1..0000000000 --- a/src/doc/unstable-book/src/language-features/impl-trait-in-bindings.md +++ /dev/null @@ -1,28 +0,0 @@ -# `impl_trait_in_bindings` - -The tracking issue for this feature is: [#63065] - -[#63065]: https://github.com/rust-lang/rust/issues/63065 - ------------------------- - -The `impl_trait_in_bindings` feature gate lets you use `impl Trait` syntax in -`let`, `static`, and `const` bindings. - -A simple example is: - -```rust -#![feature(impl_trait_in_bindings)] - -use std::fmt::Debug; - -fn main() { - let a: impl Debug + Clone = 42; - let b = a.clone(); - println!("{:?}", b); // prints `42` -} -``` - -Note however that because the types of `a` and `b` are opaque in the above -example, calling inherent methods or methods outside of the specified traits -(e.g., `a.abs()` or `b.abs()`) is not allowed, and yields an error. diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index 03dbf4fb61..e950891ef9 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -456,7 +456,7 @@ reg_spec := / "" operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" reg_operand := dir_spec "(" reg_spec ")" operand_expr operand := reg_operand / "const" const_expr / "sym" path -option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" +option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" options := "options(" option *["," option] [","] ")" asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")" ``` @@ -545,9 +545,12 @@ Here is the list of currently supported register classes: | x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` | | x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` | | x86 | `kreg` | `k[1-7]` | `Yk` | +| x86 | `x87_reg` | `st([0-7])` | Only clobbers | +| x86 | `mmx_reg` | `mm[0-7]` | Only clobbers | | AArch64 | `reg` | `x[0-30]` | `r` | | AArch64 | `vreg` | `v[0-31]` | `w` | | AArch64 | `vreg_low16` | `v[0-15]` | `x` | +| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers | | ARM | `reg` | `r[0-12]`, `r14` | `r` | | ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` | | ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` | @@ -566,6 +569,7 @@ Here is the list of currently supported register classes: | NVPTX | `reg64` | None\* | `l` | | RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` | | RISC-V | `freg` | `f[0-31]` | `f` | +| RISC-V | `vreg` | `v[0-31]` | Only clobbers | | Hexagon | `reg` | `r[0-28]` | `r` | | PowerPC | `reg` | `r[0-31]` | `r` | | PowerPC | `reg_nonzero` | | `r[1-31]` | `b` | @@ -581,6 +585,8 @@ Here is the list of currently supported register classes: > Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported. > > Note #4: WebAssembly doesn't have registers, so named registers are not supported. +> +> Note #5: Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out("reg") _` or `lateout("reg") _`. Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc). @@ -596,8 +602,11 @@ Each register class has constraints on which value types they can be used with. | x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4`
`i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` | | x86 | `kreg` | `axv512f` | `i8`, `i16` | | x86 | `kreg` | `axv512bw` | `i32`, `i64` | +| x86 | `mmx_reg` | N/A | Only clobbers | +| x86 | `x87_reg` | N/A | Only clobbers | | AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | +| AArch64 | `preg` | N/A | Only clobbers | | ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` | | ARM | `sreg` | `vfp2` | `i32`, `f32` | | ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` | @@ -613,6 +622,7 @@ Each register class has constraints on which value types they can be used with. | RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | RISC-V | `freg` | `f` | `f32` | | RISC-V | `freg` | `d` | `f64` | +| RISC-V | `vreg` | N/A | Only clobbers | | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | | PowerPC | `reg` | None | `i8`, `i16`, `i32` | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` | @@ -781,6 +791,7 @@ Currently the following options are defined: - `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code. A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked. - `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call. - `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. Register operands are substituted in with a leading `%`. +- `raw`: This causes the template string to be parsed as a raw assembly string, with no special handling for `{` and `}`. This is primarily useful when including raw assembly code from an external file using `include_str!`. The compiler performs some additional checks on options: - The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both. diff --git a/src/doc/unstable-book/src/library-features/try-trait.md b/src/doc/unstable-book/src/library-features/try-trait.md deleted file mode 100644 index 022640067b..0000000000 --- a/src/doc/unstable-book/src/library-features/try-trait.md +++ /dev/null @@ -1,50 +0,0 @@ -# `try_trait` - -The tracking issue for this feature is: [#42327] - -[#42327]: https://github.com/rust-lang/rust/issues/42327 - ------------------------- - -This introduces a new trait `Try` for extending the `?` operator to types -other than `Result` (a part of [RFC 1859]). The trait provides the canonical -way to _view_ a type in terms of a success/failure dichotomy. This will -allow `?` to supplant the `try_opt!` macro on `Option` and the `try_ready!` -macro on `Poll`, among other things. - -[RFC 1859]: https://github.com/rust-lang/rfcs/pull/1859 - -Here's an example implementation of the trait: - -```rust,ignore (cannot-reimpl-Try) -/// A distinct type to represent the `None` value of an `Option`. -/// -/// This enables using the `?` operator on `Option`; it's rarely useful alone. -#[derive(Debug)] -#[unstable(feature = "try_trait", issue = "42327")] -pub struct None { _priv: () } - -#[unstable(feature = "try_trait", issue = "42327")] -impl ops::Try for Option { - type Ok = T; - type Error = None; - - fn into_result(self) -> Result { - self.ok_or(None { _priv: () }) - } - - fn from_ok(v: T) -> Self { - Some(v) - } - - fn from_error(_: None) -> Self { - None - } -} -``` - -Note the `Error` associated type here is a new marker. The `?` operator -allows interconversion between different `Try` implementers only when -the error type can be converted `Into` the error type of the enclosing -function (or catch block). Having a distinct error type (as opposed to -just `()`, or similar) restricts this to where it's semantically meaningful. diff --git a/src/etc/dec2flt_table.py b/src/etc/dec2flt_table.py old mode 100755 new mode 100644 index ad2292e857..aa5188d96c --- a/src/etc/dec2flt_table.py +++ b/src/etc/dec2flt_table.py @@ -1,141 +1,110 @@ #!/usr/bin/env python3 """ -Generate powers of ten using William Clinger's ``AlgorithmM`` for use in +Generate powers of five using Daniel Lemire's ``Eisel-Lemire algorithm`` for use in decimal to floating point conversions. Specifically, computes and outputs (as Rust code) a table of 10^e for some -range of exponents e. The output is one array of 64 bit significands and -another array of corresponding base two exponents. The approximations are -normalized and rounded perfectly, i.e., within 0.5 ULP of the true value. +range of exponents e. The output is one array of 128 bit significands. +The base two exponents can be inferred using a logarithmic slope +of the decimal exponent. The approximations are normalized and rounded perfectly, +i.e., within 0.5 ULP of the true value. -The representation ([u64], [i16]) instead of the more natural [(u64, i16)] -is used because (u64, i16) has a ton of padding which would make the table -even larger, and it's already uncomfortably large (6 KiB). +Adapted from Daniel Lemire's fast_float ``table_generation.py``, +available here: . """ from __future__ import print_function -from math import ceil, log +from math import ceil, floor, log, log2 from fractions import Fraction -from collections import namedtuple - - -N = 64 # Size of the significand field in bits -MIN_SIG = 2 ** (N - 1) -MAX_SIG = (2 ** N) - 1 - -# Hand-rolled fp representation without arithmetic or any other operations. -# The significand is normalized and always N bit, but the exponent is -# unrestricted in range. -Fp = namedtuple('Fp', 'sig exp') - - -def algorithm_m(f, e): - assert f > 0 - if e < 0: - u = f - v = 10 ** abs(e) - else: - u = f * 10 ** e - v = 1 - k = 0 - x = u // v - while True: - if x < MIN_SIG: - u <<= 1 - k -= 1 - elif x >= MAX_SIG: - v <<= 1 - k += 1 - else: - break - x = u // v - return ratio_to_float(u, v, k) - - -def ratio_to_float(u, v, k): - q, r = divmod(u, v) - v_r = v - r - z = Fp(q, k) - if r < v_r: - return z - elif r > v_r: - return next_float(z) - elif q % 2 == 0: - return z - else: - return next_float(z) - - -def next_float(z): - if z.sig == MAX_SIG: - return Fp(MIN_SIG, z.exp + 1) - else: - return Fp(z.sig + 1, z.exp) - - -def error(f, e, z): - decimal = f * Fraction(10) ** e - binary = z.sig * Fraction(2) ** z.exp - abs_err = abs(decimal - binary) - # The unit in the last place has value z.exp - ulp_err = abs_err / Fraction(2) ** z.exp - return float(ulp_err) - +from collections import deque HEADER = """ -//! Tables of approximations of powers of ten. +//! Pre-computed tables powers-of-5 for extended-precision representations. +//! +//! These tables enable fast scaling of the significant digits +//! of a float to the decimal exponent, with minimal rounding +//! errors, in a 128 or 192-bit representation. +//! //! DO NOT MODIFY: Generated by `src/etc/dec2flt_table.py` """ +STATIC_WARNING = """ +// Use static to avoid long compile times: Rust compiler errors +// can have the entire table compiled multiple times, and then +// emit code multiple times, even if it's stripped out in +// the final binary. +""" def main(): + min_exp = minimum_exponent(10) + max_exp = maximum_exponent(10) + bias = -minimum_exponent(5) + print(HEADER.strip()) print() - print_proper_powers() - print() - print_short_powers(32, 24) + print('pub const SMALLEST_POWER_OF_FIVE: i32 = {};'.format(min_exp)) + print('pub const LARGEST_POWER_OF_FIVE: i32 = {};'.format(max_exp)) + print('pub const N_POWERS_OF_FIVE: usize = ', end='') + print('(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;') print() - print_short_powers(64, 53) + print_proper_powers(min_exp, max_exp, bias) + + +def minimum_exponent(base): + return ceil(log(5e-324, base) - log(0xFFFFFFFFFFFFFFFF, base)) + +def maximum_exponent(base): + return floor(log(1.7976931348623157e+308, base)) -def print_proper_powers(): - MIN_E = -305 - MAX_E = 305 - e_range = range(MIN_E, MAX_E+1) + +def print_proper_powers(min_exp, max_exp, bias): + powers = deque() + + # Add negative exponents. + # 2^(2b)/(5^−q) with b=64 + int(math.ceil(log2(5^−q))) powers = [] - for e in e_range: - z = algorithm_m(1, e) - err = error(1, e, z) - assert err < 0.5 - powers.append(z) - print("pub const MIN_E: i16 = {};".format(MIN_E)) - print("pub const MAX_E: i16 = {};".format(MAX_E)) - print() - print("#[rustfmt::skip]") - typ = "([u64; {0}], [i16; {0}])".format(len(powers)) - print("pub static POWERS: ", typ, " = (", sep='') - print(" [") - for z in powers: - print(" 0x{:x},".format(z.sig)) - print(" ],") - print(" [") - for z in powers: - print(" {},".format(z.exp)) - print(" ],") - print(");") - - -def print_short_powers(num_bits, significand_size): - max_sig = 2**significand_size - 1 - # The fast path bails out for exponents >= ceil(log5(max_sig)) - max_e = int(ceil(log(max_sig, 5))) - e_range = range(max_e) - typ = "[f{}; {}]".format(num_bits, len(e_range)) - print("#[rustfmt::skip]") - print("pub const F", num_bits, "_SHORT_POWERS: ", typ, " = [", sep='') - for e in e_range: - print(" 1e{},".format(e)) - print("];") + for q in range(min_exp, 0): + power5 = 5 ** -q + z = 0 + while (1 << z) < power5: + z += 1 + if q >= -27: + b = z + 127 + c = 2 ** b // power5 + 1 + powers.append((c, q)) + else: + b = 2 * z + 2 * 64 + c = 2 ** b // power5 + 1 + # truncate + while c >= (1<<128): + c //= 2 + powers.append((c, q)) + + # Add positive exponents + for q in range(0, max_exp + 1): + power5 = 5 ** q + # move the most significant bit in position + while power5 < (1<<127): + power5 *= 2 + # *truncate* + while power5 >= (1<<128): + power5 //= 2 + powers.append((power5, q)) + + # Print the powers. + print(STATIC_WARNING.strip()) + print('#[rustfmt::skip]') + typ = '[(u64, u64); N_POWERS_OF_FIVE]' + print('pub static POWER_OF_FIVE_128: {} = ['.format(typ)) + lo_mask = (1 << 64) - 1 + for c, exp in powers: + hi = '0x{:x}'.format(c // (1 << 64)) + lo = '0x{:x}'.format(c % (1 << 64)) + value = ' ({}, {}), '.format(hi, lo) + comment = '// {}^{}'.format(5, exp) + print(value.ljust(46, ' ') + comment) + print('];') if __name__ == '__main__': diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py index a5a1824c84..292e91b4d5 100644 --- a/src/etc/gdb_lookup.py +++ b/src/etc/gdb_lookup.py @@ -5,7 +5,6 @@ from gdb_providers import * from rust_types import * -rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True) _gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION) gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else [] @@ -52,9 +51,10 @@ def lookup(valobj): return StdStringProvider(valobj) if rust_type == RustType.STD_OS_STRING: return StdOsStringProvider(valobj) - if rust_type == RustType.STD_STR and not rust_enabled: + if rust_type == RustType.STD_STR: return StdStrProvider(valobj) - + if rust_type == RustType.STD_SLICE: + return StdSliceProvider(valobj) if rust_type == RustType.STD_VEC: return StdVecProvider(valobj) if rust_type == RustType.STD_VEC_DEQUE: diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index f0ce13b269..33d26db547 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -85,6 +85,39 @@ class StdStrProvider: def display_hint(): return "string" +def _enumerate_array_elements(element_ptrs): + for (i, element_ptr) in enumerate(element_ptrs): + key = "[{}]".format(i) + element = element_ptr.dereference() + + try: + # rust-lang/rust#64343: passing deref expr to `str` allows + # catching exception on garbage pointer + str(element) + except RuntimeError: + yield key, "inaccessible" + + break + + yield key, element + +class StdSliceProvider: + def __init__(self, valobj): + self.valobj = valobj + self.length = int(valobj["length"]) + self.data_ptr = valobj["data_ptr"] + + def to_string(self): + return "{}(size={})".format(self.valobj.type, self.length) + + def children(self): + return _enumerate_array_elements( + self.data_ptr + index for index in xrange(self.length) + ) + + @staticmethod + def display_hint(): + return "array" class StdVecProvider: def __init__(self, valobj): @@ -96,19 +129,9 @@ class StdVecProvider: return "Vec(size={})".format(self.length) def children(self): - saw_inaccessible = False - for index in xrange(self.length): - element_ptr = self.data_ptr + index - if saw_inaccessible: - return - try: - # rust-lang/rust#64343: passing deref expr to `str` allows - # catching exception on garbage pointer - str(element_ptr.dereference()) - yield "[{}]".format(index), element_ptr.dereference() - except RuntimeError: - saw_inaccessible = True - yield str(index), "inaccessible" + return _enumerate_array_elements( + self.data_ptr + index for index in xrange(self.length) + ) @staticmethod def display_hint(): @@ -131,9 +154,9 @@ class StdVecDequeProvider: return "VecDeque(size={})".format(self.size) def children(self): - for index in xrange(0, self.size): - value = (self.data_ptr + ((self.tail + index) % self.cap)).dereference() - yield "[{}]".format(index), value + return _enumerate_array_elements( + (self.data_ptr + ((self.tail + index) % self.cap)) for index in xrange(self.size) + ) @staticmethod def display_hint(): diff --git a/src/etc/installer/README.md b/src/etc/installer/README.md index dbefe753be..cded3bbf7f 100644 --- a/src/etc/installer/README.md +++ b/src/etc/installer/README.md @@ -18,7 +18,7 @@ prefix. You can display these options by running: $ sudo ./install.sh --help -Read [The Book](http://doc.rust-lang.org/book/index.html) to learn how +Read [The Book](https://doc.rust-lang.org/book/index.html) to learn how to use Rust. Rust is primarily distributed under the terms of both the MIT license diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands index b8e6c6c0c8..4a1204ccc4 100644 --- a/src/etc/lldb_commands +++ b/src/etc/lldb_commands @@ -1,7 +1,7 @@ type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust -type summary add -F lldb_lookup.summary_lookup -e -x -h "^&str$" --category Rust -type summary add -F lldb_lookup.summary_lookup -e -x -h "^&\\[.+\\]$" --category Rust +type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust +type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 89280149a0..558536fa61 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -1,8 +1,8 @@ - {data_ptr,[length]s8} - data_ptr,[length]s8 + {(char*)data_ptr,[length]s8} + (char*)data_ptr,[length]s8 length @@ -15,7 +15,7 @@ - + {{ len={length} }} length @@ -25,23 +25,23 @@ - + () - + ({__0}) __0 - + ({__0}, {__1}) __0 __1 - + ({__0}, {__1}, {__2}) __0 @@ -49,7 +49,7 @@ __2 - + ({__0}, {__1}, {__2}, {__3}) __0 @@ -58,7 +58,7 @@ __3 - + ({__0}, {__1}, {__2}, {__3}, {__4}) __0 @@ -68,7 +68,7 @@ __4 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}) __0 @@ -79,7 +79,7 @@ __5 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}) __0 @@ -91,7 +91,7 @@ __6 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}) __0 @@ -104,7 +104,7 @@ __7 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}) __0 @@ -118,7 +118,7 @@ __8 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}) __0 @@ -133,7 +133,7 @@ __9 - + ({__0}, {__1}, {__2}, {__3}, {__4}, {__5}, {__6}, {__7}, {__8}, {__9}, ...) __0 @@ -149,8 +149,10 @@ ... + + - + {tag(),en} {tag(),en} {tag(),en} @@ -169,6 +171,9 @@ {tag(),en} + + {tag(),en} + variant0 variant1 variant2 @@ -188,8 +193,20 @@ - + + + {"$T2",sb} + + + {"$T2",sb} + + $T2 + + + + @@ -200,6 +217,9 @@ {"$T4",sb} + + {discriminant,en} + diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index 9cc60fc7b4..d001f40fcc 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -48,6 +48,7 @@ vec.len vec.buf.cap + {(char*)vec.buf.ptr.pointer,[vec.len]s8} vec.len @@ -57,22 +58,38 @@
+ {ptr.pointer->value} ptr.pointer->value + ptr.pointer->strong + ptr.pointer->weak + + {ptr.pointer->value} + + ptr.pointer->value + ptr.pointer->strong + ptr.pointer->weak + + + {ptr.pointer->data} ptr.pointer->data + ptr.pointer->strong + ptr.pointer->weak {ptr.pointer->data} ptr.pointer->data + ptr.pointer->strong + ptr.pointer->weak diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 1766777052..fa8ee2d70b 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -1,31 +1,163 @@ - - {{ Unique {pointer} }} + + {value.value} - pointer + value.value + + + + {value} + + value + + + + {value} + + value + + + + {value.value} + + "Unborrowed",sb + "Immutably borrowed",sb + "Mutably borrowed",sb + value.value + + + + {value} + + value - - {{ Shared {pointer} }} + + {value} - pointer + value - - None - Some({($T1 *)this}) + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + {__0} + + + + {__0} + + + + ({start}..{end}) + + + ({start}..) + + + ({start}..={end}) + + + (..{end}) + + + (..={end}) + + + + Pin({(void*)pointer}: {pointer}) - ($T1 *)this + pointer - {(void*) pointer} + NonNull({(void*) pointer}: {pointer}) + + pointer + + + + + Unique({(void*)pointer}: {pointer}) + + pointer + + + + + {(bool)v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + {v.value} + + + + {secs,d}s {nanos,d}ns - *pointer + secs,d + nanos,d - \ No newline at end of file + diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index 2c05f9d7c1..c7be0167de 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -41,7 +41,7 @@ n-- - ((tuple<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1 + ((tuple$<$T1, $T2>*)base.table.table.ctrl.pointer)[-(i + 1)].__1 i++ @@ -74,9 +74,10 @@ - {inner.data_ptr,s} + {(char*)inner.data_ptr} + {(char*)inner.data_ptr} inner.length @@ -101,4 +102,19 @@ + + + {(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]} + + + {(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]} + + + inner.inner.bytes.len + (char*)inner.inner.bytes.buf.ptr.pointer + + + + + diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py index b49fd19ed4..bbc945a7dd 100644 --- a/src/etc/rust_types.py +++ b/src/etc/rust_types.py @@ -34,8 +34,8 @@ class RustType(object): STD_STRING_REGEX = re.compile(r"^(alloc::(\w+::)+)String$") -STD_STR_REGEX = re.compile(r"^&str$") -STD_SLICE_REGEX = re.compile(r"^&\[.+\]$") +STD_STR_REGEX = re.compile(r"^&(mut )?str$") +STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.+\]$") STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::(\w+::)+)OsString$") STD_VEC_REGEX = re.compile(r"^(alloc::(\w+::)+)Vec<.+>$") STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::(\w+::)+)VecDeque<.+>$") diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml new file mode 100644 index 0000000000..8226e815c2 --- /dev/null +++ b/src/etc/test-float-parse/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "test-float-parse" +version = "0.1.0" +edition = "2018" +publish = false + +[workspace] + +[dependencies] +rand = "0.4" + +[lib] +name = "test_float_parse" diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py index 218552a459..cf7279534d 100644 --- a/src/etc/test-float-parse/runtests.py +++ b/src/etc/test-float-parse/runtests.py @@ -131,22 +131,20 @@ def write_errors(): exit_status = 101 -def rustc(test): - rs = test + '.rs' - exe = test + '.exe' # hopefully this makes it work on *nix - print("compiling", test) +def cargo(): + print("compiling tests") sys.stdout.flush() - check_call(['rustc', rs, '-o', exe]) + check_call(['cargo', 'build', '--release']) def run(test): global test_name test_name = test - t0 = time.clock() + t0 = time.perf_counter() msg("setting up supervisor") - exe = test + '.exe' - proc = Popen(exe, bufsize=1<<20 , stdin=PIPE, stdout=PIPE, stderr=PIPE) + command = ['cargo', 'run', '--bin', test, '--release'] + proc = Popen(command, bufsize=1<<20 , stdin=PIPE, stdout=PIPE, stderr=PIPE) done = multiprocessing.Value(ctypes.c_bool) queue = multiprocessing.Queue(maxsize=5)#(maxsize=1024) workers = [] @@ -166,7 +164,7 @@ def run(test): worker.join() msg("python is done") assert queue.empty(), "did not validate everything" - dt = time.clock() - t0 + dt = time.perf_counter() - t0 msg("took", round(dt, 3), "seconds") @@ -176,7 +174,7 @@ def interact(proc, queue): line = proc.stdout.readline() if not line: continue - assert line.endswith('\n'), "incomplete line: " + repr(line) + assert line.endswith(b'\n'), "incomplete line: " + repr(line) queue.put(line) n += 1 if n % UPDATE_EVERY_N == 0: @@ -185,7 +183,7 @@ def interact(proc, queue): rest, stderr = proc.communicate() if stderr: msg("rust stderr output:", stderr) - for line in rest.split('\n'): + for line in rest.split(b'\n'): if not line: continue queue.put(line) @@ -193,18 +191,19 @@ def interact(proc, queue): def main(): global MAILBOX - all_tests = [os.path.splitext(f)[0] for f in glob('*.rs') if not f.startswith('_')] + files = glob('src/bin/*.rs') + basenames = [os.path.basename(i) for i in files] + all_tests = [os.path.splitext(f)[0] for f in basenames if not f.startswith('_')] args = sys.argv[1:] if args: tests = [test for test in all_tests if test in args] - else + else: tests = all_tests if not tests: print("Error: No tests to run") sys.exit(1) # Compile first for quicker feedback - for test in tests: - rustc(test) + cargo() # Set up mailbox once for all tests MAILBOX = multiprocessing.Queue() mailman = threading.Thread(target=write_errors) @@ -251,7 +250,7 @@ def do_work(queue): else: continue bin64, bin32, text = line.rstrip().split() - validate(bin64, bin32, text) + validate(bin64, bin32, text.decode('utf-8')) def decode_binary64(x): @@ -331,7 +330,11 @@ SINGLE_ZERO_CUTOFF = MIN_SUBNORMAL_SINGLE / 2 SINGLE_INF_CUTOFF = MAX_SINGLE + 2 ** (MAX_ULP_SINGLE - 1) def validate(bin64, bin32, text): - double = decode_binary64(bin64) + try: + double = decode_binary64(bin64) + except AssertionError: + print(bin64, bin32, text) + raise single = decode_binary32(bin32) real = Fraction(text) diff --git a/src/etc/test-float-parse/few-ones.rs b/src/etc/test-float-parse/src/bin/few-ones.rs similarity index 87% rename from src/etc/test-float-parse/few-ones.rs rename to src/etc/test-float-parse/src/bin/few-ones.rs index 2d82918aab..6bb406a594 100644 --- a/src/etc/test-float-parse/few-ones.rs +++ b/src/etc/test-float-parse/src/bin/few-ones.rs @@ -1,6 +1,4 @@ -mod _common; - -use _common::validate; +use test_float_parse::validate; fn main() { let mut pow = vec![]; diff --git a/src/etc/test-float-parse/huge-pow10.rs b/src/etc/test-float-parse/src/bin/huge-pow10.rs similarity index 77% rename from src/etc/test-float-parse/huge-pow10.rs rename to src/etc/test-float-parse/src/bin/huge-pow10.rs index 9a16d9c602..722a24ffcd 100644 --- a/src/etc/test-float-parse/huge-pow10.rs +++ b/src/etc/test-float-parse/src/bin/huge-pow10.rs @@ -1,6 +1,4 @@ -mod _common; - -use _common::validate; +use test_float_parse::validate; fn main() { for e in 300..310 { diff --git a/src/etc/test-float-parse/long-fractions.rs b/src/etc/test-float-parse/src/bin/long-fractions.rs similarity index 88% rename from src/etc/test-float-parse/long-fractions.rs rename to src/etc/test-float-parse/src/bin/long-fractions.rs index 60cf85c4a6..c715bc1ac2 100644 --- a/src/etc/test-float-parse/long-fractions.rs +++ b/src/etc/test-float-parse/src/bin/long-fractions.rs @@ -1,7 +1,5 @@ -mod _common; - -use _common::validate; use std::char; +use test_float_parse::validate; fn main() { for n in 0..10 { diff --git a/src/etc/test-float-parse/many-digits.rs b/src/etc/test-float-parse/src/bin/many-digits.rs similarity index 93% rename from src/etc/test-float-parse/many-digits.rs rename to src/etc/test-float-parse/src/bin/many-digits.rs index 599986e20d..ba166fd560 100644 --- a/src/etc/test-float-parse/many-digits.rs +++ b/src/etc/test-float-parse/src/bin/many-digits.rs @@ -1,11 +1,9 @@ extern crate rand; -mod _common; - -use _common::{validate, SEED}; use rand::distributions::{Range, Sample}; use rand::{IsaacRng, Rng, SeedableRng}; use std::char; +use test_float_parse::{validate, SEED}; fn main() { let mut rnd = IsaacRng::from_seed(&SEED); diff --git a/src/etc/test-float-parse/rand-f64.rs b/src/etc/test-float-parse/src/bin/rand-f64.rs similarity index 89% rename from src/etc/test-float-parse/rand-f64.rs rename to src/etc/test-float-parse/src/bin/rand-f64.rs index 39ad63945c..6991e8be15 100644 --- a/src/etc/test-float-parse/rand-f64.rs +++ b/src/etc/test-float-parse/src/bin/rand-f64.rs @@ -1,10 +1,8 @@ extern crate rand; -mod _common; - -use _common::{validate, SEED}; use rand::{IsaacRng, Rng, SeedableRng}; use std::mem::transmute; +use test_float_parse::{validate, SEED}; fn main() { let mut rnd = IsaacRng::from_seed(&SEED); diff --git a/src/etc/test-float-parse/short-decimals.rs b/src/etc/test-float-parse/src/bin/short-decimals.rs similarity index 93% rename from src/etc/test-float-parse/short-decimals.rs rename to src/etc/test-float-parse/src/bin/short-decimals.rs index 8b9b6f78ae..49084eb35e 100644 --- a/src/etc/test-float-parse/short-decimals.rs +++ b/src/etc/test-float-parse/src/bin/short-decimals.rs @@ -1,6 +1,4 @@ -mod _common; - -use _common::validate; +use test_float_parse::validate; fn main() { // Skip e = 0 because small-u32 already does those. diff --git a/src/etc/test-float-parse/subnorm.rs b/src/etc/test-float-parse/src/bin/subnorm.rs similarity index 88% rename from src/etc/test-float-parse/subnorm.rs rename to src/etc/test-float-parse/src/bin/subnorm.rs index ba68d31e4e..ac88747eac 100644 --- a/src/etc/test-float-parse/subnorm.rs +++ b/src/etc/test-float-parse/src/bin/subnorm.rs @@ -1,7 +1,5 @@ -mod _common; - -use _common::validate; use std::mem::transmute; +use test_float_parse::validate; fn main() { for bits in 0u32..(1 << 21) { diff --git a/src/etc/test-float-parse/tiny-pow10.rs b/src/etc/test-float-parse/src/bin/tiny-pow10.rs similarity index 78% rename from src/etc/test-float-parse/tiny-pow10.rs rename to src/etc/test-float-parse/src/bin/tiny-pow10.rs index 43fad5b49e..fb6ba16638 100644 --- a/src/etc/test-float-parse/tiny-pow10.rs +++ b/src/etc/test-float-parse/src/bin/tiny-pow10.rs @@ -1,6 +1,4 @@ -mod _common; - -use _common::validate; +use test_float_parse::validate; fn main() { for e in 301..327 { diff --git a/src/etc/test-float-parse/u32-small.rs b/src/etc/test-float-parse/src/bin/u32-small.rs similarity index 69% rename from src/etc/test-float-parse/u32-small.rs rename to src/etc/test-float-parse/src/bin/u32-small.rs index 3ae62425ad..5ec9d1eea5 100644 --- a/src/etc/test-float-parse/u32-small.rs +++ b/src/etc/test-float-parse/src/bin/u32-small.rs @@ -1,6 +1,4 @@ -mod _common; - -use _common::validate; +use test_float_parse::validate; fn main() { for i in 0..(1 << 19) { diff --git a/src/etc/test-float-parse/u64-pow2.rs b/src/etc/test-float-parse/src/bin/u64-pow2.rs similarity index 90% rename from src/etc/test-float-parse/u64-pow2.rs rename to src/etc/test-float-parse/src/bin/u64-pow2.rs index 7e67e2b124..984e49200c 100644 --- a/src/etc/test-float-parse/u64-pow2.rs +++ b/src/etc/test-float-parse/src/bin/u64-pow2.rs @@ -1,6 +1,4 @@ -mod _common; - -use _common::validate; +use test_float_parse::validate; fn main() { for exp in 19..64 { diff --git a/src/etc/test-float-parse/_common.rs b/src/etc/test-float-parse/src/lib.rs similarity index 100% rename from src/etc/test-float-parse/_common.rs rename to src/etc/test-float-parse/src/lib.rs diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 5ce7594945..d5957b632d 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -21,6 +21,7 @@ regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } tracing = "0.1" tracing-tree = "0.1.9" +tera = { version = "1.10.0", default-features = false } [dependencies.tracing-subscriber] version = "0.2.13" diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a3f63ea104..e479d162b8 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { name: None, attrs: Default::default(), visibility: Inherited, - def_id: FakeDefId::new_fake(item_def_id.krate), + def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, kind: box ImplItem(Impl { span: Span::dummy(), unsafety: hir::Unsafety::Normal, @@ -353,12 +353,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let (poly_trait, output) = (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned()); let new_ty = match poly_trait.trait_ { - Type::ResolvedPath { - ref path, - ref param_names, - ref did, - ref is_generic, - } => { + Type::ResolvedPath { ref path, ref did, ref is_generic } => { let mut new_path = path.clone(); let last_segment = new_path.segments.pop().expect("segments were empty"); @@ -395,7 +390,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { Type::ResolvedPath { path: new_path, - param_names: param_names.clone(), did: *did, is_generic: *is_generic, } @@ -414,7 +408,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut bounds_vec = bounds.into_iter().collect(); self.sort_where_bounds(&mut bounds_vec); - Some(WherePredicate::BoundPredicate { ty, bounds: bounds_vec }) + Some(WherePredicate::BoundPredicate { + ty, + bounds: bounds_vec, + bound_params: Vec::new(), + }) }) .chain( lifetime_to_bounds.into_iter().filter(|&(_, ref bounds)| !bounds.is_empty()).map( @@ -492,7 +490,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } let p = p.unwrap(); match p { - WherePredicate::BoundPredicate { ty, mut bounds } => { + WherePredicate::BoundPredicate { ty, mut bounds, .. } => { // Writing a projection trait bound of the form // ::Name : ?Sized // is illegal, because ?Sized bounds can only @@ -566,7 +564,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match **trait_ { Type::ResolvedPath { path: ref trait_path, - ref param_names, ref did, ref is_generic, } => { @@ -613,7 +610,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { PolyTrait { trait_: Type::ResolvedPath { path: new_trait_path, - param_names: param_names.clone(), did: *did, is_generic: *is_generic, }, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 3f2fae1aca..8f74a48547 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -96,9 +96,9 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { name: None, attrs: Default::default(), visibility: Inherited, - def_id: FakeDefId::new_fake(item_def_id.krate), + def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, kind: box ImplItem(Impl { - span: self.cx.tcx.def_span(impl_def_id).clean(self.cx), + span: Span::from_rustc_span(self.cx.tcx.def_span(impl_def_id)), unsafety: hir::Unsafety::Normal, generics: ( self.cx.tcx.generics_of(impl_def_id), diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index 34b9cbcb67..275d1b3ebd 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -2,8 +2,8 @@ use super::*; use rustc_ast::attr; use rustc_ast::Path; +use rustc_span::create_default_session_globals_then; use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::with_default_session_globals; use rustc_span::DUMMY_SP; fn word_cfg(s: &str) -> Cfg { @@ -52,7 +52,7 @@ macro_rules! dummy_meta_item_list { #[test] fn test_cfg_not() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { assert_eq!(!Cfg::False, Cfg::True); assert_eq!(!Cfg::True, Cfg::False); assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test")))); @@ -70,7 +70,7 @@ fn test_cfg_not() { #[test] fn test_cfg_and() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mut x = Cfg::False; x &= Cfg::True; assert_eq!(x, Cfg::False); @@ -154,7 +154,7 @@ fn test_cfg_and() { #[test] fn test_cfg_or() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mut x = Cfg::True; x |= Cfg::False; assert_eq!(x, Cfg::True); @@ -238,7 +238,7 @@ fn test_cfg_or() { #[test] fn test_parse_ok() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mi = dummy_meta_item_word("all"); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); @@ -271,7 +271,7 @@ fn test_parse_ok() { #[test] fn test_parse_err() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP); assert!(Cfg::parse(&mi).is_err()); @@ -303,7 +303,7 @@ fn test_parse_err() { #[test] fn test_render_short_html() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { assert_eq!(word_cfg("unix").render_short_html(), "Unix"); assert_eq!(name_value_cfg("target_os", "macos").render_short_html(), "macOS"); assert_eq!(name_value_cfg("target_pointer_width", "16").render_short_html(), "16-bit"); @@ -358,7 +358,7 @@ fn test_render_short_html() { #[test] fn test_render_long_html() { - with_default_session_globals(|| { + create_default_session_globals_then(|| { assert_eq!( word_cfg("unix").render_long_html(), "This is supported on Unix only." @@ -442,7 +442,7 @@ fn test_render_long_html() { fn test_simplify_with() { // This is a tiny subset of things that could be simplified, but it likely covers 90% of // real world usecases well. - with_default_session_globals(|| { + create_default_session_globals_then(|| { let foo = word_cfg("foo"); let bar = word_cfg("bar"); let baz = word_cfg("baz"); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 111827aacd..b3b89e6e67 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -13,9 +13,10 @@ use rustc_metadata::creader::LoadedMacro; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::Span; -use crate::clean::{self, Attributes, AttributesExt, FakeDefId, GetDefId, ToSource}; +use crate::clean::{ + self, utils, Attributes, AttributesExt, GetDefId, ItemId, NestedAttributesExt, Type, +}; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -40,6 +41,7 @@ type Attrs<'hir> = rustc_middle::ty::Attributes<'hir>; crate fn try_inline( cx: &mut DocContext<'_>, parent_module: DefId, + import_def_id: Option, res: Res, name: Symbol, attrs: Option>, @@ -107,7 +109,7 @@ crate fn try_inline( clean::ConstantItem(build_const(cx, did)) } Res::Def(DefKind::Macro(kind), did) => { - let mac = build_macro(cx, did, name); + let mac = build_macro(cx, did, name, import_def_id); let type_kind = match kind { MacroKind::Bang => ItemType::Macro, @@ -122,14 +124,13 @@ crate fn try_inline( let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone); cx.inlined.insert(did.into()); - ret.push(clean::Item::from_def_id_and_attrs_and_parts( - did, - Some(name), - kind, - box attrs, - cx, - cfg, - )); + let mut item = + clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, box attrs, cx, cfg); + if let Some(import_def_id) = import_def_id { + // The visibility needs to reflect the one from the reexport and not from the "source" DefId. + item.visibility = cx.tcx.visibility(import_def_id).clean(cx); + } + ret.push(item); Some(ret) } @@ -420,6 +421,21 @@ crate fn build_impl( if trait_.def_id() == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } + + // Return if the trait itself or any types of the generic parameters are doc(hidden). + let mut stack: Vec<&Type> = trait_.iter().collect(); + stack.push(&for_); + while let Some(ty) = stack.pop() { + if let Some(did) = ty.def_id() { + if cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { + return; + } + } + if let Some(generics) = ty.generics() { + stack.extend(generics); + } + } + if let Some(trait_did) = trait_.def_id() { record_extern_trait(cx, trait_did); } @@ -467,10 +483,11 @@ fn build_module( } if let Res::PrimTy(p) = item.res { // Primitive types can't be inlined so generate an import instead. + let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { name: None, attrs: box clean::Attributes::default(), - def_id: FakeDefId::new_fake(did.krate), + def_id: ItemId::Primitive(prim_ty, did.krate), visibility: clean::Public, kind: box clean::ImportItem(clean::Import::new_simple( item.ident.name, @@ -479,7 +496,7 @@ fn build_module( global: false, res: item.res, segments: vec![clean::PathSegment { - name: clean::PrimitiveType::from(p).as_sym(), + name: prim_ty.as_sym(), args: clean::GenericArgs::AngleBracketed { args: Vec::new(), bindings: Vec::new(), @@ -492,7 +509,9 @@ fn build_module( )), cfg: None, }); - } else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) { + } else if let Some(i) = + try_inline(cx, did, None, item.res, item.ident.name, None, visited) + { items.extend(i) } } @@ -526,27 +545,29 @@ fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::St } } -fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::ItemKind { - let imported_from = cx.tcx.crate_name(did.krate); - match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) { - LoadedMacro::MacroDef(def, _) => { - let matchers: Vec = if let ast::ItemKind::MacroDef(ref def) = def.kind { - let tts: Vec<_> = def.body.inner_tokens().into_trees().collect(); - tts.chunks(4).map(|arm| arm[0].span()).collect() +fn build_macro( + cx: &mut DocContext<'_>, + def_id: DefId, + name: Symbol, + import_def_id: Option, +) -> clean::ItemKind { + let imported_from = cx.tcx.crate_name(def_id.krate); + match cx.enter_resolver(|r| r.cstore().load_macro_untracked(def_id, cx.sess())) { + LoadedMacro::MacroDef(item_def, _) => { + if let ast::ItemKind::MacroDef(ref def) = item_def.kind { + clean::MacroItem(clean::Macro { + source: utils::display_macro_source( + cx, + name, + def, + def_id, + cx.tcx.visibility(import_def_id.unwrap_or(def_id)), + ), + imported_from: Some(imported_from), + }) } else { unreachable!() - }; - - let source = format!( - "macro_rules! {} {{\n{}}}", - name.clean(cx), - matchers - .iter() - .map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) }) - .collect::() - ); - - clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) }) + } } LoadedMacro::ProcMacro(ext) => clean::ProcMacroItem(clean::ProcMacro { kind: ext.macro_kind(), @@ -566,9 +587,11 @@ fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::Item fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics { for pred in &mut g.where_predicates { match *pred { - clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref mut bounds } - if *s == kw::SelfUpper => - { + clean::WherePredicate::BoundPredicate { + ty: clean::Generic(ref s), + ref mut bounds, + .. + } if *s == kw::SelfUpper => { bounds.retain(|bound| match *bound { clean::GenericBound::TraitBound( clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. }, @@ -591,6 +614,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: .. }, ref bounds, + .. } => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did), _ => true, }); @@ -605,7 +629,7 @@ fn separate_supertrait_bounds( ) -> (clean::Generics, Vec) { let mut ty_bounds = Vec::new(); g.where_predicates.retain(|pred| match *pred { - clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds } + clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. } if *s == kw::SelfUpper => { ty_bounds.extend(bounds.iter().cloned()); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d1c18821ea..1a2852dc6c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -14,18 +14,20 @@ use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::middle::resolve_lifetime as rl; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::subst::{InternalSubsts, Subst}; -use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, DefIdTree, Lift, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn}; use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, ExpnKind}; +use rustc_target::spec::abi::Abi; +use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety; use rustc_typeck::hir_ty_to_ty; use std::collections::hash_map::Entry; @@ -83,12 +85,6 @@ impl, U> Clean> for Option { } } -impl Clean for CrateNum { - fn clean(&self, _cx: &mut DocContext<'_>) -> ExternalCrate { - ExternalCrate { crate_num: *self } - } -} - impl Clean for doctree::Module<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let mut items: Vec = vec![]; @@ -178,7 +174,7 @@ impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); - ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false } + ResolvedPath { path, did: trait_ref.def_id, is_generic: false } } } @@ -225,20 +221,6 @@ impl<'tcx> Clean for ty::PolyTraitRef<'tcx> { } } -impl<'tcx> Clean>> for InternalSubsts<'tcx> { - fn clean(&self, cx: &mut DocContext<'_>) -> Option> { - let mut v = Vec::new(); - v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives)); - v.extend(self.types().map(|t| { - GenericBound::TraitBound( - PolyTrait { trait_: t.clean(cx), generic_params: Vec::new() }, - hir::TraitBoundModifier::None, - ) - })); - if !v.is_empty() { Some(v) } else { None } - } -} - impl Clean for hir::Lifetime { fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime { let def = cx.tcx.named_region(self.hir_id); @@ -294,12 +276,6 @@ impl Clean for hir::ConstArg { } } -impl Clean for ty::GenericParamDef { - fn clean(&self, _cx: &mut DocContext<'_>) -> Lifetime { - Lifetime(self.name) - } -} - impl Clean> for ty::RegionKind { fn clean(&self, _cx: &mut DocContext<'_>) -> Option { match *self { @@ -328,6 +304,7 @@ impl Clean for hir::WherePredicate<'_> { hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate { ty: wbp.bounded_ty.clean(cx), bounds: wbp.bounds.clean(cx), + bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(), }, hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate { @@ -350,12 +327,12 @@ impl<'a> Clean> for ty::Predicate<'a> { ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx), ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx), ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)), + ty::PredicateKind::ConstEvaluatable(..) => None, ty::PredicateKind::Subtype(..) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), } @@ -368,6 +345,7 @@ impl<'a> Clean for ty::PolyTraitPredicate<'a> { WherePredicate::BoundPredicate { ty: poly_trait_ref.skip_binder().self_ty().clean(cx), bounds: vec![poly_trait_ref.clean(cx)], + bound_params: Vec::new(), } } } @@ -400,6 +378,7 @@ impl<'tcx> Clean> for ty::OutlivesPredicate, ty: Some(WherePredicate::BoundPredicate { ty: ty.clean(cx), bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))], + bound_params: Vec::new(), }) } } @@ -433,8 +412,23 @@ impl Clean for ty::GenericParamDef { let (name, kind) = match self.kind { ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime), ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { - let default = - if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None }; + let default = if has_default { + let mut default = cx.tcx.type_of(self.def_id).clean(cx); + + // We need to reassign the `self_def_id`, if there's a parent (which is the + // `Self` type), so we can properly render `` casts, because the + // information about which type `Self` is, is only present here, but not in + // the cleaning process of the type itself. To resolve this and have the + // `self_def_id` set, we override it here. + // See https://github.com/rust-lang/rust/issues/85454 + if let QPath { ref mut self_def_id, .. } = default { + *self_def_id = cx.tcx.parent(self.def_id); + } + + Some(default) + } else { + None + }; ( self.name, GenericParamDefKind::Type { @@ -565,7 +559,9 @@ impl Clean for hir::Generics<'_> { // to where predicates when such cases occur. for where_pred in &mut generics.where_predicates { match *where_pred { - WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => { + WherePredicate::BoundPredicate { + ty: Generic(ref name), ref mut bounds, .. + } => { if bounds.is_empty() { for param in &mut generics.params { match param.kind { @@ -719,7 +715,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx // handled in cleaning associated types let mut sized_params = FxHashSet::default(); where_predicates.retain(|pred| match *pred { - WP::BoundPredicate { ty: Generic(ref g), ref bounds } => { + WP::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => { if bounds.iter().any(|b| b.is_sized_bound(cx)) { sized_params.insert(*g); false @@ -739,6 +735,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx where_predicates.push(WP::BoundPredicate { ty: Type::Generic(tp.name), bounds: vec![GenericBound::maybe_sized(cx)], + bound_params: Vec::new(), }) } } @@ -1115,6 +1112,7 @@ impl Clean for ty::AssocItem { WherePredicate::BoundPredicate { ty: QPath { ref name, ref self_type, ref trait_, .. }, ref bounds, + .. } => (name, self_type, trait_, bounds), _ => return None, }; @@ -1369,24 +1367,9 @@ impl Clean for hir::Ty<'_> { } TyKind::Path(_) => clean_qpath(&self, cx), TyKind::TraitObject(ref bounds, ref lifetime, _) => { - match bounds[0].clean(cx).trait_ { - ResolvedPath { path, param_names: None, did, is_generic } => { - let mut bounds: Vec = bounds[1..] - .iter() - .map(|bound| { - self::GenericBound::TraitBound( - bound.clean(cx), - hir::TraitBoundModifier::None, - ) - }) - .collect(); - if !lifetime.is_elided() { - bounds.push(self::GenericBound::Outlives(lifetime.clean(cx))); - } - ResolvedPath { path, param_names: Some(bounds), did, is_generic } - } - _ => Infer, // shouldn't happen - } + let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect(); + let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None }; + DynTrait(bounds, lifetime) } TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyKind::Infer | TyKind::Err => Infer, @@ -1469,7 +1452,7 @@ impl<'tcx> Clean for Ty<'tcx> { }; inline::record_extern_fqn(cx, did, kind); let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs); - ResolvedPath { path, param_names: None, did, is_generic: false } + ResolvedPath { path, did, is_generic: false } } ty::Foreign(did) => { inline::record_extern_fqn(cx, did, ItemType::ForeignType); @@ -1481,7 +1464,7 @@ impl<'tcx> Clean for Ty<'tcx> { vec![], InternalSubsts::empty(), ); - ResolvedPath { path, param_names: None, did, is_generic: false } + ResolvedPath { path, did, is_generic: false } } ty::Dynamic(ref obj, ref reg) => { // HACK: pick the first `did` as the `did` of the trait object. Someone @@ -1499,28 +1482,19 @@ impl<'tcx> Clean for Ty<'tcx> { inline::record_extern_fqn(cx, did, ItemType::Trait); - let mut param_names = vec![]; - if let Some(b) = reg.clean(cx) { - param_names.push(GenericBound::Outlives(b)); - } + let lifetime = reg.clean(cx); + let mut bounds = vec![]; + for did in dids { let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, ItemType::Trait); - let bound = GenericBound::TraitBound( - PolyTrait { - trait_: ResolvedPath { - path, - param_names: None, - did, - is_generic: false, - }, - generic_params: Vec::new(), - }, - hir::TraitBoundModifier::None, - ); - param_names.push(bound); + let bound = PolyTrait { + trait_: ResolvedPath { path, did, is_generic: false }, + generic_params: Vec::new(), + }; + bounds.push(bound); } let mut bindings = vec![]; @@ -1533,7 +1507,15 @@ impl<'tcx> Clean for Ty<'tcx> { let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs); - ResolvedPath { path, param_names: Some(param_names), did, is_generic: false } + bounds.insert( + 0, + PolyTrait { + trait_: ResolvedPath { path, did, is_generic: false }, + generic_params: Vec::new(), + }, + ); + + DynTrait(bounds, lifetime) } ty::Tuple(ref t) => { Tuple(t.iter().map(|t| t.expect_ty()).collect::>().clean(cx)) @@ -1756,12 +1738,6 @@ impl Clean for hir::VariantData<'_> { } } -impl Clean for rustc_span::Span { - fn clean(&self, _cx: &mut DocContext<'_>) -> Span { - Span::from_rustc_span(*self) - } -} - impl Clean for hir::Path<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Path { Path { @@ -1806,20 +1782,6 @@ impl Clean for hir::PathSegment<'_> { } } -impl Clean for Ident { - #[inline] - fn clean(&self, cx: &mut DocContext<'_>) -> String { - self.name.clean(cx) - } -} - -impl Clean for Symbol { - #[inline] - fn clean(&self, _: &mut DocContext<'_>) -> String { - self.to_string() - } -} - impl Clean for hir::BareFnTy<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, |cx| { @@ -2003,6 +1965,7 @@ fn clean_extern_crate( 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()), res, name, Some(attrs), @@ -2058,7 +2021,8 @@ fn clean_use_statement( // forcefully don't inline if this is not public or if the // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. - let mut denied = !import.vis.node.is_pub() + let mut denied = !(import.vis.node.is_pub() + || (cx.render_options.document_private && import.vis.node.is_pub_restricted())) || pub_underscore || attrs.iter().any(|a| { a.has_name(sym::doc) @@ -2094,17 +2058,19 @@ fn clean_use_statement( } if !denied { let mut visited = FxHashSet::default(); + let import_def_id = import.def_id.to_def_id(); if let Some(mut items) = inline::try_inline( cx, cx.tcx.parent_module(import.hir_id()).to_def_id(), + Some(import_def_id), path.res, name, Some(attrs), &mut visited, ) { items.push(Item::from_def_id_and_parts( - import.def_id.to_def_id(), + import_def_id, None, ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), cx, @@ -2132,7 +2098,11 @@ impl Clean for (&hir::ForeignItem<'_>, Option) { decl, generics, header: hir::FnHeader { - unsafety: hir::Unsafety::Unsafe, + unsafety: if abi == Abi::RustIntrinsic { + intrinsic_operation_unsafety(item.ident.name) + } else { + hir::Unsafety::Unsafe + }, abi, constness: hir::Constness::NotConst, asyncness: hir::IsAsync::NotAsync, @@ -2159,46 +2129,15 @@ impl Clean for (&hir::MacroDef<'_>, Option) { fn clean(&self, cx: &mut DocContext<'_>) -> Item { let (item, renamed) = self; let name = renamed.unwrap_or(item.ident.name); - let tts = item.ast.body.inner_tokens().trees().collect::>(); - // Extract the spans of all matchers. They represent the "interface" of the macro. - let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect::>(); - let source = if item.ast.macro_rules { - format!( - "macro_rules! {} {{\n{}}}", - name, - matchers - .iter() - .map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) }) - .collect::(), - ) - } else { - let vis = item.vis.clean(cx); - let def_id = item.def_id.to_def_id(); - - if matchers.len() <= 1 { - format!( - "{}macro {}{} {{\n ...\n}}", - vis.to_src_with_space(cx.tcx, def_id), - name, - matchers.iter().map(|span| span.to_src(cx)).collect::(), - ) - } else { - format!( - "{}macro {} {{\n{}}}", - vis.to_src_with_space(cx.tcx, def_id), - name, - matchers - .iter() - .map(|span| { format!(" {} => {{ ... }},\n", span.to_src(cx)) }) - .collect::(), - ) - } - }; + let def_id = item.def_id.to_def_id(); Item::from_hir_id_and_parts( item.hir_id(), Some(name), - MacroItem(Macro { source, imported_from: None }), + MacroItem(Macro { + source: display_macro_source(cx, name, &item.ast, def_id, &item.vis), + imported_from: None, + }), cx, ) } @@ -2222,27 +2161,3 @@ impl Clean for hir::TypeBindingKind<'_> { } } } - -enum SimpleBound { - TraitBound(Vec, Vec, Vec, hir::TraitBoundModifier), - Outlives(Lifetime), -} - -impl From for SimpleBound { - fn from(bound: GenericBound) -> Self { - match bound.clone() { - GenericBound::Outlives(l) => SimpleBound::Outlives(l), - GenericBound::TraitBound(t, mod_) => match t.trait_ { - Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound( - path.segments, - param_names.map_or_else(Vec::new, |v| { - v.iter().map(|p| SimpleBound::from(p.clone())).collect() - }), - t.generic_params, - mod_, - ), - _ => panic!("Unexpected bound {:?}", bound), - }, - } - } -} diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index d4d0a8ce24..3ec0a22a2c 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -24,16 +24,20 @@ use crate::core::DocContext; crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { // First, partition the where clause into its separate components - let mut params: BTreeMap<_, Vec<_>> = BTreeMap::new(); + let mut params: BTreeMap<_, (Vec<_>, Vec<_>)> = BTreeMap::new(); 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 } => match ty { - clean::Generic(s) => params.entry(s).or_default().extend(bounds), - t => tybounds.push((t, bounds)), + 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::RegionPredicate { lifetime, bounds } => { lifetimes.push((lifetime, bounds)); @@ -54,7 +58,7 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { clean::Generic(s) => s, _ => return true, }; - let bounds = match params.get_mut(generic) { + let (bounds, _) = match params.get_mut(generic) { Some(bound) => bound, None => return true, }; @@ -67,10 +71,16 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { clauses.extend( lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }), ); - clauses.extend( - params.into_iter().map(|(k, v)| WP::BoundPredicate { ty: clean::Generic(k), bounds: v }), - ); - clauses.extend(tybounds.into_iter().map(|(ty, bounds)| WP::BoundPredicate { ty, 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 } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 6a7c3f8caa..2fd2d14bca 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1,4 +1,4 @@ -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use std::default::Default; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; @@ -48,73 +48,68 @@ use self::ItemKind::*; use self::SelfTy::*; use self::Type::*; -crate type FakeDefIdSet = FxHashSet; +crate type ItemIdSet = FxHashSet; -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -crate enum FakeDefId { - Real(DefId), - Fake(DefIndex, CrateNum), +#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] +crate enum ItemId { + /// A "normal" item that uses a [`DefId`] for identification. + DefId(DefId), + /// Identifier that is used for auto traits. + Auto { trait_: DefId, for_: DefId }, + /// Identifier that is used for blanket implementations. + Blanket { impl_id: DefId, for_: DefId }, + /// Identifier for primitive types. + Primitive(PrimitiveType, CrateNum), } -impl FakeDefId { - #[cfg(parallel_compiler)] - crate fn new_fake(crate: CrateNum) -> Self { - unimplemented!("") - } - - #[cfg(not(parallel_compiler))] - crate fn new_fake(krate: CrateNum) -> Self { - thread_local!(static FAKE_DEF_ID_COUNTER: Cell = Cell::new(0)); - let id = FAKE_DEF_ID_COUNTER.with(|id| { - let tmp = id.get(); - id.set(tmp + 1); - tmp - }); - Self::Fake(DefIndex::from(id), krate) - } - +impl ItemId { #[inline] crate fn is_local(self) -> bool { match self { - FakeDefId::Real(id) => id.is_local(), - FakeDefId::Fake(_, krate) => krate == LOCAL_CRATE, + ItemId::Auto { for_: id, .. } + | ItemId::Blanket { for_: id, .. } + | ItemId::DefId(id) => id.is_local(), + ItemId::Primitive(_, krate) => krate == LOCAL_CRATE, } } #[inline] #[track_caller] - crate fn expect_real(self) -> rustc_hir::def_id::DefId { - self.as_real().unwrap_or_else(|| panic!("FakeDefId::expect_real: `{:?}` isn't real", self)) + crate fn expect_def_id(self) -> DefId { + self.as_def_id() + .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self)) } #[inline] - crate fn as_real(self) -> Option { + crate fn as_def_id(self) -> Option { match self { - FakeDefId::Real(id) => Some(id), - FakeDefId::Fake(_, _) => None, + ItemId::DefId(id) => Some(id), + _ => None, } } #[inline] crate fn krate(self) -> CrateNum { match self { - FakeDefId::Real(id) => id.krate, - FakeDefId::Fake(_, krate) => krate, + ItemId::Auto { for_: id, .. } + | ItemId::Blanket { for_: id, .. } + | ItemId::DefId(id) => id.krate, + ItemId::Primitive(_, krate) => krate, } } #[inline] crate fn index(self) -> Option { match self { - FakeDefId::Real(id) => Some(id.index), - FakeDefId::Fake(_, _) => None, + ItemId::DefId(id) => Some(id.index), + _ => None, } } } -impl From for FakeDefId { +impl From for ItemId { fn from(id: DefId) -> Self { - Self::Real(id) + Self::DefId(id) } } @@ -123,7 +118,7 @@ crate struct Crate { crate name: Symbol, crate src: FileName, crate module: Item, - crate externs: Vec<(CrateNum, ExternalCrate)>, + crate externs: Vec, crate primitives: ThinVec<(DefId, PrimitiveType)>, // These are later on moved into `CACHEKEY`, leaving the map empty. // Only here so that they can be filtered through the rustdoc passes. @@ -138,14 +133,14 @@ crate struct TraitWithExtraInfo { crate is_notable: bool, } -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] crate struct ExternalCrate { crate crate_num: CrateNum, } impl ExternalCrate { #[inline] - fn def_id(&self) -> DefId { + crate fn def_id(&self) -> DefId { DefId { krate: self.crate_num, index: CRATE_DEF_INDEX } } @@ -338,14 +333,14 @@ crate struct Item { /// Information about this item that is specific to what kind of item it is. /// E.g., struct vs enum vs function. crate kind: Box, - crate def_id: FakeDefId, + crate def_id: ItemId, crate cfg: Option>, } // `Item` 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!(Item, 48); +rustc_data_structures::static_assert_size!(Item, 56); crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span { Span::from_rustc_span(def_id.as_local().map_or_else( @@ -359,19 +354,19 @@ crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span { impl Item { crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> { - if self.is_fake() { None } else { tcx.lookup_stability(self.def_id.expect_real()) } + self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did)) } crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> { - if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id.expect_real()) } + self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did)) } crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option { - if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id.expect_real()) } + self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did)) } crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool { - if self.is_fake() { false } else { tcx.get_attrs(self.def_id.expect_real()).inner_docs() } + self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false) } crate fn span(&self, tcx: TyCtxt<'_>) -> Span { @@ -383,10 +378,8 @@ impl Item { kind { *span - } else if self.is_fake() { - Span::dummy() } else { - rustc_span(self.def_id.expect_real(), tcx) + self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy()) } } @@ -466,7 +459,7 @@ impl Item { .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| { match did { Some(did) => { - if let Some((mut href, ..)) = href(did.clone(), cx) { + if let Ok((mut href, ..)) = href(did.clone(), cx) { if let Some(ref fragment) = *fragment { href.push('#'); href.push_str(fragment); @@ -523,8 +516,35 @@ impl Item { .collect() } + /// Find a list of all link names, without finding their href. + /// + /// This is used for generating summary text, which does not include + /// the link text, but does need to know which `[]`-bracketed names + /// are actually links. + crate fn link_names(&self, cache: &Cache) -> Vec { + cache + .intra_doc_links + .get(&self.def_id) + .map_or(&[][..], |v| v.as_slice()) + .iter() + .filter_map(|ItemLink { link: s, link_text, did, fragment }| { + // FIXME(83083): using fragments as a side-channel for + // primitive names is very unfortunate + if did.is_some() || fragment.is_some() { + Some(RenderedLink { + original_text: s.clone(), + new_text: link_text.clone(), + href: String::new(), + }) + } else { + None + } + }) + .collect() + } + crate fn is_crate(&self) -> bool { - self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX) + self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX) } crate fn is_mod(&self) -> bool { self.type_() == ItemType::Module @@ -635,10 +655,6 @@ impl Item { _ => false, } } - - crate fn is_fake(&self) -> bool { - matches!(self.def_id, FakeDefId::Fake(_, _)) - } } #[derive(Clone, Debug)] @@ -1141,7 +1157,7 @@ impl GenericBound { inline::record_extern_fqn(cx, did, ItemType::Trait); GenericBound::TraitBound( PolyTrait { - trait_: ResolvedPath { path, param_names: None, did, is_generic: false }, + trait_: ResolvedPath { path, did, is_generic: false }, generic_params: Vec::new(), }, hir::TraitBoundModifier::Maybe, @@ -1193,7 +1209,7 @@ impl Lifetime { #[derive(Clone, Debug)] crate enum WherePredicate { - BoundPredicate { ty: Type, bounds: Vec }, + BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, EqPredicate { lhs: Type, rhs: Type }, } @@ -1407,11 +1423,12 @@ crate enum Type { /// Structs/enums/traits (most that would be an `hir::TyKind::Path`). ResolvedPath { path: Path, - param_names: Option>, did: DefId, /// `true` if is a `T::Name` path for associated types. is_generic: bool, }, + /// `dyn for<'a> Trait<'a> + Send + 'static` + DynTrait(Vec, Option), /// For parameterized types, so the consumer of the JSON don't go /// looking for types which don't exist anywhere. Generic(Symbol), @@ -1598,6 +1615,7 @@ impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option { let t: PrimitiveType = match *self { ResolvedPath { did, .. } => return Some(did.into()), + DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 706a56fbcb..bdd5350aab 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -1,12 +1,15 @@ use crate::clean::auto_trait::AutoTraitFinder; use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::{ - inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, - Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, + inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, + ItemKind, Lifetime, Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, + TypeBinding, Visibility, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; +use rustc_ast as ast; +use rustc_ast::tokenstream::TokenTree; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -14,6 +17,7 @@ use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; +use std::fmt::Write as _; use std::mem; #[cfg(test)] @@ -30,12 +34,12 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { cx.cache.owned_box_did = cx.tcx.lang_items().owned_box(); let mut externs = Vec::new(); - for &cnum in cx.tcx.crates().iter() { - externs.push((cnum, cnum.clean(cx))); + for &cnum in cx.tcx.crates(()).iter() { + externs.push(ExternalCrate { crate_num: cnum }); // Analyze doc-reachability for extern items LibEmbargoVisitor::new(cx).visit_lib(cnum); } - externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); + externs.sort_unstable_by_key(|e| e.crate_num); // Clean the crate, translating the entire librustc_ast AST to one that is // understood by rustdoc. @@ -57,7 +61,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { _ => unreachable!(), } - let local_crate = LOCAL_CRATE.clean(cx); + let local_crate = ExternalCrate { crate_num: LOCAL_CRATE }; let src = local_crate.src(cx.tcx); let name = local_crate.name(cx.tcx); let primitives = local_crate.primitives(cx.tcx); @@ -163,8 +167,18 @@ pub(super) fn external_path( crate fn strip_type(ty: Type) -> Type { match ty { - Type::ResolvedPath { path, param_names, did, is_generic } => { - Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic } + Type::ResolvedPath { path, did, is_generic } => { + Type::ResolvedPath { path: strip_path(&path), did, is_generic } + } + Type::DynTrait(mut bounds, lt) => { + let first = bounds.remove(0); + let stripped_trait = strip_type(first.trait_); + + bounds.insert( + 0, + PolyTrait { trait_: stripped_trait, generic_params: first.generic_params }, + ); + Type::DynTrait(bounds, lt) } Type::Tuple(inner_tys) => { Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect()) @@ -238,22 +252,6 @@ crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret: } } -crate trait ToSource { - fn to_src(&self, cx: &DocContext<'_>) -> String; -} - -impl ToSource for rustc_span::Span { - fn to_src(&self, cx: &DocContext<'_>) -> String { - debug!("converting span {:?} to snippet", self); - let sn = match cx.sess().source_map().span_to_snippet(*self) { - Ok(x) => x, - Err(_) => String::new(), - }; - debug!("got snippet {}", sn); - sn - } -} - crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { use rustc_hir::*; debug!("trying to get a name from pattern: {:?}", p); @@ -262,17 +260,12 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { PatKind::Wild | PatKind::Struct(..) => return kw::Underscore, PatKind::Binding(_, _, ident, _) => return ident.name, PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), - PatKind::Or(ref pats) => pats - .iter() - .map(|p| name_from_pat(&**p).to_string()) - .collect::>() - .join(" | "), + PatKind::Or(ref pats) => { + pats.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(" | ") + } PatKind::Tuple(ref elts, _) => format!( "({})", - elts.iter() - .map(|p| name_from_pat(&**p).to_string()) - .collect::>() - .join(", ") + elts.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(", ") ), PatKind::Box(ref p) => return name_from_pat(&**p), PatKind::Ref(ref p, _) => return name_from_pat(&**p), @@ -284,9 +277,9 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { } PatKind::Range(..) => return kw::Underscore, PatKind::Slice(ref begin, ref mid, ref end) => { - let begin = begin.iter().map(|p| name_from_pat(&**p).to_string()); + let begin = begin.iter().map(|p| name_from_pat(p).to_string()); let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter(); - let end = end.iter().map(|p| name_from_pat(&**p).to_string()); + let end = end.iter().map(|p| name_from_pat(p).to_string()); format!("[{}]", begin.chain(mid).chain(end).collect::>().join(", ")) } }) @@ -431,7 +424,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty _ => false, }; let did = register_res(cx, path.res); - ResolvedPath { path, param_names: None, did, is_generic } + ResolvedPath { path, did, is_generic } } crate fn get_auto_trait_and_blanket_impls( @@ -562,3 +555,56 @@ crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool { /// /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable. crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL"); + +/// Render a sequence of macro arms in a format suitable for displaying to the user +/// as part of an item declaration. +pub(super) fn render_macro_arms<'a>( + matchers: impl Iterator, + arm_delim: &str, +) -> String { + let mut out = String::new(); + for matcher in matchers { + writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(matcher), arm_delim).unwrap(); + } + out +} + +/// Render a macro matcher in a format suitable for displaying to the user +/// as part of an item declaration. +pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String { + rustc_ast_pretty::pprust::tt_to_string(matcher) +} + +pub(super) fn display_macro_source( + cx: &mut DocContext<'_>, + name: Symbol, + def: &ast::MacroDef, + def_id: DefId, + vis: impl Clean, +) -> String { + let tts: Vec<_> = def.body.inner_tokens().into_trees().collect(); + // Extract the spans of all matchers. They represent the "interface" of the macro. + let matchers = tts.chunks(4).map(|arm| &arm[0]); + + if def.macro_rules { + format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";")) + } else { + let vis = vis.clean(cx); + + if matchers.len() <= 1 { + format!( + "{}macro {}{} {{\n ...\n}}", + vis.to_src_with_space(cx.tcx, def_id), + name, + matchers.map(render_macro_matcher).collect::(), + ) + } else { + format!( + "{}macro {} {{\n{}}}", + vis.to_src_with_space(cx.tcx, def_id), + name, + render_macro_arms(matchers, ","), + ) + } + } +} diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 1b5a00dde5..abd1fd2bf3 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -156,6 +156,8 @@ crate struct Options { crate run_check: bool, /// Whether doctests should emit unused externs crate json_unused_externs: bool, + /// Whether to skip capturing stdout and stderr of tests. + crate nocapture: bool, } impl fmt::Debug for Options { @@ -199,6 +201,7 @@ impl fmt::Debug for Options { .field("enable-per-target-ignores", &self.enable_per_target_ignores) .field("run_check", &self.run_check) .field("no_run", &self.no_run) + .field("nocapture", &self.nocapture) .finish() } } @@ -456,7 +459,31 @@ impl Options { }) .collect(), ]; - let default_settings = default_settings.into_iter().flatten().collect(); + let default_settings = default_settings + .into_iter() + .flatten() + .map( + // The keys here become part of `data-` attribute names in the generated HTML. The + // browser does a strange mapping when converting them into attributes on the + // `dataset` property on the DOM HTML Node: + // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset + // + // The original key values we have are the same as the DOM storage API keys and the + // command line options, so contain `-`. Our Javascript needs to be able to look + // these values up both in `dataset` and in the storage API, so it needs to be able + // to convert the names back and forth. Despite doing this kebab-case to + // StudlyCaps transformation automatically, the JS DOM API does not provide a + // mechanism for doing the just transformation on a string. So we want to avoid + // the StudlyCaps representation in the `dataset` property. + // + // We solve this by replacing all the `-`s with `_`s. We do that here, when we + // generate the `data-` attributes, and in the JS, when we look them up. (See + // `getSettingValue` in `storage.js.`) Converting `-` to `_` is simple in JS. + // + // The values will be HTML-escaped by the default Tera escaping. + |(k, v)| (k.replace('-', "_"), v), + ) + .collect(); let test_args = matches.opt_strs("test-args"); let test_args: Vec = @@ -513,7 +540,7 @@ impl Options { )) .warn("the theme may appear incorrect when loaded") .help(&format!( - "to see what rules are missing, call `rustdoc --check-theme \"{}\"`", + "to see what rules are missing, call `rustdoc --check-theme \"{}\"`", theme_s )) .emit(); @@ -627,8 +654,9 @@ impl Options { let run_check = matches.opt_present("check"); let generate_redirect_map = matches.opt_present("generate-redirect-map"); let show_type_layout = matches.opt_present("show-type-layout"); + let nocapture = matches.opt_present("nocapture"); - let (lint_opts, describe_lints, lint_cap, _) = + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format, &debugging_opts); Ok(Options { @@ -665,6 +693,7 @@ impl Options { test_builder, run_check, no_run, + nocapture, render_options: RenderOptions { output, external_html, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 97be79a655..0689d72e4e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -30,7 +30,7 @@ use std::mem; use std::rc::Rc; use crate::clean::inline::build_external_trait; -use crate::clean::{self, FakeDefId, TraitWithExtraInfo}; +use crate::clean::{self, ItemId, TraitWithExtraInfo}; use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions}; use crate::formats::cache::Cache; use crate::passes::{self, Condition::*, ConditionalPass}; @@ -78,7 +78,7 @@ crate struct DocContext<'tcx> { /// This same cache is used throughout rustdoc, including in [`crate::html::render`]. crate cache: Cache, /// Used by [`clean::inline`] to tell if an item has already been inlined. - crate inlined: FxHashSet, + crate inlined: FxHashSet, /// Used by `calculate_doc_coverage`. crate output_format: OutputFormat, } @@ -128,12 +128,13 @@ impl<'tcx> DocContext<'tcx> { /// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds. /// (This avoids a slice-index-out-of-bounds panic.) - crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: FakeDefId) -> Option { + crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: ItemId) -> Option { match def_id { - FakeDefId::Real(real_id) => { + ItemId::DefId(real_id) => { real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) } - FakeDefId::Fake(_, _) => None, + // FIXME: Can this be `Some` for `Auto` or `Blanket`? + _ => None, } } } @@ -312,7 +313,6 @@ crate fn create_resolver<'a>( .collect(); let (_, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek(); - let resolver = resolver.borrow(); // Before we actually clone it, let's force all the extern'd crates to // actually be loaded, just in case they're only referred to inside diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 88e2f6048e..b45e84aff8 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -3,6 +3,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_errors::{ColorConfig, ErrorReported}; use rustc_hir as hir; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::intravisit; use rustc_hir::{HirId, CRATE_HIR_ID}; use rustc_interface::interface; @@ -13,6 +14,7 @@ use rustc_session::{lint, DiagnosticOutput, 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; @@ -103,16 +105,14 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { registry: rustc_driver::diagnostics_registry(), }; - let mut test_args = options.test_args.clone(); + let test_args = options.test_args.clone(); let display_warnings = options.display_warnings; + let nocapture = options.nocapture; let externs = options.externs.clone(); let json_unused_externs = options.json_unused_externs; let res = interface::run_compiler(config, |compiler| { compiler.enter(|queries| { - let _lower_to_hir = queries.lower_to_hir()?; - - let crate_name = queries.crate_name()?.peek().to_string(); let mut global_ctxt = queries.global_ctxt()?.take(); let collector = global_ctxt.enter(|tcx| { @@ -123,7 +123,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { opts.display_warnings |= options.display_warnings; let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( - crate_name, + tcx.crate_name(LOCAL_CRATE), options, false, opts, @@ -166,13 +166,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { Err(ErrorReported) => return Err(ErrorReported), }; - test_args.insert(0, "rustdoctest".to_string()); - - testing::test_main( - &test_args, - tests, - Some(testing::Options::new().display_output(display_warnings)), - ); + run_tests(test_args, nocapture, display_warnings, tests); // Collect and warn about unused externs, but only if we've gotten // reports for each doctest @@ -215,6 +209,19 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { Ok(()) } +crate fn run_tests( + mut test_args: Vec, + nocapture: bool, + display_warnings: bool, + tests: Vec, +) { + test_args.insert(0, "rustdoctest".to_string()); + if nocapture { + test_args.push("--nocapture".to_string()); + } + test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings))); +} + // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade. fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions { use rustc_ast_pretty::pprust; @@ -293,7 +300,7 @@ struct UnusedExterns { fn run_test( test: &str, - cratename: &str, + crate_name: &str, line: usize, options: Options, should_panic: bool, @@ -312,7 +319,7 @@ fn run_test( report_unused_externs: impl Fn(UnusedExterns), ) -> Result<(), TestFailure> { let (test, line_offset, supports_color) = - make_test(test, Some(cratename), as_test_harness, opts, edition, Some(test_id)); + make_test(test, Some(crate_name), as_test_harness, opts, edition, Some(test_id)); let output_file = outdir.path().join("rust_out"); @@ -461,7 +468,16 @@ fn run_test( cmd.current_dir(run_directory); } - match cmd.output() { + let result = if options.nocapture { + cmd.status().map(|status| process::Output { + status, + stdout: Vec::new(), + stderr: Vec::new(), + }) + } else { + cmd.output() + }; + match result { Err(e) => return Err(TestFailure::ExecutionError(e)), Ok(out) => { if should_panic && out.status.success() { @@ -479,7 +495,7 @@ fn run_test( /// lines before the test code begins as well as if the output stream supports colors or not. crate fn make_test( s: &str, - cratename: Option<&str>, + crate_name: Option<&str>, dont_insert_main: bool, opts: &TestOptions, edition: Edition, @@ -514,7 +530,7 @@ crate fn make_test( // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern // crate already is included. let result = rustc_driver::catch_fatal_errors(|| { - rustc_span::with_session_globals(edition, || { + rustc_span::create_session_if_not_set_then(edition, |_| { use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::Handler; use rustc_parse::maybe_new_parser_from_source_str; @@ -540,7 +556,7 @@ crate fn make_test( let sess = ParseSess::with_span_handler(handler, sm); let mut found_main = false; - let mut found_extern_crate = cratename.is_none(); + let mut found_extern_crate = crate_name.is_none(); let mut found_macro = false; let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source) { @@ -567,13 +583,13 @@ crate fn make_test( if !found_extern_crate { if let ast::ItemKind::ExternCrate(original) = item.kind { - // This code will never be reached if `cratename` is none because + // This code will never be reached if `crate_name` is none because // `found_extern_crate` is initialized to `true` if it is none. - let cratename = cratename.unwrap(); + let crate_name = crate_name.unwrap(); match original { - Some(name) => found_extern_crate = name.as_str() == cratename, - None => found_extern_crate = item.ident.as_str() == cratename, + Some(name) => found_extern_crate = name.as_str() == crate_name, + None => found_extern_crate = item.ident.as_str() == crate_name, } } } @@ -631,14 +647,14 @@ crate fn make_test( // Don't inject `extern crate std` because it's already injected by the // compiler. - if !already_has_extern_crate && !opts.no_crate_inject && cratename != Some("std") { - if let Some(cratename) = cratename { + if !already_has_extern_crate && !opts.no_crate_inject && crate_name != Some("std") { + if let Some(crate_name) = crate_name { // Don't inject `extern crate` if the crate is never used. // NOTE: this is terribly inaccurate because it doesn't actually // parse the source, but only has false positives, not false // negatives. - if s.contains(cratename) { - prog.push_str(&format!("extern crate r#{};\n", cratename)); + if s.contains(crate_name) { + prog.push_str(&format!("extern crate r#{};\n", crate_name)); line_offset += 1; } } @@ -770,7 +786,7 @@ crate trait Tester { } crate struct Collector { - crate tests: Vec, + crate tests: Vec, // The name of the test displayed to the user, separated by `::`. // @@ -797,7 +813,7 @@ crate struct Collector { options: Options, use_headers: bool, enable_per_target_ignores: bool, - cratename: String, + crate_name: Symbol, opts: TestOptions, position: Span, source_map: Option>, @@ -809,7 +825,7 @@ crate struct Collector { impl Collector { crate fn new( - cratename: String, + crate_name: Symbol, options: Options, use_headers: bool, opts: TestOptions, @@ -823,7 +839,7 @@ impl Collector { options, use_headers, enable_per_target_ignores, - cratename, + crate_name, opts, position: DUMMY_SP, source_map, @@ -871,7 +887,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 cratename = self.cratename.to_string(); + let crate_name = self.crate_name.to_string(); let opts = self.opts.clone(); let edition = config.edition.unwrap_or(self.options.edition); let options = self.options.clone(); @@ -931,30 +947,28 @@ impl Tester for Collector { }; debug!("creating test {}: {}", name, test); - self.tests.push(testing::TestDescAndFn { - desc: testing::TestDesc { - name: testing::DynTestName(name), + self.tests.push(test::TestDescAndFn { + desc: test::TestDesc { + name: test::DynTestName(name), ignore: match config.ignore { Ignore::All => true, Ignore::None => false, Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), }, // compiler failures are test failures - should_panic: testing::ShouldPanic::No, + should_panic: test::ShouldPanic::No, allow_fail: config.allow_fail, - #[cfg(not(bootstrap))] compile_fail: config.compile_fail, - #[cfg(not(bootstrap))] no_run, - test_type: testing::TestType::DocTest, + test_type: test::TestType::DocTest, }, - testfn: testing::DynTestFn(box move || { + testfn: test::DynTestFn(box move || { let report_unused_externs = |uext| { unused_externs.lock().unwrap().push(uext); }; let res = run_test( &test, - &cratename, + &crate_name, line, options, config.should_panic, diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 6c86baa36a..56d2ca5721 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -4,7 +4,9 @@ use std::fs; use std::path::Path; use std::str; -#[derive(Clone, Debug)] +use serde::Serialize; + +#[derive(Clone, Debug, Serialize)] crate struct ExternalHtml { /// Content that will be included inline in the section of a /// rendered Markdown file or generated documentation diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 5734a4a98e..5ea2cdc2ad 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -8,7 +8,7 @@ use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; -use crate::clean::{self, FakeDefId, GetDefId}; +use crate::clean::{self, GetDefId, ItemId}; use crate::fold::DocFolder; use crate::formats::item_type::ItemType; use crate::formats::Impl; @@ -122,13 +122,12 @@ crate struct Cache { /// All intra-doc links resolved so far. /// /// Links are indexed by the DefId of the item they document. - crate intra_doc_links: BTreeMap>, + crate intra_doc_links: FxHashMap>, } /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`. struct CacheBuilder<'a, 'tcx> { cache: &'a mut Cache, - empty_cache: Cache, tcx: TyCtxt<'tcx>, } @@ -152,19 +151,18 @@ impl Cache { // Cache where all our extern crates are located // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code - for &(n, ref e) in &krate.externs { + for &e in &krate.externs { let name = e.name(tcx); let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u); - let did = DefId { krate: n, index: CRATE_DEF_INDEX }; - self.extern_locations.insert(n, e.location(extern_url, &dst, tcx)); - self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module)); + self.extern_locations.insert(e.crate_num, e.location(extern_url, &dst, tcx)); + self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module)); } // Cache where all known primitives have their documentation located. // // Favor linking to as local extern as possible, so iterate all crates in // reverse topological order. - for &(_, ref e) in krate.externs.iter().rev() { + for &e in krate.externs.iter().rev() { for &(def_id, prim) in &e.primitives(tcx) { self.primitive_locations.insert(prim, def_id); } @@ -173,7 +171,7 @@ impl Cache { self.primitive_locations.insert(prim, def_id); } - krate = CacheBuilder { tcx, cache: self, empty_cache: Cache::default() }.fold_crate(krate); + krate = CacheBuilder { tcx, cache: self }.fold_crate(krate); for (trait_did, dids, impl_) in self.orphan_trait_impls.drain(..) { if self.traits.contains_key(&trait_did) { @@ -216,7 +214,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.def_id.expect_real()).or_insert_with(|| { + self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| { clean::TraitWithExtraInfo { trait_: t.clone(), is_notable: item.attrs.has_doc_flag(sym::notable_trait), @@ -292,16 +290,17 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // which should not be indexed. The crate-item itself is // inserted later on when serializing the search-index. if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) { + let desc = item.doc_value().map_or_else(String::new, |x| { + short_markdown_summary(&x.as_str(), &item.link_names(&self.cache)) + }); self.cache.search_index.push(IndexItem { ty: item.type_(), name: s.to_string(), path: path.join("::"), - desc: item - .doc_value() - .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())), + desc, parent, parent_idx: None, - search_type: get_index_search_type(&item, &self.empty_cache, self.tcx), + search_type: get_index_search_type(&item, self.tcx), aliases: item.attrs.get_doc_aliases(), }); } @@ -348,11 +347,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // `public_items` map, so we can skip inserting into the // paths map if there was already an entry present and we're // not a public item. - if !self.cache.paths.contains_key(&item.def_id.expect_real()) - || self.cache.access_levels.is_public(item.def_id.expect_real()) + if !self.cache.paths.contains_key(&item.def_id.expect_def_id()) + || self.cache.access_levels.is_public(item.def_id.expect_def_id()) { self.cache.paths.insert( - item.def_id.expect_real(), + item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()), ); } @@ -361,7 +360,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { clean::PrimitiveItem(..) => { self.cache .paths - .insert(item.def_id.expect_real(), (self.cache.stack.clone(), item.type_())); + .insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_())); } clean::ExternCrateItem { .. } @@ -391,7 +390,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { | clean::StructItem(..) | clean::UnionItem(..) | clean::VariantItem(..) => { - self.cache.parent_stack.push(item.def_id.expect_real()); + self.cache.parent_stack.push(item.def_id.expect_def_id()); self.cache.parent_is_trait_impl = false; true } @@ -402,6 +401,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { self.cache.parent_stack.push(did); true } + clean::DynTrait(ref bounds, _) + | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { + if let Some(did) = bounds[0].trait_.def_id() { + self.cache.parent_stack.push(did); + true + } else { + false + } + } ref t => { let prim_did = t .primitive_type() @@ -432,6 +440,12 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => { dids.insert(did); } + clean::DynTrait(ref bounds, _) + | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { + if let Some(did) = bounds[0].trait_.def_id() { + dids.insert(did); + } + } ref t => { let did = t .primitive_type() diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 918a5cb509..08499cef33 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -9,6 +9,7 @@ use std::cell::Cell; use std::fmt; use std::iter; +use rustc_attr::{ConstStability, StabilityLevel}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; @@ -18,7 +19,7 @@ use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_target::spec::abi::Abi; use crate::clean::{ - self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, GetDefId, PrimitiveType, + self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType, }; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; @@ -249,17 +250,33 @@ crate fn print_where_clause<'a, 'tcx: 'a>( } match pred { - clean::WherePredicate::BoundPredicate { ty, bounds } => { + clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => { let bounds = bounds; + let for_prefix = match bound_params.len() { + 0 => String::new(), + _ if f.alternate() => { + format!( + "for<{:#}> ", + comma_sep(bound_params.iter().map(|lt| lt.print())) + ) + } + _ => format!( + "for<{}> ", + comma_sep(bound_params.iter().map(|lt| lt.print())) + ), + }; + if f.alternate() { clause.push_str(&format!( - "{:#}: {:#}", + "{}{:#}: {:#}", + for_prefix, ty.print(cx), print_generic_bounds(bounds, cx) )); } else { clause.push_str(&format!( - "{}: {}", + "{}{}: {}", + for_prefix, ty.print(cx), print_generic_bounds(bounds, cx) )); @@ -455,7 +472,19 @@ impl clean::GenericArgs { } } -crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec)> { +// Possible errors when computing href link source for a `DefId` +crate enum HrefError { + /// This item is known to rustdoc, but from a crate that does not have documentation generated. + /// + /// This can only happen for non-local items. + DocumentationNotBuilt, + /// This can only happen for non-local items when `--document-private-items` is not passed. + Private, + // Not in external cache, href link should be in same page + NotInExternalCache, +} + +crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec), HrefError> { let cache = &cx.cache(); let relative_to = &cx.current; fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] { @@ -463,7 +492,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec) -> Option<(String, ItemType, Vec { - let &(ref fqp, shortty) = cache.external_paths.get(&did)?; - let module_fqp = to_module_fqp(shortty, fqp); - ( - fqp, - shortty, - match cache.extern_locations[&did.krate] { - ExternalLocation::Remote(ref s) => { - let s = s.trim_end_matches('/'); - let mut s = vec![&s[..]]; - s.extend(module_fqp[..].iter().map(String::as_str)); - s - } - ExternalLocation::Local => href_relative_parts(module_fqp, relative_to), - ExternalLocation::Unknown => return None, - }, - ) + if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) { + let module_fqp = to_module_fqp(shortty, fqp); + ( + fqp, + shortty, + match cache.extern_locations[&did.krate] { + ExternalLocation::Remote(ref s) => { + let s = s.trim_end_matches('/'); + let mut s = vec![&s[..]]; + s.extend(module_fqp[..].iter().map(String::as_str)); + s + } + ExternalLocation::Local => href_relative_parts(module_fqp, relative_to), + ExternalLocation::Unknown => return Err(HrefError::DocumentationNotBuilt), + }, + ) + } else { + return Err(HrefError::NotInExternalCache); + } } }; let last = &fqp.last().unwrap()[..]; @@ -501,7 +533,7 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec( write!(w, "{}{:#}", &last.name, last.args.print(cx))?; } else { let path = if use_absolute { - if let Some((_, _, fqp)) = href(did, cx) { + if let Ok((_, _, fqp)) = href(did, cx) { format!( "{}::{}", fqp[..fqp.len() - 1].join("::"), @@ -630,18 +662,24 @@ fn primitive_link( /// Helper to render type parameters fn tybounds<'a, 'tcx: 'a>( - param_names: &'a Option>, + bounds: &'a Vec, + lt: &'a Option, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - display_fn(move |f| match *param_names { - Some(ref params) => { - for param in params { + display_fn(move |f| { + for (i, bound) in bounds.iter().enumerate() { + if i > 0 { write!(f, " + ")?; - fmt::Display::fmt(¶m.print(cx), f)?; } - Ok(()) + + fmt::Display::fmt(&bound.print(cx), f)?; } - None => Ok(()), + + if let Some(lt) = lt { + write!(f, " + ")?; + fmt::Display::fmt(<.print(), f)?; + } + Ok(()) }) } @@ -652,7 +690,7 @@ crate fn anchor<'a, 'cx: 'a>( ) -> impl fmt::Display + 'a { let parts = href(did.into(), cx); display_fn(move |f| { - if let Some((url, short_ty, fqp)) = parts { + if let Ok((url, short_ty, fqp)) = parts { write!( f, r#"{}"#, @@ -678,13 +716,13 @@ fn fmt_type<'cx>( match *t { clean::Generic(name) => write!(f, "{}", name), - clean::ResolvedPath { did, ref param_names, ref path, is_generic } => { - if param_names.is_some() { - f.write_str("dyn ")?; - } + clean::ResolvedPath { did, ref path, is_generic } => { // Paths like `T::Output` and `Self::Output` should be rendered with all segments. - resolved_path(f, did, path, is_generic, use_absolute, cx)?; - fmt::Display::fmt(&tybounds(param_names, cx), f) + resolved_path(f, did, path, is_generic, use_absolute, cx) + } + clean::DynTrait(ref bounds, ref lt) => { + f.write_str("dyn ")?; + fmt::Display::fmt(&tybounds(bounds, lt, cx), f) } clean::Infer => write!(f, "_"), clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx), @@ -819,7 +857,9 @@ fn fmt_type<'cx>( } } } - clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => { + clean::DynTrait(ref bounds, ref trait_lt) + if bounds.len() > 1 || trait_lt.is_some() => + { write!(f, "{}{}{}(", amp, lt, m)?; fmt_type(&ty, f, use_absolute, cx)?; write!(f, ")") @@ -880,9 +920,9 @@ fn fmt_type<'cx>( // the ugliness comes from inlining across crates where // everything comes in as a fully resolved QPath (hard to // look at). - box clean::ResolvedPath { did, ref param_names, .. } => { + box clean::ResolvedPath { did, .. } => { match href(did.into(), cx) { - Some((ref url, _, ref path)) if !f.alternate() => { + Ok((ref url, _, ref path)) if !f.alternate() => { write!( f, "( } _ => write!(f, "{}", name)?, } - - // FIXME: `param_names` are not rendered, and this seems bad? - drop(param_names); Ok(()) } _ => write!(f, "{}", name), @@ -1159,7 +1196,7 @@ impl clean::FnDecl { impl clean::Visibility { crate fn print_with_space<'a, 'tcx: 'a>( self, - item_did: FakeDefId, + item_did: ItemId, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { let to_print = match self { @@ -1169,7 +1206,7 @@ impl clean::Visibility { // FIXME(camelid): This may not work correctly if `item_did` is a module. // However, rustdoc currently never displays a module's // visibility, so it shouldn't matter. - let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_real()); + let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id()); if vis_did.index == CRATE_DEF_INDEX { "pub(crate) ".to_owned() @@ -1253,15 +1290,6 @@ impl PrintWithSpace for hir::Unsafety { } } -impl PrintWithSpace for hir::Constness { - fn print_with_space(&self) -> &str { - match self { - hir::Constness::Const => "const ", - hir::Constness::NotConst => "", - } - } -} - impl PrintWithSpace for hir::IsAsync { fn print_with_space(&self) -> &str { match self { @@ -1280,6 +1308,22 @@ impl PrintWithSpace for hir::Mutability { } } +crate fn print_constness_with_space( + c: &hir::Constness, + s: Option<&ConstStability>, +) -> &'static str { + match (c, s) { + // const stable or when feature(staged_api) is not set + ( + hir::Constness::Const, + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }), + ) + | (hir::Constness::Const, None) => "const ", + // const unstable or not const + _ => "", + } +} + impl clean::Import { crate fn print<'a, 'tcx: 'a>( &'a self, diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 51392ca119..33b1d98313 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -413,7 +413,7 @@ impl<'a> Classifier<'a> { }, c => c, }, - TokenKind::RawIdent => Class::Ident, + TokenKind::RawIdent | TokenKind::UnknownPrefix => Class::Ident, TokenKind::Lifetime { .. } => Class::Lifetime, }; // Anything that didn't return above is the simple case where we the diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index a0da2c963d..a505865b14 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -1,8 +1,8 @@ use super::write_code; use crate::html::format::Buffer; use expect_test::expect_file; +use rustc_span::create_default_session_globals_then; use rustc_span::edition::Edition; -use rustc_span::with_default_session_globals; const STYLE: &str = r#" \ -\ -\ - \ - {before_content}\ - \ -
\ - \ -
\ -
\ -
\ -
{content}
\ -
\ - {after_content}\ -
\ - \ - {extra_scripts}\ -\ -", - css_extension = if layout.css_file_extension.is_some() { + let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string(); + let style_files = style_files + .iter() + .filter_map(|t| { + if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None } + }) + .filter_map(|t| if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }) + .map(|t| { format!( - "", - static_root_path = static_root_path, - suffix = page.resource_suffix - ) - } else { - String::new() - }, - content = Buffer::html().to_display(t), - static_root_path = static_root_path, - root_path = page.root_path, - css_class = page.css_class, - logo = { - if layout.logo.is_empty() { - format!( - "\ - ", - root = page.root_path, - path = ensure_trailing_slash(&layout.krate), - static_root_path = static_root_path, - suffix = page.resource_suffix - ) - } else { - format!( - "\ -
logo
", - root = page.root_path, - path = ensure_trailing_slash(&layout.krate), - logo = layout.logo - ) - } - }, - title = page.title, - description = Escape(page.description), - keywords = page.keywords, - favicon = if layout.favicon.is_empty() { - format!( - r##" - -"##, - static_root_path = static_root_path, - suffix = page.resource_suffix - ) - } else { - format!(r#""#, layout.favicon) - }, - in_header = layout.external_html.in_header, - before_content = layout.external_html.before_content, - after_content = layout.external_html.after_content, - sidebar = Buffer::html().to_display(sidebar), - krate = layout.krate, - default_settings = layout - .default_settings - .iter() - .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v))) - .collect::(), - style_files = style_files - .iter() - .filter_map(|t| { - if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None } - }) - .filter_map(|t| { - if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None } - }) - .map(|t| format!( r#""#, Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)), if t.1 { "disabled" } else { "" }, if t.0 == "light" { "id=\"themeStyle\"" } else { "" } - )) - .collect::(), - suffix = page.resource_suffix, - extra_scripts = page - .static_extra_scripts - .iter() - .map(|e| { - format!( - "", - static_root_path = static_root_path, - extra_script = e - ) - }) - .chain(page.extra_scripts.iter().map(|e| { - format!( - "", - root_path = page.root_path, - extra_script = e - ) - })) - .collect::(), - filter_crates = if layout.generate_search_filter { - "" - } else { - "" - }, - ) + ) + }) + .collect::(); + let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar. + let sidebar = Buffer::html().to_display(sidebar); + let teractx = tera::Context::from_serialize(PageLayout { + static_root_path, + page, + layout, + style_files, + sidebar, + content, + krate_with_trailing_slash, + }) + .unwrap(); + templates.render("page.html", &teractx).unwrap() } crate fn redirect(url: &str) -> String { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 00a91e07d6..908e292d96 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -33,6 +33,7 @@ use std::str; use crate::clean::RenderedLink; use crate::doctest; +use crate::html::escape::Escape; use crate::html::highlight; use crate::html::toc::TocBuilder; @@ -56,7 +57,7 @@ pub(crate) fn opts() -> Options { /// A subset of [`opts()`] used for rendering summaries. pub(crate) fn summary_opts() -> Options { - Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION + Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION | Options::ENABLE_TABLES } /// When `to_string` is called, this struct will emit the HTML corresponding to @@ -207,26 +208,11 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let should_panic; let ignore; let edition; - if let Some(Event::Start(Tag::CodeBlock(kind))) = event { - let parse_result = match kind { - CodeBlockKind::Fenced(ref lang) => { - LangString::parse_without_check(&lang, self.check_error_codes, false) - } - CodeBlockKind::Indented => Default::default(), - }; - if !parse_result.rust { - return Some(Event::Start(Tag::CodeBlock(kind))); - } - compile_fail = parse_result.compile_fail; - should_panic = parse_result.should_panic; - ignore = parse_result.ignore; - edition = parse_result.edition; + let kind = if let Some(Event::Start(Tag::CodeBlock(kind))) = event { + kind } else { return event; - } - - let explicit_edition = edition.is_some(); - let edition = edition.unwrap_or(self.edition); + }; let mut origtext = String::new(); for event in &mut self.inner { @@ -241,6 +227,35 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let lines = origtext.lines().filter_map(|l| map_line(l).for_html()); let text = lines.collect::>>().join("\n"); + let parse_result = match kind { + CodeBlockKind::Fenced(ref lang) => { + let parse_result = + LangString::parse_without_check(&lang, self.check_error_codes, false); + if !parse_result.rust { + return Some(Event::Html( + format!( + "
\ + {}\ +
", + format!(" class=\"language-{}\"", lang), + Escape(&text), + ) + .into(), + )); + } + parse_result + } + CodeBlockKind::Indented => Default::default(), + }; + + compile_fail = parse_result.compile_fail; + should_panic = parse_result.should_panic; + ignore = parse_result.ignore; + edition = parse_result.edition; + + let explicit_edition = edition.is_some(); + let edition = edition.unwrap_or(self.edition); + let playground_button = self.playground.as_ref().and_then(|playground| { let krate = &playground.crate_name; let url = &playground.url; @@ -507,6 +522,10 @@ fn check_if_allowed_tag(t: &Tag<'_>) -> bool { ) } +fn is_forbidden_tag(t: &Tag<'_>) -> bool { + matches!(t, Tag::CodeBlock(_) | Tag::Table(_) | Tag::TableHead | Tag::TableRow | Tag::TableCell) +} + impl<'a, I: Iterator>> Iterator for SummaryLine<'a, I> { type Item = Event<'a>; @@ -520,14 +539,17 @@ impl<'a, I: Iterator>> Iterator for SummaryLine<'a, I> { if let Some(event) = self.inner.next() { let mut is_start = true; let is_allowed_tag = match event { - Event::Start(Tag::CodeBlock(_)) | Event::End(Tag::CodeBlock(_)) => { - return None; - } Event::Start(ref c) => { + if is_forbidden_tag(c) { + return None; + } self.depth += 1; check_if_allowed_tag(c) } Event::End(ref c) => { + if is_forbidden_tag(c) { + return None; + } self.depth -= 1; is_start = false; check_if_allowed_tag(c) @@ -606,8 +628,7 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { is_paragraph = true; } html::push_html(&mut ret, content.into_iter()); - write!(ret, " â†©", id) - .unwrap(); + write!(ret, " â†©", id).unwrap(); if is_paragraph { ret.push_str("

"); } @@ -1051,7 +1072,11 @@ impl MarkdownSummaryLine<'_> { /// /// Returns a tuple of the rendered HTML string and whether the output was shortened /// due to the provided `length_limit`. -fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool) { +fn markdown_summary_with_limit( + md: &str, + link_names: &[RenderedLink], + length_limit: usize, +) -> (String, bool) { if md.is_empty() { return (String::new(), false); } @@ -1065,7 +1090,20 @@ fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool) *text_length += text.len(); } - 'outer: for event in Parser::new_ext(md, summary_opts()) { + let mut replacer = |broken_link: BrokenLink<'_>| { + if let Some(link) = + link_names.iter().find(|link| &*link.original_text == broken_link.reference) + { + Some((link.href.as_str().into(), link.new_text.as_str().into())) + } else { + None + } + }; + + let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer)); + let p = LinkReplacer::new(p, link_names); + + 'outer: for event in p { match &event { Event::Text(text) => { for word in text.split_inclusive(char::is_whitespace) { @@ -1121,8 +1159,8 @@ fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool) /// Will shorten to 59 or 60 characters, including an ellipsis (…) if it was shortened. /// /// See [`markdown_summary_with_limit`] for details about what is rendered and what is not. -crate fn short_markdown_summary(markdown: &str) -> String { - let (mut s, was_shortened) = markdown_summary_with_limit(markdown, 59); +crate fn short_markdown_summary(markdown: &str, link_names: &[RenderedLink]) -> String { + let (mut s, was_shortened) = markdown_summary_with_limit(markdown, link_names, 59); if was_shortened { s.push('…'); @@ -1341,7 +1379,10 @@ pub struct IdMap { fn init_id_map() -> FxHashMap { let mut map = FxHashMap::default(); - // This is the list of IDs used by rustdoc templates. + // This is the list of IDs used in Javascript. + map.insert("help".to_owned(), 1); + // This is the list of IDs used in HTML generated in Rust (including the ones + // used in tera template files). map.insert("mainThemeStyle".to_owned(), 1); map.insert("themeStyle".to_owned(), 1); map.insert("theme-picker".to_owned(), 1); @@ -1358,14 +1399,14 @@ fn init_id_map() -> FxHashMap { map.insert("rustdoc-vars".to_owned(), 1); map.insert("sidebar-vars".to_owned(), 1); map.insert("copy-path".to_owned(), 1); - map.insert("help".to_owned(), 1); map.insert("TOC".to_owned(), 1); - map.insert("render-detail".to_owned(), 1); - // This is the list of IDs used by rustdoc sections. + // This is the list of IDs used by rustdoc sections (but still generated by + // rustdoc). map.insert("fields".to_owned(), 1); map.insert("variants".to_owned(), 1); map.insert("implementors-list".to_owned(), 1); map.insert("synthetic-implementors-list".to_owned(), 1); + map.insert("foreign-impls".to_owned(), 1); map.insert("implementations".to_owned(), 1); map.insert("trait-implementations".to_owned(), 1); map.insert("synthetic-implementations".to_owned(), 1); @@ -1376,6 +1417,10 @@ fn init_id_map() -> FxHashMap { map.insert("provided-methods".to_owned(), 1); map.insert("implementors".to_owned(), 1); map.insert("synthetic-implementors".to_owned(), 1); + map.insert("trait-implementations-list".to_owned(), 1); + map.insert("synthetic-implementations-list".to_owned(), 1); + map.insert("blanket-implementations-list".to_owned(), 1); + map.insert("deref-methods".to_owned(), 1); map } diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index ac3ea4c8c5..d10da64ccf 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -221,7 +221,7 @@ fn test_header_ids_multiple_blocks() { #[test] fn test_short_markdown_summary() { fn t(input: &str, expect: &str) { - let output = short_markdown_summary(input); + let output = short_markdown_summary(input, &[][..]); assert_eq!(output, expect, "original: {}", input); } @@ -232,6 +232,7 @@ fn test_short_markdown_summary() { t("Hard-break \nsummary", "Hard-break summary"); t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)"); t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)"); + t("dud [link]", "dud [link]"); t("code `let x = i32;` ...", "code let x = i32; …"); t("type `Type<'static>` ...", "type Type<'static> …"); t("# top header", "top header"); @@ -259,6 +260,7 @@ fn test_plain_text_summary() { t("Hard-break \nsummary", "Hard-break summary"); t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)"); t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)"); + t("dud [link]", "dud [link]"); t("code `let x = i32;` ...", "code `let x = i32;` …"); t("type `Type<'static>` ...", "type `Type<'static>` …"); t("# top header", "top header"); diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 3e056c4b67..0734d2670c 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -12,7 +12,7 @@ use crate::clean::types::{ use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::markdown::short_markdown_summary; -use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind}; +use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, TypeWithKind}; /// Indicates where an external crate can be found. crate enum ExternalLocation { @@ -34,19 +34,27 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< // has since been learned. for &(did, ref item) in &cache.orphan_impl_items { if let Some(&(ref fqp, _)) = cache.paths.get(&did) { + let desc = item + .doc_value() + .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(&cache))); cache.search_index.push(IndexItem { ty: item.type_(), name: item.name.unwrap().to_string(), path: fqp[..fqp.len() - 1].join("::"), - desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)), + desc, parent: Some(did.into()), parent_idx: None, - search_type: get_index_search_type(&item, cache, tcx), + search_type: get_index_search_type(&item, tcx), aliases: item.attrs.get_doc_aliases(), }); } } + let crate_doc = krate + .module + .doc_value() + .map_or_else(String::new, |s| short_markdown_summary(&s, &krate.module.link_names(&cache))); + let Cache { ref mut search_index, ref paths, .. } = *cache; // Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, @@ -100,9 +108,6 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< crate_items.push(&*item); } - let crate_doc = - krate.module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)); - struct CrateData<'a> { doc: String, items: Vec<&'a IndexItem>, @@ -187,7 +192,6 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< crate fn get_index_search_type<'tcx>( item: &clean::Item, - cache: &Cache, tcx: TyCtxt<'tcx>, ) -> Option { let (all_types, ret_types) = match *item.kind { @@ -199,12 +203,12 @@ crate fn get_index_search_type<'tcx>( let inputs = all_types .iter() - .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty, &cache), *kind))) + .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) .filter(|a| a.ty.name.is_some()) .collect(); let output = ret_types .iter() - .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty, &cache), *kind))) + .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) .filter(|a| a.ty.name.is_some()) .collect::>(); let output = if output.is_empty() { None } else { Some(output) }; @@ -212,12 +216,10 @@ crate fn get_index_search_type<'tcx>( Some(IndexItemFunctionType { inputs, output }) } -fn get_index_type(clean_type: &clean::Type, cache: &Cache) -> RenderType { +fn get_index_type(clean_type: &clean::Type) -> RenderType { RenderType { - ty: clean_type.def_id_full(cache), - idx: None, name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()), - generics: get_generics(clean_type, cache), + generics: get_generics(clean_type), } } @@ -233,6 +235,7 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option }); Some(path_segment.name) } + clean::DynTrait(ref bounds, _) => get_index_type_name(&bounds[0].trait_, accept_generic), clean::Generic(s) if accept_generic => Some(s), clean::Primitive(ref p) => Some(p.as_sym()), clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), @@ -249,16 +252,17 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option } } -fn get_generics(clean_type: &clean::Type, cache: &Cache) -> Option> { +/// Return a list of generic parameters for use in the search index. +/// +/// This function replaces bounds with types, so that `T where T: Debug` just becomes `Debug`. +/// It does return duplicates, and that's intentional, since search queries like `Result` +/// are supposed to match only results where both parameters are `usize`. +fn get_generics(clean_type: &clean::Type) -> Option> { clean_type.generics().and_then(|types| { let r = types .iter() .filter_map(|t| { - get_index_type_name(t, false).map(|name| Generic { - name: name.as_str().to_ascii_lowercase(), - defid: t.def_id_full(cache), - idx: None, - }) + get_index_type_name(t, false).map(|name| name.as_str().to_ascii_lowercase()) }) .collect::>(); if r.is_empty() { None } else { Some(r) } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 84c5b5dd60..b6c3220901 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::collections::BTreeMap; +use std::error::Error as StdError; use std::io; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -29,6 +30,7 @@ use crate::formats::FormatRenderer; use crate::html::escape::Escape; use crate::html::format::Buffer; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; +use crate::html::static_files::PAGE; use crate::html::{layout, sources}; /// Major driving force in all rustdoc rendering. This contains information @@ -121,6 +123,8 @@ crate struct SharedContext<'tcx> { /// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of /// the crate. redirections: Option>>, + + pub(crate) templates: tera::Tera, } impl SharedContext<'_> { @@ -218,6 +222,7 @@ impl<'tcx> Context<'tcx> { if !self.render_redirect_pages { layout::render( + &self.shared.templates, &self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), @@ -225,7 +230,7 @@ impl<'tcx> Context<'tcx> { &self.shared.style_files, ) } else { - if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_real()) { + if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_def_id()) { let mut path = String::new(); for name in &names[..names.len() - 1] { path.push_str(name); @@ -408,6 +413,12 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let mut issue_tracker_base_url = None; let mut include_sources = true; + let mut templates = tera::Tera::default(); + templates.add_raw_template("page.html", PAGE).map_err(|e| Error { + file: "page.html".into(), + error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()), + })?; + // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML for attr in krate.module.attrs.lists(sym::doc) { @@ -454,6 +465,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { errors: receiver, redirections: if generate_redirect_map { Some(Default::default()) } else { None }, show_type_layout, + templates, }; // Add the default themes to the `Vec` of stylepaths @@ -540,6 +552,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { }; let all = self.shared.all.replace(AllTypes::new()); let v = layout::render( + &self.shared.templates, &self.shared.layout, &page, sidebar, @@ -557,6 +570,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let sidebar = "

Settings

"; style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false }); let v = layout::render( + &self.shared.templates, &self.shared.layout, &page, sidebar, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 0b14c327e4..fab7440817 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -42,7 +42,7 @@ use std::str; use std::string::ToString; use rustc_ast_pretty::pprust; -use rustc_attr::{Deprecation, StabilityLevel}; +use rustc_attr::{ConstStability, Deprecation, StabilityLevel}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -53,7 +53,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; -use crate::clean::{self, FakeDefId, GetDefId, RenderedLink, SelfTy}; +use crate::clean::{self, GetDefId, ItemId, RenderedLink, SelfTy}; use crate::docfs::PathError; use crate::error::Error; use crate::formats::cache::Cache; @@ -61,8 +61,8 @@ use crate::formats::item_type::ItemType; use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ - href, print_abi_with_space, print_default_space, print_generic_bounds, print_where_clause, - Buffer, PrintWithSpace, + href, print_abi_with_space, print_constness_with_space, print_default_space, + print_generic_bounds, print_where_clause, Buffer, HrefError, PrintWithSpace, }; use crate::html::markdown::{Markdown, MarkdownHtml, MarkdownSummaryLine}; @@ -95,53 +95,8 @@ crate struct IndexItem { /// A type used for the search index. #[derive(Debug)] crate struct RenderType { - ty: Option, - idx: Option, name: Option, - generics: Option>, -} - -impl Serialize for RenderType { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - if let Some(name) = &self.name { - let mut seq = serializer.serialize_seq(None)?; - if let Some(id) = self.idx { - seq.serialize_element(&id)?; - } else { - seq.serialize_element(&name)?; - } - if let Some(generics) = &self.generics { - seq.serialize_element(&generics)?; - } - seq.end() - } else { - serializer.serialize_none() - } - } -} - -/// A type used for the search index. -#[derive(Debug)] -crate struct Generic { - name: String, - defid: Option, - idx: Option, -} - -impl Serialize for Generic { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - if let Some(id) = self.idx { - serializer.serialize_some(&id) - } else { - serializer.serialize_some(&self.name) - } - } + generics: Option>, } /// Full type of functions/methods in the search index. @@ -195,7 +150,13 @@ impl Serialize for TypeWithKind { where S: Serializer, { - (&self.ty.name, self.kind).serialize(serializer) + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.ty.name)?; + seq.serialize_element(&self.kind)?; + if let Some(generics) = &self.ty.generics { + seq.serialize_element(generics)?; + } + seq.end() } } @@ -488,9 +449,8 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result, w: &mut Buffer, @@ -746,13 +708,15 @@ fn render_impls( containing_item, assoc_link, RenderMode::Normal, - containing_item.stable_since(tcx).as_deref(), - containing_item.const_stable_since(tcx).as_deref(), - true, None, - false, - true, &[], + ImplRenderingParameters { + show_def_docs: true, + is_on_foreign_type: false, + show_default_items: true, + show_non_assoc_items: true, + toggle_open_by_default: true, + }, ); buffer.into_inner() }) @@ -775,7 +739,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id), AssocItemLink::Anchor(None) => anchor, AssocItemLink::GotoSource(did, _) => { - href(did.expect_real(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) + href(did.expect_def_id(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) } } } @@ -827,21 +791,45 @@ fn assoc_type( fn render_stability_since_raw( w: &mut Buffer, ver: Option<&str>, - const_ver: Option<&str>, + const_stability: Option<&ConstStability>, containing_ver: Option<&str>, containing_const_ver: Option<&str>, ) { let ver = ver.filter(|inner| !inner.is_empty()); - let const_ver = const_ver.filter(|inner| !inner.is_empty()); - match (ver, const_ver) { - (Some(v), Some(cv)) if const_ver != containing_const_ver => { + match (ver, const_stability) { + // stable and const stable + (Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. })) + if Some(since.as_str()).as_deref() != containing_const_ver => + { write!( w, "{0} (const: {1})", - v, cv + v, since + ); + } + // stable and const unstable + ( + Some(v), + Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }), + ) => { + write!( + w, + "{0} (const: ", + v ); + if let Some(n) = issue { + write!( + w, + "unstable", + n, feature + ); + } else { + write!(w, "unstable"); + } + write!(w, ")"); } + // stable (Some(v), _) if ver != containing_ver => { write!( w, @@ -872,8 +860,8 @@ fn render_assoc_item( ) { let name = meth.name.as_ref().unwrap(); let href = match link { - AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id), - AssocItemLink::Anchor(None) => format!("#{}.{}", meth.type_(), name), + AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{}", id)), + AssocItemLink::Anchor(None) => Some(format!("#{}.{}", meth.type_(), name)), AssocItemLink::GotoSource(did, provided_methods) => { // We're creating a link from an impl-item to the corresponding // trait-item and need to map the anchored type accordingly. @@ -883,17 +871,21 @@ fn render_assoc_item( ItemType::TyMethod }; - href(did.expect_real(), cx) - .map(|p| format!("{}#{}.{}", p.0, ty, name)) - .unwrap_or_else(|| format!("#{}.{}", ty, name)) + match (href(did.expect_def_id(), cx), ty) { + (Ok(p), ty) => Some(format!("{}#{}.{}", p.0, ty, name)), + (Err(HrefError::DocumentationNotBuilt), ItemType::TyMethod) => None, + (Err(_), ty) => Some(format!("#{}.{}", ty, name)), + } } }; let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string(); - let constness = header.constness.print_with_space(); + let constness = + print_constness_with_space(&header.constness, meth.const_stability(cx.tcx())); let asyncness = header.asyncness.print_with_space(); let unsafety = header.unsafety.print_with_space(); let defaultness = print_default_space(meth.is_default()); let abi = print_abi_with_space(header.abi).to_string(); + // NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`. let generics_len = format!("{:#}", g.print(cx)).len(); let mut header_len = "fn ".len() @@ -918,16 +910,17 @@ fn render_assoc_item( w.reserve(header_len + "{".len() + "".len()); write!( w, - "{}{}{}{}{}{}{}fn {name}\ + "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn {name}\ {generics}{decl}{notable_traits}{where_clause}", - indent_str, - vis, - constness, - asyncness, - unsafety, - defaultness, - abi, - href = href, + indent = indent_str, + vis = vis, + constness = constness, + asyncness = asyncness, + unsafety = unsafety, + defaultness = defaultness, + abi = abi, + // links without a href are valid - https://www.w3schools.com/tags/att_a_href.asp + href = href.map(|href| format!("href=\"{}\"", href)).unwrap_or_else(|| "".to_string()), name = name, generics = g.print(cx), decl = d.full_print(header_len, indent, header.asyncness, cx), @@ -965,14 +958,8 @@ fn render_assoc_item( } } -const ALLOWED_ATTRIBUTES: &[Symbol] = &[ - sym::export_name, - sym::link_section, - sym::must_use, - sym::no_mangle, - sym::repr, - sym::non_exhaustive, -]; +const ALLOWED_ATTRIBUTES: &[Symbol] = + &[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive]; fn attributes(it: &clean::Item) -> Vec { it.attrs @@ -1007,7 +994,7 @@ fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item) { #[derive(Copy, Clone)] enum AssocItemLink<'a> { Anchor(Option<&'a str>), - GotoSource(FakeDefId, &'a FxHashSet), + GotoSource(ItemId, &'a FxHashSet), } impl<'a> AssocItemLink<'a> { @@ -1031,7 +1018,6 @@ fn render_assoc_items( Some(v) => v, None => return, }; - let tcx = cx.tcx(); let cache = cx.cache(); let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { @@ -1048,7 +1034,7 @@ fn render_assoc_items( write!( w, "

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

", trait_ = trait_.print(cx), @@ -1065,13 +1051,15 @@ fn render_assoc_items( containing_item, AssocItemLink::Anchor(None), render_mode, - containing_item.stable_since(tcx).as_deref(), - containing_item.const_stable_since(tcx).as_deref(), - true, None, - false, - true, &[], + ImplRenderingParameters { + show_def_docs: true, + is_on_foreign_type: false, + show_default_items: true, + show_non_assoc_items: true, + toggle_open_by_default: true, + }, ); } } @@ -1260,6 +1248,16 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { out.into_inner() } +#[derive(Clone, Copy, Debug)] +struct ImplRenderingParameters { + show_def_docs: bool, + is_on_foreign_type: bool, + show_default_items: bool, + /// Whether or not to show methods. + show_non_assoc_items: bool, + toggle_open_by_default: bool, +} + fn render_impl( w: &mut Buffer, cx: &Context<'_>, @@ -1267,15 +1265,9 @@ fn render_impl( parent: &clean::Item, link: AssocItemLink<'_>, render_mode: RenderMode, - outer_version: Option<&str>, - outer_const_version: Option<&str>, - show_def_docs: bool, use_absolute: Option, - is_on_foreign_type: bool, - show_default_items: bool, - // This argument is used to reference same type with different paths to avoid duplication - // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], + rendering_params: ImplRenderingParameters, ) { let cache = cx.cache(); let traits = &cache.traits; @@ -1285,30 +1277,31 @@ fn render_impl( // For trait implementations, the `interesting` output contains all methods that have doc // comments, and the `boring` output contains all methods that do not. The distinction is // used to allow hiding the boring methods. + // `containing_item` is used for rendering stability info. If the parent is a trait impl, + // `containing_item` will the grandparent, since trait impls can't have stability attached. fn doc_impl_item( boring: &mut Buffer, interesting: &mut Buffer, cx: &Context<'_>, item: &clean::Item, parent: &clean::Item, + containing_item: &clean::Item, link: AssocItemLink<'_>, render_mode: RenderMode, is_default_item: bool, - outer_version: Option<&str>, - outer_const_version: Option<&str>, trait_: Option<&clean::Trait>, - show_def_docs: bool, + rendering_params: ImplRenderingParameters, ) { let item_type = item.type_(); let name = item.name.as_ref().unwrap(); - let tcx = cx.tcx(); - let render_method_item = match render_mode { - RenderMode::Normal => true, - RenderMode::ForDeref { mut_: deref_mut_ } => { - should_render_item(&item, deref_mut_, &cx.cache) - } - }; + let render_method_item = rendering_params.show_non_assoc_items + && match render_mode { + RenderMode::Normal => true, + RenderMode::ForDeref { mut_: deref_mut_ } => { + should_render_item(&item, deref_mut_, &cx.cache) + } + }; let in_trait_class = if trait_.is_some() { " trait-impl" } else { "" }; @@ -1331,18 +1324,32 @@ fn render_impl( } else { // In case the item isn't documented, // provide short documentation from the trait. - document_short(&mut doc_buffer, it, cx, link, parent, show_def_docs); + document_short( + &mut doc_buffer, + it, + cx, + link, + parent, + rendering_params.show_def_docs, + ); } } } else { document_item_info(&mut info_buffer, cx, item, Some(parent)); - if show_def_docs { + if rendering_params.show_def_docs { document_full(&mut doc_buffer, item, cx); short_documented = false; } } } else { - document_short(&mut doc_buffer, item, cx, link, parent, show_def_docs); + document_short( + &mut doc_buffer, + item, + cx, + link, + parent, + rendering_params.show_def_docs, + ); } } let w = if short_documented && trait_.is_some() { interesting } else { boring }; @@ -1370,6 +1377,8 @@ fn render_impl( "
", id, item_type, in_trait_class, ); + render_rightside(w, cx, item, containing_item); + write!(w, "", id); w.write_str("

"); render_assoc_item( w, @@ -1379,15 +1388,6 @@ fn render_impl( cx, ); w.write_str("

"); - render_stability_since_raw( - w, - item.stable_since(tcx).as_deref(), - item.const_stable_since(tcx).as_deref(), - outer_version, - outer_const_version, - ); - write!(w, "", id); - write_srclink(cx, item, w); w.write_str("
"); } } @@ -1399,6 +1399,7 @@ fn render_impl( "
", id, item_type, in_trait_class ); + write!(w, "", id); w.write_str("

"); assoc_type( w, @@ -1410,7 +1411,6 @@ fn render_impl( cx, ); w.write_str("

"); - write!(w, "", id); w.write_str("
"); } clean::AssocConstItem(ref ty, ref default) => { @@ -1421,6 +1421,8 @@ fn render_impl( "
", id, item_type, in_trait_class ); + render_rightside(w, cx, item, containing_item); + write!(w, "", id); w.write_str("

"); assoc_const( w, @@ -1432,21 +1434,13 @@ fn render_impl( cx, ); w.write_str("

"); - render_stability_since_raw( - w, - item.stable_since(tcx).as_deref(), - item.const_stable_since(tcx).as_deref(), - outer_version, - outer_const_version, - ); - write!(w, "", id); - write_srclink(cx, item, w); w.write_str("
"); } clean::AssocTypeItem(ref bounds, ref default) => { let source_id = format!("{}.{}", item_type, name); let id = cx.derive_id(source_id.clone()); write!(w, "
", id, item_type, in_trait_class,); + write!(w, "", id); w.write_str("

"); assoc_type( w, @@ -1458,7 +1452,6 @@ fn render_impl( cx, ); w.write_str("

"); - write!(w, "", id); w.write_str("
"); } clean::StrippedItem(..) => return, @@ -1483,13 +1476,12 @@ fn render_impl( cx, trait_item, if trait_.is_some() { &i.impl_item } else { parent }, + parent, link, render_mode, false, - outer_version, - outer_const_version, trait_.map(|t| &t.trait_), - show_def_docs, + rendering_params, ); } @@ -1500,10 +1492,9 @@ fn render_impl( t: &clean::Trait, i: &clean::Impl, parent: &clean::Item, + containing_item: &clean::Item, render_mode: RenderMode, - outer_version: Option<&str>, - outer_const_version: Option<&str>, - show_def_docs: bool, + rendering_params: ImplRenderingParameters, ) { for trait_item in &t.items { let n = trait_item.name; @@ -1520,13 +1511,12 @@ fn render_impl( cx, trait_item, parent, + containing_item, assoc_link, render_mode, true, - outer_version, - outer_const_version, Some(t), - show_def_docs, + rendering_params, ); } } @@ -1535,7 +1525,7 @@ fn render_impl( // default items which weren't overridden in the implementation block. // We don't emit documentation for default items if they appear in the // Implementations on Foreign Types or Implementors sections. - if show_default_items { + if rendering_params.show_default_items { if let Some(t) = trait_ { render_default_items( &mut default_impl_items, @@ -1544,46 +1534,37 @@ fn render_impl( &t.trait_, &i.inner_impl(), &i.impl_item, + parent, render_mode, - outer_version, - outer_const_version, - show_def_docs, + rendering_params, ); } } if render_mode == RenderMode::Normal { - let is_implementing_trait = i.inner_impl().trait_.is_some(); - let toggled = !impl_items.is_empty() || !default_impl_items.is_empty(); + let toggled = !(impl_items.is_empty() && default_impl_items.is_empty()); if toggled { close_tags.insert_str(0, ""); - if is_implementing_trait { - write!(w, "
"); - } else { - write!(w, "
"); - } - } - if toggled { + write!( + w, + "
", + if rendering_params.toggle_open_by_default { " open" } else { "" } + ); write!(w, "") } render_impl_summary( w, cx, i, - outer_version, - outer_const_version, - show_def_docs, + parent, + parent, + rendering_params.show_def_docs, use_absolute, - is_on_foreign_type, + rendering_params.is_on_foreign_type, aliases, ); if toggled { write!(w, "") } - if trait_.is_some() { - if let Some(portability) = portability(&i.impl_item, Some(parent)) { - write!(w, "
{}
", portability); - } - } if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { let mut ids = cx.id_map.borrow_mut(); @@ -1611,12 +1592,35 @@ fn render_impl( w.write_str(&close_tags); } -fn render_impl_summary( +// Render the items that appear on the right side of methods, impls, and +// associated types. For example "1.0.0 (const: 1.39.0) [src]". +fn render_rightside( + w: &mut Buffer, + cx: &Context<'_>, + item: &clean::Item, + containing_item: &clean::Item, +) { + let tcx = cx.tcx(); + + write!(w, "
"); + render_stability_since_raw( + w, + item.stable_since(tcx).as_deref(), + item.const_stability(tcx), + containing_item.stable_since(tcx).as_deref(), + containing_item.const_stable_since(tcx).as_deref(), + ); + + write_srclink(cx, item, w); + w.write_str("
"); +} + +pub(crate) fn render_impl_summary( w: &mut Buffer, cx: &Context<'_>, i: &Impl, - outer_version: Option<&str>, - outer_const_version: Option<&str>, + parent: &clean::Item, + containing_item: &clean::Item, show_def_docs: bool, use_absolute: Option, is_on_foreign_type: bool, @@ -1624,7 +1628,6 @@ fn render_impl_summary( // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], ) { - let tcx = cx.tcx(); let id = cx.derive_id(match i.inner_impl().trait_ { Some(ref t) => { if is_on_foreign_type { @@ -1640,9 +1643,12 @@ fn render_impl_summary( } else { format!(" data-aliases=\"{}\"", aliases.join(",")) }; + write!(w, "
", id, aliases); + render_rightside(w, cx, &i.impl_item, containing_item); + write!(w, "", id); + write!(w, "

"); + if let Some(use_absolute) = use_absolute { - write!(w, "
", id, aliases); - write!(w, "

"); write!(w, "{}", i.inner_impl().print(use_absolute, cx)); if show_def_docs { for it in &i.inner_impl().items { @@ -1653,26 +1659,18 @@ fn render_impl_summary( } } } - w.write_str("

"); } else { - write!( - w, - "
\ -

{}

", - id, - aliases, - i.inner_impl().print(false, cx) - ); + write!(w, "{}", i.inner_impl().print(false, cx)); } - write!(w, "", id); - render_stability_since_raw( - w, - i.impl_item.stable_since(tcx).as_deref(), - i.impl_item.const_stable_since(tcx).as_deref(), - outer_version, - outer_const_version, - ); - write_srclink(cx, &i.impl_item, w); + write!(w, "

"); + + let is_trait = i.inner_impl().trait_.is_some(); + if is_trait { + if let Some(portability) = portability(&i.impl_item, Some(parent)) { + write!(w, "
{}
", portability); + } + } + w.write_str("
"); } @@ -1715,6 +1713,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { write!( buffer, "
\ +
\

Version {}

\
", Escape(version), @@ -1856,7 +1855,7 @@ fn small_url_encode(s: String) -> String { } fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { - let did = it.def_id.expect_real(); + let did = it.def_id.expect_def_id(); if let Some(v) = cx.cache.impls.get(&did) { let mut used_links = FxHashSet::default(); let cache = cx.cache(); @@ -2022,19 +2021,6 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V out.push_str(""); } } - - // Recurse into any further impls that might exist for `target` - if let Some(target_did) = target.def_id_full(c) { - if let Some(target_impls) = c.impls.get(&target_did) { - if let Some(target_deref_impl) = target_impls - .iter() - .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_trait_did) - { - sidebar_deref_methods(cx, out, target_deref_impl, target_impls); - } - } - } } } @@ -2159,7 +2145,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean "", ); - if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) { + if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) { let cache = cx.cache(); let mut res = implementors .iter() diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index aef516e333..b12e56bfe9 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1,6 +1,7 @@ use clean::AttributesExt; use std::cmp::Ordering; +use std::fmt; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -16,16 +17,22 @@ use super::{ collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl, render_stability_since_raw, write_srclink, AssocItemLink, Context, + ImplRenderingParameters, }; use crate::clean::{self, GetDefId}; use crate::formats::item_type::ItemType; use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; -use crate::html::format::{print_abi_with_space, print_where_clause, Buffer, PrintWithSpace}; +use crate::html::format::{ + print_abi_with_space, print_constness_with_space, print_where_clause, Buffer, PrintWithSpace, +}; use crate::html::highlight; use crate::html::layout::Page; use crate::html::markdown::MarkdownSummaryLine; +const ITEM_TABLE_OPEN: &'static str = "
"; +const ITEM_TABLE_CLOSE: &'static str = "
"; + pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) { debug_assert!(!item.is_stripped()); // Write the breadcrumb trail header for the top @@ -93,7 +100,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, render_stability_since_raw( buf, item.stable_since(cx.tcx()).as_deref(), - item.const_stable_since(cx.tcx()).as_deref(), + item.const_stability(cx.tcx()), None, None, ); @@ -127,7 +134,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, clean::StructItem(ref s) => item_struct(buf, cx, item, s), clean::UnionItem(ref s) => item_union(buf, cx, item, s), clean::EnumItem(ref e) => item_enum(buf, cx, item, e), - clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t), + clean::TypedefItem(ref t, is_associated) => item_typedef(buf, cx, item, t, is_associated), clean::MacroItem(ref m) => item_macro(buf, cx, item, m), clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), clean::PrimitiveItem(_) => item_primitive(buf, cx, item), @@ -149,7 +156,7 @@ fn should_hide_fields(n_fields: usize) -> bool { n_fields > 12 } -fn toggle_open(w: &mut Buffer, text: &str) { +fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { write!( w, "
\ @@ -260,14 +267,15 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl curty = myty; } else if myty != curty { if curty.is_some() { - w.write_str(""); + w.write_str(ITEM_TABLE_CLOSE); } curty = myty; let (short, name) = item_ty_to_strs(myty.unwrap()); write!( w, "

\ - {name}

\n", + {name}\n{}", + ITEM_TABLE_OPEN, id = cx.derive_id(short.to_owned()), name = name ); @@ -280,23 +288,23 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl match *src { Some(ref src) => write!( w, - ""); + w.write_str(""); } clean::ImportItem(ref import) => { @@ -323,10 +331,10 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl write!( w, - "\ - \ - \ - ", + "
\ + {vis}{imp}\ +
\ +
{stab_tags}
", stab = stab.unwrap_or_default(), add = add, vis = myitem.visibility.print_with_space(myitem.def_id, cx), @@ -355,11 +363,12 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl let doc_value = myitem.doc_value().unwrap_or_default(); write!( w, - "\ - \ - \ - ", + "
\ + {name}\ + {unsafety_flag}\ + {stab_tags}\ +
\ +
{docs}
", name = *myitem.name.as_ref().unwrap(), stab_tags = extra_info_tags(myitem, item, cx.tcx()), docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(), @@ -379,7 +388,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl } if curty.is_some() { - w.write_str("
{}extern crate {} as {};", + "
{}extern crate {} as {};", myitem.visibility.print_with_space(myitem.def_id, cx), - anchor(myitem.def_id.expect_real(), &*src.as_str(), cx), + anchor(myitem.def_id.expect_def_id(), &*src.as_str(), cx), myitem.name.as_ref().unwrap(), ), None => write!( w, - "
{}extern crate {};", + "
{}extern crate {};", myitem.visibility.print_with_space(myitem.def_id, cx), anchor( - myitem.def_id.expect_real(), + myitem.def_id.expect_def_id(), &*myitem.name.as_ref().unwrap().as_str(), cx ), ), } - w.write_str("
{vis}{imp}{stab_tags}
{name}{unsafety_flag}{stab_tags}{docs}
"); + w.write_str(ITEM_TABLE_CLOSE); } } @@ -429,29 +438,36 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) -> } fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) { - let header_len = format!( - "{}{}{}{}{:#}fn {}{:#}", - it.visibility.print_with_space(it.def_id, cx), - f.header.constness.print_with_space(), - f.header.asyncness.print_with_space(), - f.header.unsafety.print_with_space(), - print_abi_with_space(f.header.abi), - it.name.as_ref().unwrap(), - f.generics.print(cx), - ) - .len(); + let vis = it.visibility.print_with_space(it.def_id, cx).to_string(); + let constness = print_constness_with_space(&f.header.constness, it.const_stability(cx.tcx())); + let asyncness = f.header.asyncness.print_with_space(); + let unsafety = f.header.unsafety.print_with_space(); + let abi = print_abi_with_space(f.header.abi).to_string(); + let name = it.name.as_ref().unwrap(); + + let generics_len = format!("{:#}", f.generics.print(cx)).len(); + let header_len = "fn ".len() + + vis.len() + + constness.len() + + asyncness.len() + + unsafety.len() + + abi.len() + + name.as_str().len() + + generics_len; + w.write_str("
");
     render_attributes_in_pre(w, it, "");
+    w.reserve(header_len);
     write!(
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
          {name}{generics}{decl}{notable_traits}{where_clause}
", - vis = it.visibility.print_with_space(it.def_id, cx), - constness = f.header.constness.print_with_space(), - asyncness = f.header.asyncness.print_with_space(), - unsafety = f.header.unsafety.print_with_space(), - abi = print_abi_with_space(f.header.abi), - name = it.name.as_ref().unwrap(), + vis = vis, + constness = constness, + asyncness = asyncness, + unsafety = unsafety, + abi = abi, + name = name, generics = f.generics.print(cx), where_clause = print_where_clause(&f.generics, cx, 0, true), decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx), @@ -466,6 +482,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); let required = t.items.iter().filter(|m| m.is_ty_method()).collect::>(); let provided = t.items.iter().filter(|m| m.is_method()).collect::>(); + let count_types = types.len(); + let count_consts = consts.len(); + let count_methods = required.len() + provided.len(); // Output the trait definition wrap_into_docblock(w, |w| { @@ -496,9 +515,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra let mut toggle = false; // If there are too many associated types, hide _everything_ - if should_hide_fields(types.len()) { + if should_hide_fields(count_types) { toggle = true; - toggle_open(w, "associated items"); + toggle_open( + w, + format_args!("{} associated items", count_types + count_consts + count_methods), + ); } for t in &types { render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx); @@ -508,9 +530,18 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra // We also do this if the types + consts is large because otherwise we could // render a bunch of types and _then_ a bunch of consts just because both were // _just_ under the limit - if !toggle && should_hide_fields(types.len() + consts.len()) { + if !toggle && should_hide_fields(count_types + count_consts) { toggle = true; - toggle_open(w, "associated constants and methods"); + toggle_open( + w, + format_args!( + "{} associated constant{} and {} method{}", + count_consts, + pluralize(count_consts), + count_methods, + pluralize(count_methods), + ), + ); } if !types.is_empty() && !consts.is_empty() { w.write_str("\n"); @@ -519,9 +550,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx); w.write_str(";\n"); } - if !toggle && should_hide_fields(required.len() + provided.len()) { + if !toggle && should_hide_fields(count_methods) { toggle = true; - toggle_open(w, "methods"); + toggle_open(w, format_args!("{} methods", count_methods)); } if !consts.is_empty() && !required.is_empty() { w.write_str("\n"); @@ -586,11 +617,13 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra write!(w, "
"); } write!(w, "
", id); + write!(w, "
"); + render_stability_since(w, m, t, cx.tcx()); + write_srclink(cx, m, w); + write!(w, "
"); write!(w, "

"); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx); w.write_str("

"); - render_stability_since(w, m, t, cx.tcx()); - write_srclink(cx, m, w); w.write_str("
"); if toggled { write!(w, "
"); @@ -652,9 +685,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All); + render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All); - if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) { + if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) { // The DefId is for the first Type found with that name. The bool is // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap = FxHashMap::default(); @@ -702,13 +735,15 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra it, assoc_link, RenderMode::Normal, - implementor.impl_item.stable_since(cx.tcx()).as_deref(), - implementor.impl_item.const_stable_since(cx.tcx()).as_deref(), - false, None, - true, - false, &[], + ImplRenderingParameters { + show_def_docs: false, + is_on_foreign_type: true, + show_default_items: false, + show_non_assoc_items: true, + toggle_open_by_default: false, + }, ); } } @@ -772,7 +807,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra path = if it.def_id.is_local() { cx.current.join("/") } else { - let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_real()]; + let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_def_id()]; path[..path.len() - 1].join("/") }, ty = it.type_(), @@ -798,7 +833,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All) } fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) { @@ -819,12 +854,21 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean: // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All) } -fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { +fn item_typedef( + w: &mut Buffer, + cx: &Context<'_>, + it: &clean::Item, + t: &clean::Typedef, + is_associated: bool, +) { w.write_str("
");
     render_attributes_in_pre(w, it, "");
+    if !is_associated {
+        write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
+    }
     write!(
         w,
         "type {}{}{where_clause} = {type_};
", @@ -836,7 +880,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T document(w, cx, it, None); - let def_id = it.def_id.expect_real(); + let def_id = it.def_id.expect_def_id(); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but @@ -865,7 +909,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni if fields.peek().is_some() { write!( w, - "

+ "

\ Fields

" ); for (field, ty) in fields { @@ -888,7 +932,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni document(w, cx, field, Some(it)); } } - let def_id = it.def_id.expect_real(); + let def_id = it.def_id.expect_def_id(); render_assoc_items(w, cx, it, def_id, AssocItemRender::All); document_type_layout(w, cx, def_id); } @@ -909,9 +953,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum w.write_str(" {}"); } else { w.write_str(" {\n"); - let toggle = should_hide_fields(e.variants.len()); + let count_variants = e.variants.len(); + let toggle = should_hide_fields(count_variants); if toggle { - toggle_open(w, "variants"); + toggle_open(w, format_args!("{} variants", count_variants)); } for v in &e.variants { w.write_str(" "); @@ -954,8 +999,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum if !e.variants.is_empty() { write!( w, - "

- Variants{}

\n", + "

\ + Variants{}

", document_non_exhaustive_header(it) ); document_non_exhaustive(w, it); @@ -980,19 +1025,20 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum } w.write_str(")"); } - w.write_str(""); + w.write_str(""); + render_stability_since(w, variant, it, cx.tcx()); + w.write_str(""); document(w, cx, variant, Some(it)); document_non_exhaustive(w, variant); use crate::clean::Variant; if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind { - toggle_open(w, "fields"); let variant_id = cx.derive_id(format!( "{}.{}.fields", ItemType::Variant, variant.name.as_ref().unwrap() )); - write!(w, "
", id = variant_id); + write!(w, "
", id = variant_id); write!( w, "

Fields of {name}

", @@ -1020,12 +1066,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum } } w.write_str("
"); - toggle_close(w); } - render_stability_since(w, variant, it, cx.tcx()); } } - let def_id = it.def_id.expect_real(); + let def_id = it.def_id.expect_def_id(); render_assoc_items(w, cx, it, def_id, AssocItemRender::All); document_type_layout(w, cx, def_id); } @@ -1077,7 +1121,7 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { document(w, cx, it, None); - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All) } fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) { @@ -1140,7 +1184,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St if fields.peek().is_some() { write!( w, - "

+ "

\ Fields{}

", document_non_exhaustive_header(it) ); @@ -1166,7 +1210,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St } } } - let def_id = it.def_id.expect_real(); + let def_id = it.def_id.expect_def_id(); render_assoc_items(w, cx, it, def_id, AssocItemRender::All); document_type_layout(w, cx, def_id); } @@ -1197,7 +1241,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { document(w, cx, it, None); - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All) } fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { @@ -1289,7 +1333,7 @@ fn render_stability_since( render_stability_since_raw( w, item.stable_since(tcx).as_deref(), - item.const_stable_since(tcx).as_deref(), + item.const_stability(tcx), containing_item.stable_since(tcx).as_deref(), containing_item.const_stable_since(tcx).as_deref(), ) @@ -1311,7 +1355,7 @@ fn render_implementor( implementor_dups: &FxHashMap, aliases: &[String], ) { - // If there's already another implementor that has the same abbridged name, use the + // If there's already another implementor that has the same abridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { clean::ResolvedPath { ref path, is_generic: false, .. } @@ -1328,13 +1372,15 @@ fn render_implementor( trait_, AssocItemLink::Anchor(None), RenderMode::Normal, - trait_.stable_since(cx.tcx()).as_deref(), - trait_.const_stable_since(cx.tcx()).as_deref(), - false, Some(use_absolute), - false, - false, aliases, + ImplRenderingParameters { + show_def_docs: false, + is_on_foreign_type: false, + show_default_items: false, + show_non_assoc_items: false, + toggle_open_by_default: false, + }, ); } @@ -1364,7 +1410,7 @@ fn render_union( fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(w, "fields"); + toggle_open(w, format_args!("{} fields", count_fields)); } for field in fields { @@ -1420,7 +1466,7 @@ fn render_struct( let has_visible_fields = count_fields > 0; let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(w, "fields"); + toggle_open(w, format_args!("{} fields", count_fields)); } for field in fields { if let clean::StructFieldItem(ref ty) = *field.kind { @@ -1597,3 +1643,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { writeln!(w, "
"); } + +fn pluralize(count: usize) -> &'static str { + if count > 1 { "s" } else { "" } +} diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index a4188e6b20..94a902a2d0 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -25,10 +25,16 @@ static FILES_UNVERSIONED: Lazy> = Lazy::new(|| { "FiraSans-Regular.woff" => static_files::fira_sans::REGULAR, "FiraSans-Medium.woff" => static_files::fira_sans::MEDIUM, "FiraSans-LICENSE.txt" => static_files::fira_sans::LICENSE, + "SourceSerif4-Regular.ttf.woff2" => static_files::source_serif_4::REGULAR2, + "SourceSerif4-Bold.ttf.woff2" => static_files::source_serif_4::BOLD2, + "SourceSerif4-It.ttf.woff2" => static_files::source_serif_4::ITALIC2, "SourceSerif4-Regular.ttf.woff" => static_files::source_serif_4::REGULAR, "SourceSerif4-Bold.ttf.woff" => static_files::source_serif_4::BOLD, "SourceSerif4-It.ttf.woff" => static_files::source_serif_4::ITALIC, "SourceSerif4-LICENSE.md" => static_files::source_serif_4::LICENSE, + "SourceCodePro-Regular.ttf.woff2" => static_files::source_code_pro::REGULAR2, + "SourceCodePro-Semibold.ttf.woff2" => static_files::source_code_pro::SEMIBOLD2, + "SourceCodePro-It.ttf.woff2" => static_files::source_code_pro::ITALIC2, "SourceCodePro-Regular.ttf.woff" => static_files::source_code_pro::REGULAR, "SourceCodePro-Semibold.ttf.woff" => static_files::source_code_pro::SEMIBOLD, "SourceCodePro-It.ttf.woff" => static_files::source_code_pro::ITALIC, @@ -460,7 +466,14 @@ pub(super) fn write_shared( }) .collect::() ); - let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files); + let v = layout::render( + &cx.shared.templates, + &cx.shared.layout, + &page, + "", + content, + &cx.shared.style_files, + ); cx.shared.fs.write(&dst, v.as_bytes())?; } } diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 5e2a94fe68..80dd7a7a95 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -136,6 +136,7 @@ impl SourceCollector<'_, 'tcx> { static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; let v = layout::render( + &self.scx.templates, &self.scx.layout, &page, "", diff --git a/src/librustdoc/html/static/COPYRIGHT.txt b/src/librustdoc/html/static/COPYRIGHT.txt index 16d79032fc..c2629a83f7 100644 --- a/src/librustdoc/html/static/COPYRIGHT.txt +++ b/src/librustdoc/html/static/COPYRIGHT.txt @@ -2,7 +2,8 @@ These documentation pages include resources by third parties. This copyright file applies only to those resources. The following third party resources are included, and carry their own copyright notices and license terms: -* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): +* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2, + FiraSans-Regular.woff, FiraSans-Medium.woff): Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ with Reserved Font Name Fira Sans. @@ -23,8 +24,10 @@ included, and carry their own copyright notices and license terms: Copyright (c) Nicolas Gallagher and Jonathan Neal. Licensed under the MIT license (see LICENSE-MIT.txt). -* Source Code Pro (SourceCodePro-Regular.ttf.woff, - SourceCodePro-Semibold.ttf.woff, SourceCodePro-It.ttf.woff): +* Source Code Pro (SourceCodePro-Regular.ttf.woff2, + SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2, + SourceCodePro-Regular.ttf.woff, SourceCodePro-Semibold.ttf.woff, + SourceCodePro-It.ttf.woff): Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark @@ -33,8 +36,9 @@ included, and carry their own copyright notices and license terms: Licensed under the SIL Open Font License, Version 1.1. See SourceCodePro-LICENSE.txt. -* Source Serif 4 (SourceSerif4-Regular.ttf.woff, SourceSerif4-Bold.ttf.woff, - SourceSerif4-It.ttf.woff): +* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, + SourceSerif4-It.ttf.woff2, SourceSerif4-Regular.ttf.woff, + SourceSerif4-Bold.ttf.woff, SourceSerif4-It.ttf.woff): Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United diff --git a/src/librustdoc/html/static/css/normalize.css b/src/librustdoc/html/static/css/normalize.css new file mode 100644 index 0000000000..fdb8a8c652 --- /dev/null +++ b/src/librustdoc/html/static/css/normalize.css @@ -0,0 +1,2 @@ +/* ignore-tidy-linelength */ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} diff --git a/src/librustdoc/html/static/noscript.css b/src/librustdoc/html/static/css/noscript.css similarity index 100% rename from src/librustdoc/html/static/noscript.css rename to src/librustdoc/html/static/css/noscript.css diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css similarity index 93% rename from src/librustdoc/html/static/rustdoc.css rename to src/librustdoc/html/static/css/rustdoc.css index f801ef09c5..91243a4086 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -23,21 +23,27 @@ font-family: 'Source Serif 4'; font-style: normal; font-weight: 400; - src: local('Source Serif 4'), url("SourceSerif4-Regular.ttf.woff") format('woff'); + src: local('Source Serif 4'), + url("SourceSerif4-Regular.ttf.woff2") format("woff2"), + url("SourceSerif4-Regular.ttf.woff") format("woff"); font-display: swap; } @font-face { font-family: 'Source Serif 4'; font-style: italic; font-weight: 400; - src: local('Source Serif 4 Italic'), url("SourceSerif4-It.ttf.woff") format('woff'); + src: local('Source Serif 4 Italic'), + url("SourceSerif4-It.ttf.woff2") format("woff2"), + url("SourceSerif4-It.ttf.woff") format("woff"); font-display: swap; } @font-face { font-family: 'Source Serif 4'; font-style: normal; font-weight: 700; - src: local('Source Serif 4 Bold'), url("SourceSerif4-Bold.ttf.woff") format('woff'); + src: local('Source Serif 4 Bold'), + url("SourceSerif4-Bold.ttf.woff2") format("woff2"), + url("SourceSerif4-Bold.ttf.woff") format("woff"); font-display: swap; } @@ -48,21 +54,24 @@ font-weight: 400; /* Avoid using locally installed font because bad versions are in circulation: * see https://github.com/rust-lang/rust/issues/24355 */ - src: url("SourceCodePro-Regular.ttf.woff") format('woff'); + src: url("SourceCodePro-Regular.ttf.woff2") format("woff2"), + url("SourceCodePro-Regular.ttf.woff") format("woff"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: italic; font-weight: 400; - src: url("SourceCodePro-It.ttf.woff") format('woff'); + src: url("SourceCodePro-It.ttf.woff2") format("woff2"), + url("SourceCodePro-It.ttf.woff") format("woff"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 600; - src: url("SourceCodePro-Semibold.ttf.woff") format('woff'); + src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2"), + url("SourceCodePro-Semibold.ttf.woff") format("woff"); font-display: swap; } @@ -134,7 +143,7 @@ h1.fqn { h1.fqn > .in-band > a:hover { text-decoration: underline; } -#main > h2, #main > h3, #main > h4 { +h2, h3, h4 { border-bottom: 1px solid; } h3.code-header, h4.code-header { @@ -173,6 +182,7 @@ div.impl-items > div { h1, h2, h3, h4, .sidebar, a.source, .search-input, .search-results .result-name, .content table td:first-child > a, +.item-left > a, div.item-list .out-of-band, span.since, #source-sidebar, #sidebar-toggle, details.rustdoc-toggle > summary::before, @@ -244,6 +254,9 @@ code, pre, a.test-arrow, .code-header { pre { padding: 14px; } +.type-decl pre { + overflow-x: auto; +} .source .content pre { padding: 20px; @@ -323,6 +336,7 @@ nav.sub { .logo-container > img { max-width: 100px; max-height: 100px; + height: 100%; position: absolute; left: 50%; top: 50%; @@ -436,7 +450,7 @@ nav.sub { border-bottom-left-radius: 5px; } -.rustdoc:not(.source) .example-wrap > pre.rust { +.rustdoc:not(.source) .example-wrap > pre:not(.line-number) { width: 100%; overflow-x: auto; } @@ -517,7 +531,6 @@ nav.sub { .method > .code-header, .trait-impl > .code-header, .invisible > .code-header { max-width: calc(100% - 41px); display: block; - flex-grow: 1; } .invisible { @@ -555,7 +568,8 @@ nav.sub { .docblock table { margin: .5em 0; width: calc(100% - 2px); - border: 1px dashed; + overflow-x: auto; + display: block; } .docblock table td { @@ -626,7 +640,6 @@ nav.sub { .content .item-info { position: relative; margin-left: 33px; - margin-top: -6px; } .sub-variant > div > .item-info { @@ -637,7 +650,7 @@ nav.sub { content: '⬑'; font-size: 25px; position: absolute; - top: 0px; + top: -6px; left: -19px; } @@ -699,6 +712,12 @@ a { background: transparent; } +.small-section-header { + display: flex; + justify-content: space-between; + position: relative; +} + .small-section-header:hover > .anchor { display: initial; } @@ -741,6 +760,25 @@ a { .block a.current.crate { font-weight: 500; } +.item-table { + display: grid; + column-gap: 1.2rem; + row-gap: 0.0rem; + grid-template-columns: auto 1fr; + /* align content left */ + justify-items: start; +} + +.item-left, .item-right { + display: block; +} +.item-left { + grid-column: 1; +} +.item-right { + grid-column: 2; +} + .search-container { position: relative; } @@ -896,22 +934,21 @@ body.blur > :not(#help) { padding: 0 20px 20px 17px;; } -.stab { +.item-info .stab { display: table; +} +.stab { border-width: 1px; border-style: solid; padding: 3px; margin-bottom: 5px; font-size: 90%; + font-weight: normal; } .stab p { display: inline; } -.stab summary { - display: list-item; -} - .stab .emoji { font-size: 1.5em; } @@ -932,7 +969,7 @@ body.blur > :not(#help) { font-size: 80%; line-height: 1.2; margin-bottom: 0; - margin-right: .3em; + margin-left: .3em; padding: 2px; vertical-align: text-bottom; } @@ -945,32 +982,25 @@ body.blur > :not(#help) { .since { font-weight: normal; font-size: initial; - position: absolute; - right: 0; - top: 0; } .impl-items .since, .impl .since, .methods .since { - flex-grow: 0; padding-left: 12px; - padding-right: 6px; + padding-right: 2px; position: initial; } .impl-items .srclink, .impl .srclink, .methods .srclink { - flex-grow: 0; /* Override header settings otherwise it's too bold */ font-size: 17px; font-weight: normal; } -.impl-items code, .impl code, .methods code { - flex-grow: 1; +.rightside { + float: right; } .has-srclink { - display: flex; - flex-basis: 100%; font-size: 16px; margin-bottom: 12px; /* Push the src link out to the right edge consistently */ @@ -1031,7 +1061,6 @@ a.test-arrow:hover{ } .since + .srclink { - display: table-cell; padding-left: 10px; } @@ -1051,7 +1080,7 @@ a.test-arrow:hover{ padding-top: 1px; } -#main > details > .sub-variant > h3 { +#main .sub-variant > h3 { font-size: 15px; margin-left: 25px; margin-bottom: 5px; @@ -1082,14 +1111,14 @@ a.test-arrow:hover{ left: -10px; } -#main > .variant, #main > .structfield { - display: block; -} - :target > code, :target > .code-header { opacity: 1; } +:target { + padding-right: 3px; +} + .information { position: absolute; left: -25px; @@ -1636,9 +1665,25 @@ details.undocumented[open] > summary::before { } .sidebar > .block.version { + overflow: hidden; border-bottom: none; - margin-top: 12px; margin-bottom: 0; + height: 100%; + padding-left: 12px; + } + .sidebar > .block.version > div.narrow-helper { + float: left; + width: 1px; + height: 100%; + } + .sidebar > .block.version > p { + /* hide Version text if too narrow */ + margin: 0; + min-width: 55px; + /* vertically center */ + display: flex; + align-items: center; + height: 100%; } nav.sub { @@ -1659,11 +1704,6 @@ details.undocumented[open] > summary::before { margin-left: 0; } - .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant, - .impl-items > .associatedtype { - display: flex; - } - .anchor { display: none !important; } @@ -1708,7 +1748,8 @@ details.undocumented[open] > summary::before { width: calc(100% + 30px); } - .show-it { + .show-it, .sidebar-elems:focus-within { + z-index: 2; left: 0; } @@ -1778,6 +1819,16 @@ details.undocumented[open] > summary::before { #help-button { display: none; } + + /* Display an alternating layout on tablets and phones */ + .item-table { + display: flex; + flex-flow: column wrap; + } + .item-left, .item-right { + width: 100%; + } + .search-container > div { width: calc(100% - 32px); } @@ -1790,7 +1841,7 @@ details.undocumented[open] > summary::before { .search-results .result-name, .search-results div.desc, .search-results .result-description { width: 100%; } - .search-results div.desc, .search-results .result-description { + .search-results div.desc, .search-results .result-description, .item-right { padding-left: 2em; } } diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/css/settings.css similarity index 100% rename from src/librustdoc/html/static/settings.css rename to src/librustdoc/html/static/css/settings.css diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css similarity index 98% rename from src/librustdoc/html/static/themes/ayu.css rename to src/librustdoc/html/static/css/themes/ayu.css index 1fc648d76b..df386fb66a 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -34,7 +34,7 @@ h4 { background: rgba(0, 0, 0, 0); } -code { +.docblock code { color: #ffb454; } h3 > code, h4 > code, h5 > code { @@ -133,13 +133,14 @@ pre, .rustdoc.source .example-wrap { color: #708090; background-color: rgba(255, 236, 164, 0.06); padding-right: 4px; + border-right: 1px solid #ffb44c; } .docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { border-bottom-color: #5c6773; } -.docblock table, .docblock table td, .docblock table th { +.docblock table td, .docblock table th { border-color: #5c6773; } @@ -160,7 +161,7 @@ pre, .rustdoc.source .example-wrap { .search-results a { color: #0096cf; } -.search-results a span.desc { +.search-results a div.desc { color: #c5c5c5; } @@ -285,7 +286,7 @@ details.undocumented > summary::before { color: grey; } -tr.result span.primitive::after, tr.result span.keyword::after { +.result-name .primitive > i, .result-name .keyword > i { color: #788797; } @@ -335,6 +336,9 @@ a.test-arrow:hover { :target, :target > * { background: rgba(255, 236, 164, 0.06); +} + +:target { border-right: 3px solid rgba(255, 180, 76, 0.85); } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css similarity index 98% rename from src/librustdoc/html/static/themes/dark.css rename to src/librustdoc/html/static/css/themes/dark.css index 3105a99de1..c8a5dbdc66 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -97,7 +97,7 @@ pre, .rustdoc.source .example-wrap { border-bottom-color: #DDD; } -.docblock table, .docblock table td, .docblock table th { +.docblock table td, .docblock table th { border-color: #ddd; } @@ -247,7 +247,7 @@ details.undocumented > summary::before { color: grey; } -tr.result span.primitive::after, tr.result span.keyword::after { +.result-name .primitive > i, .result-name .keyword > i { color: #ddd; } @@ -286,6 +286,10 @@ a.test-arrow:hover{ background-color: #494a3d; } +:target { + border-right: 3px solid #bb7410; +} + pre.compile_fail { border-left: 2px solid rgba(255,0,0,.8); } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/css/themes/light.css similarity index 98% rename from src/librustdoc/html/static/themes/light.css rename to src/librustdoc/html/static/css/themes/light.css index 10fde92dcb..bc18a72450 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -97,7 +97,7 @@ pre, .rustdoc.source .example-wrap { border-bottom-color: #ddd; } -.docblock table, .docblock table td, .docblock table th { +.docblock table td, .docblock table th { border-color: #ddd; } @@ -159,9 +159,6 @@ a.result-keyword:focus { background-color: #f99650; } .content .fnname { color: #9a6e31; } .content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; } -pre.rust .comment { color: #8E908C; } -pre.rust .doccomment { color: #4D4D4C; } - nav:not(.sidebar) { border-bottom-color: #e0e0e0; } @@ -240,7 +237,7 @@ details.undocumented > summary::before { color: grey; } -tr.result span.primitive::after, tr.result span.keyword::after { +.result-name .primitive > i, .result-name .keyword > i { color: black; } @@ -252,6 +249,8 @@ 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, pre.rust .attribute .ident { 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 { @@ -279,6 +278,10 @@ a.test-arrow:hover{ background: #FDFFD3; } +:target { + border-right: 3px solid #ffb44c; +} + pre.compile_fail { border-left: 2px solid rgba(255,0,0,.5); } diff --git a/src/librustdoc/html/static/FiraSans-LICENSE.txt b/src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt similarity index 99% rename from src/librustdoc/html/static/FiraSans-LICENSE.txt rename to src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt index d444ea92b6..ff9afab064 100644 --- a/src/librustdoc/html/static/FiraSans-LICENSE.txt +++ b/src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt @@ -1,5 +1,5 @@ Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. -with Reserved Font Name < Fira >, +with Reserved Font Name < Fira >, This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: @@ -19,7 +19,7 @@ with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, +fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The diff --git a/src/librustdoc/html/static/FiraSans-Medium.woff b/src/librustdoc/html/static/fonts/FiraSans-Medium.woff similarity index 100% rename from src/librustdoc/html/static/FiraSans-Medium.woff rename to src/librustdoc/html/static/fonts/FiraSans-Medium.woff diff --git a/src/librustdoc/html/static/FiraSans-Medium.woff2 b/src/librustdoc/html/static/fonts/FiraSans-Medium.woff2 similarity index 100% rename from src/librustdoc/html/static/FiraSans-Medium.woff2 rename to src/librustdoc/html/static/fonts/FiraSans-Medium.woff2 diff --git a/src/librustdoc/html/static/FiraSans-Regular.woff b/src/librustdoc/html/static/fonts/FiraSans-Regular.woff similarity index 100% rename from src/librustdoc/html/static/FiraSans-Regular.woff rename to src/librustdoc/html/static/fonts/FiraSans-Regular.woff diff --git a/src/librustdoc/html/static/FiraSans-Regular.woff2 b/src/librustdoc/html/static/fonts/FiraSans-Regular.woff2 similarity index 100% rename from src/librustdoc/html/static/FiraSans-Regular.woff2 rename to src/librustdoc/html/static/fonts/FiraSans-Regular.woff2 diff --git a/src/librustdoc/html/static/SourceCodePro-It.ttf.woff b/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff similarity index 100% rename from src/librustdoc/html/static/SourceCodePro-It.ttf.woff rename to src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceCodePro-It.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..462c34efcd9d6b70b42359ca1a1d9476efe43eeb GIT binary patch literal 44896 zcmV({K+?Z=Pew8T0RR910Iy&G4gdfE0nTUu0Ivi90S?&!00000000000000000000 z0000PMjC_$8>N06tv&`|0ND--gv@Y*#diynZ~y@|0we>Ia0DO)nHC4y7Fz;g^QUR-U>{{R2~-;pfF znEyxK^MD~{S_^ZvZJW@jqFZvwvE=cL>SS%!7k9J}@oIWizRXQF&f>}$LhRiq^@4?xgspR-qywNkz(HVnPb>Cyk2C#LU_3C23!ia>e(7`W3z0I|O2>5tqNMeQ)fBmVn&FUMUQBxb>kfOni-uQobvy1C2KD-x9HyL~T z8AHa?kKud4gk&GcLtt<$z=u@YSn1q8;|oH`{#&y5!HYU*(NV&<%3a3h|H}?a%t_7TuH9a|{+nv~A5fYblX2}a<@wDCQU|on0cs-nkLNe-%$)}$gr;i0 z0;!0kT@kg4h;5jE|6WsLt0!n!+nl{-Ks@;ix-a%x08>3Yzs;WV)#(>O5Ku&-3~Ve= z0Ra(&7NfCp;moBylaPD&)|h3b!5E ze+68s=)&q*e$@~~#E+_4K(Z_R^O6UnZH>fEB^nEJKiVGq0d#(kZAgl!Ura_f=Y~ko5_xy;?y9 zjpzTj{CO#*3Nw@kUDz$OYj>%_aLz(cGCBvFI^XO|X=4#43c8P_jtXGfWqP7R{>-@A zbNzv9nXTyqsirkG4<|UV4fHvxRu`GJpYGjn-2!S%urx|2lLee&y5yYawVzCx;7F0G#(=l_S5r@{CEqv_@wJePn=7GzYMn6&-LI{x}&Z1pDj4RGml4s0={UJ2wG8KtQPA(v*3?fV5(bVAIG-1-%D+z;x>1AKbMu8+43{`GMU# z{nE^uOPX}R9dMu2;Qn8oy#!lltXIV^@3qS#5opSZrVc1_WrmyDKcYzZUq5Qb$$};>$ct89XP;bx zyOw~i{O8Ze($}|QLARBMwEGoDr3{y9dLebTA`spf*Ly&Q;759YU&h zJEzt~nLFohyUwTIs_-#UW5MbUxZzTNd)I!CoL~w1|1ICyd3*Q$wrRtrN?LQ^b5IzG zk^5)=&(G#EX>Bu?5!SX(+u zr9q39Dn>U(AN~nIA);>Me@o2?1i~NHgi%ozTJZ0NRK6cJS-1)}$RI_ec)3u&_SWm) z)7Vm$k+-QS)dUlYkT&Vy4xunnczUw#QvP}?;=!(bg@B07VS`PLPEActA&-PK$!$wZ zO9*h?0_V~x5}wQBlV>Kw+DvL$Zbni9+Vd7y`Mkd|?K`uYEp2A<>t&l88!;*fC=YlP zjdwiX+*sK!TV66GlUXiYXb(i+uPxt)YG~fx5L>muccyl@CeY?UfSLc?J%!z%X#Ugb zdO93I&GP$g;`pHUy2tThHtleHG~ACkt_T1G1zWKbWJ3%A5MXuyoI?RG3Me3;#x4-- zMU;nQ=<;wD0}ki#<>4BoJUpP4hbQ#%@SI5=Xj$cf0RsYFya=R8BakD9K$R*2GiE4o z%Y5)hKKB!m>RVh~b0 zj(k!tkv!5Qg?!REyL{3$1ch8v1clsC93i)tMIrapfsp5#LdZ+aM#wvLA>_BTD5PIL zgbXc;kool^WKjdC$>N4k$kHYevbGt7Y-kQ4Tl)x+BYl9#ss4pXk+>-^F<1#E6^@@t zSKUmBHO!P8X(nT|nM^Te8XtS6%y=_Bo^~dCx&=+mJZVPunPvr#=wRrA-vF10>!%vFIt`Z}xFhB1bQUMiE!VflL@v5lR>bWTNFf}dOS0R)E3 z51c`va;onu^#6$x78RWTKpAQ?Zvv>|f+{GZgp?e?{k{&t^1E%%$`~MAmRO}!xgDz2 z_fB`j$wIo zVJV(E1GB@j_r1h}77TapaL=Q`-n>lZ+dS;B+MOCV8f4H`YQFJb5Gz{tf3Lgx8DUD+ za4`hI*&-GK6%KYGBHHNTfbqhG5RtFZ=d2z7Dlm~ubE^X=jyRMMLyQ3gsvUEz&{n7& z;`Hgo7o1;ti7Q-dndNtLtK8$$)>y5*#+lx+kL(Nk&VDg=f-24#ph=>cfSRZ?;*kq_ z<4^k=DAMl?tNE{4IFj|-urOv&+0dXRLtm+7nq`?eAxrnlX4bj>+Vs@UKn24!ipMfB ziN9*BADc&|Us%6(l(P4YXYChX;$D?hFWEW0q4)HOzS0k>vv{X0To*7~?9i9rIlhwU zUFF{KxtDDBJe_A%Df3U8$9mBR0wu_Gma~bbZa!Uv`RpdVYIk-B)m#_hOoJsjf|YS;PAni)vBrZNU>8P42^MjB9L14imbqBq zkRthuWtR2Czqr`Sr@@`Zc16KrmsG+VEWcDj{^OQXxhupYgnytgnm3$t?Ch+0h$#!! zycOrO0V5itCdEI!-Ac&AM}TDULzJGwf<+Bl05p6bLVNNM0zPmOp)z_#r4qbBf5e@T zyKo`96Fd<|3w8tg;J4`E1e?_(#t?nkpg+!LB6MQw^uKYdWWd^8w=1MVNL0+=@S#Ju z7(hfcSBx=g!etsgSLLOR&v~T;+JnU#OBXgL#{sTP@Xa5 zuZZPhtO=*KG*t#~6I9KVzC;XWu%_$O%r>^u7_vRC0`2d$%Y(=H!JsFOS6e&r$14Tp10S*RJAqGDAKlaAzDxD7!^D z34N>wCmITbe#F?pg>j{8eh?J?OGPdX@w}1&QI>>C{j|v@4NO4`%ZP0e>bV|Db;*2& zR+48hqRK#o16XOCB#^}Bw1_xhrSa5*X(%Z9km1uCGBY0I7KA4YO&NJ^rLmDX@Bm(bd53Uhy^l-rV;6jMV z*XVQBj(-)HNJinvbc=+F0rG-27?)}vChU6}KXIPxp}M+xyC^jCdwW%_>V6LlmSVwp zgBe@{oSdtp25O-;(#W6yjS2Mx*KxbgeAD-Hz@bMRdGeWOopas=2Zu-3Zb*(5Sc&7X zzJ>@9BSo&UrYJLNp(fI(j|ON#&fo6=N1Sx>DW{!r)_Lbkye@y?;-za%GAxs`#8+4S zo@tsep8*~)6fz#orhQ)x)dmOCad7Z0a z=!VrkHCnas>eOpMKt$H42?Z4`SuE>RVFoVs$oLyw6xiSsp3$N8r{!PP*V056r`Yv2t0sOs;H5CY1zk0pUpmPawo zvBQ`HE}+trZ}6rM*(k#r#WzZ?bQ+*78o9g{4#3vn6cx=PnbAq@|3C5rmriZyoXOp%gTY5C|T(}WFkr!fhX4^0WGGOfL5G1W3BuLs&&ui9 zx$qMwPmv}=mK=Es6e&@rLX{eI8nkrxa(<=JCe{X12IM#i!yv^~W+Z&DaF}hGQdRx4 z_Z?et^@_KA;4|O&$+0+7w5oU6P4_h8bw;Rc6%}iPsel|OVKSUPM#^XcGb_71&X`@I z=38QgwaS#Mian+3X*FuS<{cmTBEBnAzc}HX23L7_!(Xo2iNYlPZ8$aVnbIAfs8DF= zr83E6VcR}I9Ex+eEVEvveGc|-JifD`T=7Z&)ssgRRf-?fIpu;z*WI~odi%2~0w4&A z=rhnpHW>QEuBDX>ODjpbak6BOoR?6OahPwtU21*eSby~+R+cdVf}n^#18rnONw@E2 zMaxQ%Y8*2gM>vbDOR;5ES#Pt-*imfvdDcNMdBb}?iLXlS59*w9L8I&LL{pg!5Clc^ z8E7N3qvejJl_cFbS+ZZ|{Kvl~>o8N1xfXFNnM$W8ZMDPG4tv8#z8Q7@vQ_6axXQ!J zul?+a03-e}28JAle!24`whBbTwu}^WDKK3wTR2L$<;a$0oODUFVJL`|k`ixZIOCWD zaia7s2@|#R^YTPfCH5WHHM-!GIzPm*O6s3{<1-(4%PS7YYn9x!YCLU^D&@+evJAc1 zdaEo`%+(5JU^(V89FhN{%Dy&$mQ*aMU5O!M`lM%qJOD$2*QqG^qRf)%^K*+_0d1JAM@gl@m+=+T z%0Z(s-vM6P{*JhQ!`iL$M)6o+z&NsSGLtvBOfyY*xyPN(Nj>OGZgOX0c&wUYoEMZl zJ$h6?M#BVpdWU`zo>~hnOfbPLW)fKwZS8TdgLy_v9h*^U#bO)?7L~WZl>r%ACf&ZV ziVThfBs841$aim><-4z~@;%TF`7U&}d=IgZ0~>P1J`uV+2&qag?I!>>bu2xOD-+75 z9+Mzr%inrpnq>Czoi*!{Hy2XRk?VSm7*R@kRw8C$CT7C)r<0~0Sw<(T}?KVk@62Ul!HA4ipS zy{0x35|?PDLn2Pf3aZ~RmEr2bGT-jY-Yy{7BR(LWzvXiGnahNm!yH98nVui6dII@aoiSKtM!7)~E>u z6%Bn-=QO%nw_g1Qef8Z>zx@RT2Luj#-hxlS#lxR;Z24*m4GWKmjEatlO-PK3A9BM| z$kSJkCNTNdBT{C>Wb=!Q1eORPqx)VV>BVa7PU2zL{tW}!Yz*DHqz*D2MhFg zl@)0=T3Mx?n|xy)A%3uj0oNGJ#0n6lb*h%Cw2qU~wQdEj!h(YyX>i;1eww8)OrK&g zNhO!rl2A0tW+=@cyfoq79feJF@t9}xvcl}=>CPBc&=OeP6Ri?aoMKhTXU8ssTt9P0 z7(v@w+_IolqJcoEN8VrWx^U*oohNU;`~?aYE>g5u&BaTUtff@xUaUt@1gd;yh&f7` zX~aAORo;xCB7{?OhFJSUMqE(}xmaD)NUh2;pJ}OT`m%=%ll>}UY*kUwawAmekWr(E zc`v%CA*rtz`g?G>Z_8q!Pw$fNjXBfFXe`O?K4A~#$&`c=C8nnFQh_#9008Lnn28^R zXybp;PY(F1TmGxacLQukpMwYv!~h4?9t22D83LdI91CSSNnUOPd@d*DcMrFb%2e4@ zFWZEKHQ7~XdsbH)Y;gk}Xzs;7)Uceaw#IvL!e5?R=6s63M3q-z-c`z;%<1H`Q{M|# z4Mp?l>dbk~W^2m6Oc^k|@IbE(8WV8Ej~Wt@#VlcQOIr0r2@@yHmp6aG1{!ayiKd$D zfh-AZJ4ZI9q(mJG%X#WR=|uhdUdO9)mFU#2gV?wU^DPK5*?%UmO1HYI#`KvX(`!}> zThz#N?lIb;o3SA_%%3HzZ+6qoNPFrA_WyM!X?_dd&F2>ht+BaK9($_I6CGsPbKt~I zl4Rgw!$vsjwR^AV8Tj(++n*l*)S6Il{}Yr5U?xbo!w4cpffc)!M8+k}T&TfjT5i2J zed~*Xl$JiUY<=}N+N|ccs1-?)r_PuqTh2m7ODERXK;MCJDdva{gNTHZhLuB`4ln=7 z98UrXCz_UIvNxsx*3f>XGg!HJiP1$LW2{7pfuHj-ei0`ZH+K(DZy!BQIM>Cll~tx$ zn@-*O3>YzP#v+`hSuyLFL?(mDV)B?WW{$a*HbC1&yGI9f1gnTu&BC)9SdA%XV3lY$9Mnj&inRkcVm6>Pe=bo}>^*&$dW?FaN|3N@ zl-sbB+95KFmbSCHKSbdI);Mbq>j>*ilQ-oPsi~Rv!FznaO5_! z0|S7eq3Fvz;kyUFMR8WOBRda`O8_0$5SP<&NMWV%Eqj9`g69kwRDR?w+lmC82=D+C zjNcm?3fsp3$8Tq2ThQLN>APxM8iH+wOjvMHj;-yN9ZODj)}uFC`1M3s2iy72AcJ23 z1I>7E)5wsp`HyH)8tHWY2=3@OlSWgX&WQ8%!R{=KD`;q7)47Gu|C+GzQvZy1-t`L% zO!~;b?q3U5iS^HT+#X}X`gSv~ZT7m~`KEWSbk5CayYa&rGWTH55BBC@A09oxFXrVR z{BnbajT$#;$pC+Mfd4qGihoOHrFqxBq+yX6KFQCYaR;;fKIiHPW9tSG1V*7&f8eNw zPUy_Gv;zp20uWBcv`_j1Acia7a$6F)N|QZI7}9D?p(L3>D2P>?S-qR9&LmR?xNEP5 zC`T-_nKuW$m?y}ee|^?VA5M7 zXBdwf?dou-xw?k*CX9o#iJY0o^bCx<9t{MQ4e}DI+iuUO`0FEy`-XLj)Vr=y+C9>Z z`QTpzt*~G*i@!`?SSk9EPud|fz4_?5pkra0Xfo^4t#(=G|9GsgnHs%FCD5c&7^*}# zhUSM>&p*@N5EGDv=%w{UPIiYOxaO^ba&hqRMx6X6va)1o* z>I(0!mgd(@0o~@`EulRS(tVNTi>+96g^k*+nQx(Y z-_%q*QkOe?zjI&J;z$A_vZs#%3ZNHi#s2+ySxK0OTF2!4)1)B1C6!S*RUB~BtEq-G z!QYC%-sMr`pT)~nL`}4(?mtsdqewI@ai!u($2XeEOfah)EW=pmVw0Os*Z6i_V0Q#{ zS8(@)l_R`d5#@=iM0}+ZDpOIXx)=@lY0O_!0XhrURfM)e^cQEKc(1DTx+-s~_O4o= zyXaTf{BGW#uE*BB7^{M*YM85mRm%~cvpTNoxohBwz#EY-5`Sd9sr04RpTa@lv9)3n&s6Zzg7jcDXd*_-AaO#1}h6u9%`{dOBGqE#A>D1Dzjd> zmsNOQoiAPTwadPBMcVa#G%QDQrI<^b)4YRX+vavKd)RyLyd(Kjrpl8qZ=BUFOE(CO0YjiLRpy$nMaGOFgSxf$SfRp2 z)R=BQ06^Ub(RD|~o*L-M zftu*Kfm&$NfZBN7K^pHmkU{4U6ttcl>Qr6y%b*_mZ%`k*(*n8|cr$oA?6*e-kbo_y;{T@GstQ@E=}p&<(FM z=#JMP^g#a(dZHeKUij<*z0v4FA5=7;FM4C3AO6rlfAscX02(_Oh|d`?2!DKF@b!Di zkQzFgb%p_-G+;RX^uP$zb1)KpI2eU5955Qq954n47~6Vt7*`YU^9LqgJwqm~X_QH; zPS>$BT+x}XHOm}#bgp~Mv%s5O=-n=Iu8aL{i533&Soz6s8CYes)$dx~yAD=#y@TE0 ze=N_&ZCfjwYTKBf?SMYxcEIO&9N>%V8S-U)JzhKC;ChRETi^f7mFtg?5BL##fS+2; z;ph4t^?^T_CI$R?byxnXf5xQqFE9=G59@*du@{((jcQ4R`2h)ArGy0lsn{lUSQy;I zE;onOz%870YgirJ#yPi#HNhQRaA#Np+{Jl!hqb^xTy$?(58TI9_lHfv1Kjpt*bF?x z9S?`i!6V%BXxIWg#$AtxjlmP#^kmo>JOz!X!!F<%XgwQt1DK!y&Db(?;*PP!9HNXhv8W85n?_L z$AM1}-=|3VESvy7N7@(RB#;JKX~T&i9Wv5~(?JH5WDKW)Oeo46&IVaflQo!{2D@-7A(C6}g~C0cFrJEpdqGjW6blc4;&>|& z?gJ(9Q7SwFN)xC|codW+NV)I?C{L&g;W1E=V3opipfWM4gl9ojqE!nof$Aix5ncl| zNmVPn0cw-3PIwd4B}2XN7N}3A2H|bckSvYDyPz>SnuKpbQ)I}ZUY7%>;)!-Tfjsd%@3b|1r*zK zj1z#pVIjaicG@3~00$6oFkB4|Vdijn2OJ^W(eNHPMy})GeQ<)jnY?@bp91+#hY!IS z3S0^+fy@S1j}!h6cY_-c z)ZiaU0z5ED<{xPe`9TptxvP!yP3p<1Z7gXE@*(yY+BaLtp^hDwejF_Kq&JM2; z2fjb?c=;75(?3A}s@QJI=%J^w=$=7%4xk};63|e*)X+%0{Lm=8;?U^!5u>qn3@&VW ztDgGTHg^7vE!I`av-Q_K*8N4A3;g_UY0=`2fB=tHt?uFRu4~igws!662?Qn`I&eC5 z(&^I0up-8>1>PdQV*V0=Qha6FD<@PzEF)N@P+5_xM9YyH=Z|WI8}DHYfbmzc{^5-3 zKa8+1Kyc^ImIn_oPhOC`c|-9P04+!mCp?jGuL$lp%A>PZoInJ?CH$*YfItJlqX{Gc zJd@xCfM*fN0Qh+%2B4~>Eaw)85yO(40z^&ChL#pgM+eEk03|^Jv_wgqq)LT1Y#740 zan_vMY2d{4IG`L@1ZK^d=69&_JGPG zBUB0Yg(@Q}R0Z~dsv-+i4fcboBRfAyLQPNsY6@pS%}^O?4rf9wPz7oUXF;t{6>1F^Ky6SPY6}-a?NA454;Mil zP#5Y5cR`)d0qPF-Lp{(J>In}*z0eQp4G%$m&>!jx4@3Ph0O}7Fa#P6FF<234jKzDLgO$V8V_GV6R;AR2wy{!unL+C-#}Ba8k!2*@16l@) zLCbM3&2a`YTOUB29|`@;sKy_uoSc&4+3p~rJ;>@2xt>518v5`KwDs0 zXe%B8+6K!(+wmyS4p<)AiN}C;!Isc&ybrVowu1KJ1E77dHMAce0v&*Dpo91b=n!lR z9mdB%M_@bXC_Vu?2HQi&@hQ*=*a13;&wx(BQP61=g3iFv&{-6Q&cU_Nd9;8oz;)0? zw1h6f_0VOsg08>~&{edCuECAab+m!<;3nt>+Cn$sX6P2$LAT*n=ngtTci}eZ9y&w! z;dbZ&xqf@cIR81>;0p2p0{}Ui8k0 z_J8#Lhz^{C=-m+=LLZFiFzPj;BUeAZ=;%3yo*$y)=;a|garNqpPX4DB-FVSyr@i8= zbGkY2ypLRV*%NyQkFaMD-90}K_dW20M;>{~vpgTYh6at^XwmAA4!xh21rP5$BKA`s zaNy7nCr*7CFfd~cah?m4SdQkfWoOaa<2)Y@@fXpD$-JkQms{}&_SgtZMPN=?>LH7!|Hquu&~xH9w!M12u`7* zI*X3(%(8J_4PU<2(b3V;GcbyiB1WnVI&In{*l3IOw(8NT*MKIw?9%PFdp{eVOZ-9& zOO}>HK&WNSS``$O)f_om1p^}q4vvTm7paJdDv^uaRDBeLR`HwGaPiWDd3WpUm@mf%h318hq%; zFyMnnh6x`sG75O_kx|Bbj*RN{9z-o_=@qSLSGQlm0pS0Q0wMgnQJ~V^Zwl6G9St3g zj~ECu0kh-3 zmGMEd)4%^FeBgj^asasp2C)j`l25?B4*=!kiV_h85Cbl!A_Nl$h0@!C`J3a{Z%O0XMDe`2K5ZMh#ipFJppDB8*c3RlReUI3m~C5{ zQs%#(iAwLaQS!d4FnUA*6StXO;g%+kx{*_d(K)}F$+~e)psFg|E%4Axs?UV9mHDQ`aHANW+1eG&Gqc-+SD8T{1PWX1y*%l~_Qkn6TaG91(B% zv(zFs9bVYGH8VmdKLZ%!#HTP?xfU@L2{R7;jA3ytkjdY^B*N@{5(U6)>t{Xl_` zY20e|wza4C1P8fjQP;UhOLcn|5j)}$)UeT7coF*?ie%Xop@&oBOBc^l#P&pMcu&ji zB6F5Y1XixO1_hX1Ewk+TYLQ87r`8U1O%HcX?(gN;@#2TeGqa~lb1}D1pXarW=vv8$ zDP0y7Ys2q&E@g06s~kricsRVvIsLRv*(X(=XQ#8{XZIpuo!oFf3j?pL%6_~dcL-CM zdPU^bieH$H=MXe~50dOZPF8VlAF15+3v0>Q4K)EbjaxoU+s zn`;zT^2&&Mb%%E9NooQn6jO z0v>5WzpAVbI`EYtgG1a502KhUW7mo#w}%r9*XD|-qP$YPkH1BLoZ{LXIwMN-5z%-- zWDrqJHDD_UP`CnN2TJ_bI2Ld-<{aV&Za`3mtT9Ir7&@gc(OPmGQG!L37x8P#9#{@X z4H`1I1d(XyuLJ{APp26wKmu# z@GwL4VGIx>=7f(wJIP1ng;s4ppMVcgtU>c_X+`%95SPTDlnK7iW>A2(4tJ?;!k2Py zr-uyJGC1f;O5_>}W1s>qGRA>n0uVzIKCbRRr!Fb002^)r{xcW_j|kWyiZFx_*hE$GBl1bvoltXuJSkgqTr21&B~rakvDeQu*`r_oBhLTVHqtVHb?EW%v(^4!3nIE?1CgW)_Z2Hp{@x0n=2 zdGTg0EX=!08QmzzBTE}jTFVI8SdXJpJVR>E_#h=IV5I|Wmj3(-0MoHDWbf$&2+>NL>se%B*2#>jBur>6I38o3j& z%XqA&rv|d+Ox|D*sK8;T+I2d3)*>5iX!Ck|@2T1&x&2TiRA-;3N#-DD7iCGybU{s$ zLycW7cEApbf+RY_zuP+%I2g+^gbv+_Iyg~CctL61FKp-;#>jiT-lQ!!66t!XaQ$cK zAw(9 zn;+`=aPqIzi4}TeHCHxoM>#R18JqhESxRjtH%`KkE2EmaeI5UahT0gK_SSe9JxtE1 z_zypL5ejIf0*+x08g|-G^x>J{FddVK%vFnxbjBPFJ98* z1#ZAo3`h0Kr@(b+r%?2qq(cSXweM&~1;+G*>8}1cQbu~PGM{Ki;&gWP&LzZX^6(Iie3vTw*7e+0u;%Vn z94MfKztyLJpq&o6$~dtnjp+%2^Lx(U^S19%hVV<74tog?x&jt^8>#Bt!otJ{BjMcnhT1*^P)UjmavO6Ff z)1*eg=ek$`O(ejm&(=uOcdx_XSmh&ujpraL)O5f>vNwWsR1ljR_bt0-rYZ%jNWtX} zAgxo*H?xGMd6Jv0o`2+_(nd5#2?XrHs7h+3E<+>lYL+D@bh%#HYhq=$oGb=?AoOBt z^Az31gGiBzbZAZ=t|x;&(w#loWZt8+d}NTU_?W|VxPK!*NpPd?3PzC2xV^L|UwLIj z^&%KrXzLpT;_{0iY0J;$MOsXIBi%1QJze0@v*+haiZT1Gc&wQ}fNEWOe1w%=Rzw)n zbs0-=iVl6I&g+)_p878_;ysNcu}$6q77gpos%aK*U-&BrPh8a3o59so&-Xs)o&TKc z=;3RDzVA=ZE=YiYur>w&3c*>LYkH6QN=$=egOijkiTeu03>-NS+Hn(st4z}0=MVN! z(cNFH^I)duw?ur9AUOa32zLvwQoV6S8AwmTXaq*5W%saFERbLHVFdtKUT-ui5G%}M zh1c@9(G0tiJ2KYEi7)oG)~oZuPv)az*F@|6@ujU7+=|l*FCW6WdSR(BM{1wr4^CPM zCe(?wNIbd$2#g?ovemAx6KZ7*6-2+)!}@%KJ_uq+IS5|%T{v)L2TtNo)VK)XIYKcK z&q1P~t9P~-My}FhBqcdbOlKKcjGg4nQCYK7Ex~P5Qs-qU>{X2DW`;DGS)9uGPhD{G zcV7RKKI|^EEZrKoaw^<)&xAUn{f9`u_qMtlP(Y&Sm|%YavdDw)=u>H6gbs~9b`S62GP2UmDj*!l5AocciHQQF!{-g=NG+f4 zfVeXy*S5<7874iSY)qkvsc0OlqgeI-4@hy;4ErAnvv4*FXd}P~!?2pL(l(jP|Grm( z^TS}di9l{P%czI5?qfb?W8L~J=*XQ7d_F>m1%Fb4bR%&`kAxOVY(0utX1RFi)|J&Y zG=B77Aaaw4>e6%G-_97A6w**??t7n!rW><2AWv*8iQ(+PPd;5|dP3j30QVb?8EL>m1$2PMh5XUj`+(sEYMMIKK_7sMTklPkh zin9zgPpqsGhlCe8yx5frnA8C6bZ>P$b3Nxmm))@o0W z*hSr5!Y(eUg69Om-eZS7W;BilipQ1oW;>P-T;F|)B)jewz-Vd4v=>cUaFBCN6}0HB zsuu{NFco*k)^wng?ls37Q1&%Bbm4XmXq4goOIGOMpnW5+**|{pQinySZio;!mN-LM zdT|#FW9}wBH`RP!EfocC0++#AsB|Iqk5g@U7!)$!jVa=flX!;0PhVt6KPK)a0aLMy z#Og@hgX>)6h||;=w;~{Em0!d(kDmTi|vovG_CwkVQhjF1;kRo)IKr+;{9xpuddArW!5?UgRMpV-f zWp!x}`R+3iLy1wbtn86kn{)mT8sE)4L)F&rZuYL;<#`GcWY@`8+E{n!mh0@ketO9; zg2&*TxWrrMC|fF;NAlMw&ZIg=M%q4bqY2(|MszicF~H+HEBI+iSC5&vz!?QLpS%1y zDasrQOYWW5HZDJNvPa||)pKWtC4RxNyH24}<*;GH6nCJ~fVIHGf&+DdBwddi{ac(X z0*;QY3%sBfZ?;caGaPQ~8WsK$OWMIws@G@CdGXb?e@)3jTMgZPJAJGV%f!O~x9qrF zw$eI(Sr-~`Ii>5Azq)pUgPrpvb$Dv_oLz7ZqmhX^ONxXS@2CGDcBm^-@tyVzR!MA$-_y~nMk zp|TgcW`O|~SV30A1w6z7HtgLAa{KQgtej!(hlG(d@80qwR--09wxUNx-ukJ#JtMp#VDNqPGlk*sk|ns z8Lm#m2@0a@$()m|vX4|(Hu1qKZi|J-l}W`&E>)4zC;JowE3U3BNLRT$Nq(ugT^Nd) zsFHIZ*!r;Uq&D$YD-1y(x{)d9J!wr?&^)(r%Ng@BNKB@*dqgP^?%>iFVCFh?z%)9?PIWUukA5y_Za6Ly8^?KSU9s#F&h-{jc+OV&}eP& z7ThOi<1ux0G=%PmIjbCY*v~kv_Cv2BgwH)IH-=M;)bw_ZYmT4Idb9z z$a`(k0SnEQxK8Bv_LNRUT$|h^dS1-7PE?vvi4en# z1JN_PiF_L)~@nkqx_-0CY2G-ubz9QzjT%#LBEg)-&3vvd&7DUvbZ0cx5NfGwyY zeV2X23&ooGdJ^nErE{K7@P>BeCOW2Dp@!nnP1oCo6DK+kC+##+dkrKOkJr=FQ@mtq z`|*X>1ZytDEkh!ZW!p&2T#=ri4R+M^$=n1hQ@9bO=c-R?t1(`1l=VVbs%D=CkMHuQIALAdx}KS^Jk9sw2fE2G}ViKA8 zbPLTlM)Fis=*L5|P4-v^dAloiZ*b05P=j31{7rU=B zi5eCDuzT8i5qZBW*opm+I_a&LD`Zb0H~E3F8Fij-QPfVx${Z{U z_MtaCrpswNM~64fArcSk51ZFwN3iHHSUf9aAqrqr*&)M`_*RD%<7+r7+QMb_$5&WZ zo)&O*0j>j->Ux=@M(P@#c`|*8LmeHmVng{80oPPX6J|Rz`|CRk%3`n#lhFKLb_$Z3 zck=rnhf4_QqtJ?+54x_WST5Q|QD0tN&zQxofw@YI)TkEfXce(w%vNeP+Ndg}RgwUt zO5-b&Ep1*c_s(7`MD|b$%hHo@avuG~n{FspJKoA4$u#yB%pT?Ca|Tn1rdg$-jQ(_i z_2y8fO`&9HQ;|Hql0}-Ug(i&DRrd+tKaypMF;+9a>;RuoI|k7crq4+AtU5>w&A4S8 zY8+t`(5jIA;=ORh9Hx;?BRj1V+vQOY{2<7S9ekPTSi#S5u>Vx>n(I$Q?33|pSAzzm zu$vVftmXFPrc4`__bs$xq|A!9YX(6)4tzsk=7Mx3l6JrrCsk-H&UcNWd!uL@8D=2c zQXaT@zn$H8K=4|Ej3cPqIqqCoQMZRi@*a$<1iD8z)HY(S;LSHsc28McNpBmOO(FDe zllD*5*vMFmADXoI7P%H?9%jS~-~09>ydIk)HQjfhkAROqLf+8p>ID=A?K^cHhdTpz zs5?=0p2_ylZKt4h(Itu#${3es4`meEiXLF8QEoxv;tP@po{B}YUM361X@L4Hh9g~5 zQh_vy{DTy3QfU%@!`8EXy&ky{ZkK}Z4GXOH6sdFr%+L)@H_0;0bB4}&n*vRsx%;Rl z?q~$>o<9lw`|_)L_ingGwu{L|u6mF3_zGh@ldk%&=PI{vZ%%3n` zh3_IRpE9-0*ow`OigBP3p4WA zXq`vuDnsEnlsM0J+mL_-;x}kA|WvAdU ziI7a0$#m-ICnV&Ze_?H(mS8=p59kRE?-{*CqzUoPrcc1EOQ|O`@+QqHg;5PrWR5x> zn*fU%KwE%PzVfuj5v^=BZSv7BYhT||fTSMin&bU|b;CO4ATIDV;$kc^w4{%FU{pg+ z99H*L;T6~E@IWT5x$G(HJTZ9xsPCcnVIF*zkz7-5YNTcuWd|uyP#oO?TFh>ZL7^}e z@2;I0wlN8otKK>&i)AZzGoytD0Z(GtQq^p9anri`h*WfoW9>O%2(SDFz)LnA=|F+4 zANIr7d5QAXukou~Tf(Dij_TR3m1`Pt{4ZE({LUOOylY0! z4tug?|9uels+ezd5U-F11~H9*4GtU@VnSCQ)4zSx)eKF1X?y`+2EI^!@W_w#WnzLQCAq|MF-3FGzUp7SCh{^LtKZ;_cq7`f|^& zzu5KXUw`?lza1BfiXC@edQS`fHm}vw{}9#rR)v5#n9>xsmOJ9cN;pTbz&gIfk@|3U z7cFa!FBG>Hy}M2plV4o2Ko{>z8VUF;SI}PxhaN_d%4oh6LUL}Hyt#exiQQ?!UX^;7 z|FoL4IepIg`?41y0SELH?$?qRH|rD`(>;rx7K@}8z_Mny6yfN(Pio~YZG%^}ntDCW zojvDV_`N2eSJT_cuH4N$>+i%GGkS{6PQMF^`u6s`PbrDL|(izmwS``q#xx`f|t<8 zpmVZ&MS0xTXJX+VZo0Q>*y638Y!dB$cQEp0Cz9GR41W<1G#J>n|icg;7@`v)-)=EIt!Z;Gr3}o|7V_$ZnWLbTnnRzW{c#6vkN@A%`fP0) zZHJzgJ>!NkDBKQRMjVyMrYRh?4q<20m`$o6gcH{o)AP!*UP>-UtNqcMT|dqyF$s=s($Q2LBvx@22fp*>@ zy!ic!vO^$Ok9RQ$voXYs6tMFW3a3e>qd@hPzOX4gGZICw_DY*qJ6wk6 z>rf>s>{iCnxy3?%9!BhHHAtTwNce8v9J!;KS+MZNA#7mH*^x=YLELOq13N1v9vvT#HaoPEj z$qrMK)q8q6yZ2P>>JIe?pRzE^sM#8ZHMFBj&TsGgu}lT3N(eezdb-k#y2l`gzZSDC z)&6LX<)JH;e7~;dNDg`@EZ>Ol!u-cIM_Es@#_!WINyG7PRl?tndQ8@A?iQHY47<>K zn_5}xZ`ncq`I=_zaKmYZc?84Xps;DiTd74P|t7BFK9A*)ZL2SqSk#;0Co-kj_gboo6J{*-A@ zPEvqKhI_cxe1x}Jp&~r~=N<2*p$@{M-C3*UU=GC>D9dp^e5IP;l%T5ST z4aRI0%`85EK=0v6qT5%=O}4CS{<6`?%wLFTXEvUjvVM9mT#>@37j|)Hl)Fez0B&zS zGv+S4J80rAzj-Szocg9RSTFglcp@jCa%%k&IrwQ8Iz_C`wyTAaeY4B9Wg(|B8!MBy z!@UnH!qzD)p-K#&SZ3STTz6ZU*A8D^fs74L@e(7zgNz~&(zlf{dQFWw1>FjgwB+dS zhWSOcU*WM2_m}f{4XGaXikz>I85)*Tb?1uQ67$Puu_i? z?@eJHR)L30_qiSp5PS3SG1EwjS!`A)SYN$Al8Y}9`c#df?NMt-piHVtSv&hnjFv^Q^kju-FT8&^9ac=ufD6KbsF z->Q&)T7(*`^igoFZz4l38XDj1|EGkak$yf$NF`fO%pZZr-C%^I(~@_1=m?a@_q0vQ(w7!E_vgfwaog-!_L+%Uvq$h(D(mzNyyM~4ZxU-Kp@w(lZv~*a4I}w<#Jf34t)@{~d&;8MV4hS2~d$Nl> zE{O<5#4cQu12TA=*?Hoic5b>gh3KV_B$yZ|A59;&`&E9uXB-5>z5+x$I~b5}Pp(?v z^c%w3b%oS8&y=&kUF_KwGb`)Sn0OfduYh1y0`Lvy#+LTxy6Wa9$8wh^?8)T(FtQ^r zv#Yn=4k8-OTkN42;fIbDFk1DSt^x+y2D2FnMM=K4uY~Q)0>FW1YPZyA6s2112${pW zwS|7YLTj4^v078*m;5~rR zU_P9-!r5$5wIua})0D(e!gnP|aQ?gqIu2%a0XOCD`B2QQP!Dl!vdoUx} z5?d4W&T}T~P@CIoXh}4Tgtn{ndoUTU@h&+y6J^$shp^(|VBB(E<-+Gm;&YpU&V5TP z?My^TzzxU0=5w1ps~o|6fyW^bOeiAEdZZWMd@lC-Mw4SHrNB)n>~nUVTV4tvD7n_q zj2^4R_uzgn-ru+{;a}-$rO|c5lsV;f24465X2V`x#G5nDiIX_HA^l9pHG|?w z?{C1*qDtsq*C|>;1vEQ)iVB{>{*+t>7EF6m?P|To&sX3iw)U&SVh@x^lPwk`;q*EwE}7c3ChD zw?&x|f7!MHo#rqI>bk2H(5=RbQ%OmiQviXwn^yaYI1b81cDKhX672!hS9zQL(B3j#*QO0qJb?6MMVMi9_Fr)vKi zvgEb?aN%x-Zt?A{RW6Hx6gGGuh&O9g?jKgMsX2{7c>yLN4YgnNXPJ+E)P z_W$0yzFbxzB+7T>*bU6{^){Ri~}!_L+h9tHO#-==ov^xKegiWoewO zaA)K4g|6m9E*jodV1lpu^J%Q=eB7%9=*rT9plt!3&c?kz`f3Hu`__w&!aprxF77qM z*F}EXqTRq$B?|3>tX#f#i}zQFs>nRuH( zYU5S>1m3Q4&0Qzf7hZz~!^gYLVfN5DuX}^`(4hZc*X&^w@61HSWgwy-)811S#P{vt zr%*Feizn-?sY|(Fv&YrCNE#c4M|%34A#F_I8pNmWe$?Z6FR{DXVwL)N&L}WfCzG5e zZbWReEf4TOl`3wVCom*+E?nMJTif#dj^avtiN895?I}nO^)}~&@-HD*-PQ1<%He=+25Txp*Jyy@HM z33p+`SdcJA8L|WtTo~l9l_7~Q^y>MoC!QZ7qc4s zX^UWey38$(9^-v2X8E2mDK7V^u3n^BUD#29Y>^?4U-=HFQMeZ%PF=Ij92h@P;T~rbdhHD!fTRtD`2~039W$-6a{)RwrrpH zf14h414)BfgBzch8u2E=p5CSY#tF(!ulxBJ=>+6axhBBxaIt`g3Q31JejeN6D*YX*QRd zk&*7n{j6DLRyw$(-7=vs+c!JSd_b@+?ggBP*fe*?1i`apT~8>QQoXyWSJSu^iAj?H z67QwTzytO$OrmgUJU5q0pm7a#q^Ikupn@Y95YWCF0UJs^Qo36;EGZ1154AS5&$$v! z)P_9-moWul9T-_;bqiSh!FO!jg-0hRba8cjSEF{2i%3ml`IYb8X9 zy>npb5IWvp6L-#d3MYc?MRd*>bHkO(F& zNP$gmtA)7GhIp#Bb*v?`ST7?ny#u;c~;St%Q{#U!MIz^{eAMrpN5)) zM(ykQqH{J9=t?Cl%R&#Cgf@#B*7Mi!t(`Wjpc)@0O_+WbA|J1OVIo%c;*a*k_efkk zi*d}yFu53>&x&RN^{K&hd2y~hV+%DIw9M%W>^nJl5bHt^u)-@9b#{?$pVPh8Wk+2D zn-2Zd>@OKQR6V_woE9(vvg|aWlC3}1XbO8SEm>{8OFkRLfFllM$BxC%^VT<8q&Z7bA80Wa68#_ z$rmi@pWnaxk3v7yQZ-9uq{VuFtlFP_OWjw9Z=D)zfs+u*eQ-nLHfQ`Vw;%n+7K^d4 z0BbiYA)&C1>sT|>ilD5w#qenremwmm#~$lf1Oh($4%=&tVC!t|j_+#K4la%1dsf`* zqpAla#J;oR6b~_WIQf!A_mOn@tVrRtKv`Hbh4Y?JF-1_?AZuChPiR`IP1=I4nK`gm z8xkzEaNB?Dm2GMj^b`|3teG9s`W8WjWT~#yv$r`OKnvwlJ)Y7iv63%9@HD}*!@Z^d1=ugi%74{SdWi>bxnXZ}(F#6krD|~(NpiUVckSArM+LC@4L@kq=bp@( zx0C2g1?NKyUEGQz?Dvu2w`a=}NRK5W6wuj84#uskv!IT5_pJL@CdLDte*^>uOtjIug`> zh$r7NmEWRWlz9bkszPq7c4QF2ge%@IcV}}#s$m$jB3X(d;rky2Zo;;-@|FKa#59Gq z(`fF)+>sC}^RmmnmbOb^YlqyB!LpIn?Fz7RfTgXwEFo)r?Y&!#}B^=5{iZ5k6T{*PK*2mu66aJ>_MW@E<4Ng=uc?+joL}Qz1R)K)8%7T z|3D!;#)%auu|XBiFL$pwAD$CDGP+wzR=7v9HIZ=!UdW2U&Ni_nIWpAQ=3TR14#b&P zufR!(R%3upTK@U7hifo5I%AyUflXq@lzw7GNz6eO@n+yCcn2pGcD67c12NHOng^UMNFr+b1+mgxUxflJoAHQ9aU}#i2 zlI}7jo-y8E+fd$8`PNr*0_FeKe;@^n3QRW9iyk-(o#eVha%p6X)B=2hLo>{*Kr|bs zHy11xG9;TasTO;mpmsY|$(g%q9m*YSi|-a?t|NP z2`mlfHwoAXAM+nmNWx++7iFngN#d$zQXxsHijWKVD#&mSk&*M|Mt83OpkXXeYiP5_ zgDYFqaf&ec*Cf482KSq2k6@ozZsxO5K1w)-k%mNE&OuIOyUoyVcP8WWdUtqVne91e zMZ0_PTe0Y)k<%mI-%s&q!xa#QNhz9g$=r)XrEWV%{K$%TOUO4jQZcU7+F>>HBN_pQGKK6bk)(x-R$TG?=n0qF^=`NC`jxIZ- zj=1v{64?TEyTkH(zwqIoxcrI&IU;)UTXgEO8t7S;hR6qh!bmJ?a%SgahVU&?XloFRu$|vjttHn z8$Xc*c6+5GDhe2;t7_isUmR60gT$W#5rhit;Za%EfyTKJoD&M%yEPzuA?+Q=l8E!V|$00)!*4_3wPGyoGZU+6%rHcBs}0wedL<=N0T@Hbf-3b-AQW0I&rAeVR8r} zwXSJP`ghFd1Lm<~pBD;20bKW-N^+%X^~+C*L8b_m>iO-cD=APo6N-KN^2J=8z^jnQ zblN9^aTndww-M~-!(hO4RTVqzeFLB`qD|p{uvrdLBSsIpmh%wmYchVH(Joz}-Wzji z6XL@HjuD?Z%4V_F+Eoyl)yr#(OK>$!zxQS2T`{Mc`fYa&;$L?JbWY=4zTHrXt0wLr zi(MJa8WVp2>>Am>xXK$A0nBOa^!C{$HI$RN1tmeROEi|Qatr<7(zM=KBc{M!Bik}8 zF0bct@W0t^Apma1Rn-)JWl9T_vrkv?-c+7vs+`8}R5n9FWI6Z~7H05bUBNU?Jp2== zTU`0F$jdWemnA?Zi!561tC1K&_sJ2Zg&tW9oPeV_ZMlqdOI=)$e75J)*#+12JNNFQ zOguPi6Ysf&CKOTXf!@#5JLiOOEs(SbsHXiVJdkE7X;Hz?F)DT4`cg7%N#fZqC1-Z(VRz(Fx#fhJ z`kEi+%)c*!>(dG;%4^*Eek{*K{fpeg&E%oCW6KNfh&bgwG{4|uS)^6BCQwqc0#!#(@0v<=0|f}I{ceIOx~ zU3K&uwKF(5nNNLL;9Vk-gQlO%s)+39A9t6Tlj(y zw_UB(c?|jpA{j8LX`WqEN6!>ky6Aqjj@#u7x68m=I50|AI1H6GnStcj)yTx9qW`c> z5|36Fr*=sdavuIS;fF`i;fT`@2^M9Xw!y)z(}JW=@;a0gad%x(}*sWj?3yxq@Ht z+Nb-MsIbUwnA7F5Yh03+hcO}+7gF+@HQk`k>rl^%H#>=*D7ydIw@Bvm<#27N>j zsJlPU$E!_pG)_%!?(!<0o(R4RBfY37aH5vZ0X^#OFkgD|nn$8`#o~6WJ?)X%j9`Dj zKjs;;Rf65)7loVAjdsuOQ11Trbl^YWJHM@FW`?YKd07*&N)ViZC40Z!%Ifr?1!eEU zz55~J*rR<15m>YjbsRdq6TkGK)4OBy!QZeUZ{bwC;JBuJsoovyS}?s|f$H{Udf2Xv zxGeLS_vlmYNzFexy|9I#2aQCV7_b1wT)uYZ^@M~KLTe=;GiNLe!{+Na{OF-o*#nR{+vCB-ws0jXWx z^dcRy&Q|Y=FjY+zx?Bu0fk+ACI08}Omk0ZX5w!KPjrV?Y{Pcta8j?Dp+n3=9Y!2nO ztDziu!7jqCvkIEbis=L@H;h2bvDO8ti;JI$yKmS0RLFsz2I#Jx(a=i^Nw2z$)OS`m z?HRN(+~kI-Fem<8F1|8|>m?80JB!Uzedapg#nA^emoXhcX}2uG0SX(U$JmRj?t?ZX zdy(00w*idFQMQe!f)Ao_TlLvz#@zZ7yhRa^^k!}j)(Ztih9zDbr2h&psdsQOi8(=G zJj}O$%f2n(n`gq439pja#P&w9$t&Y|Qemf77Vubi2|^9BL_nd?Wo24TFlIf+=?_Ly z=C0W;8seGr-to1GH%>+|{;JPrZy5J$@}W5?zb7L-vn~i-;D0zRZ`IOR?lyVNu*bRg zS-nh=Y{>l&H(=NHHqAArY<+NL*7Y^bnSi~o`+dSAMCvGc@_#tyfcvwV%x}9kMH>lU z@~5oF&H--OqJf8cjWrfIUoVNsxEqIxcu2S<;l?71@9HW{VYSmfhGFm#Ru$VQq$LKf z1eF_={13DA?1-8#Sfl?2%EL5NCX%2LGFf^D>)D<8oM4^MM@j(fwef7@cozyoA z3wWDkZtu~Lt2b}yH)uBI-pFMg2fx6|ax0a*Ek4j94Rcjqy%n*VB~U|`$g9nj!>-EL zuOIhNb%#;`*T|F+Y4KsEz z#3*!-AMjv(9V=Sd8LiOrV%Na~lR}wM)*J3FtSF3X6BdO_!4Js)$8VOe@K}D59n@p? zEiCVJ@6#D20jAt*Ml8dF5NgXBG`+4t&3!2))4H~fhfi`|S$%TFJ@R6!jklf1KHYt~ z;s@GtfhA2`E#*o}g2OupBJn}_AIwXsHGKg$cbP1|--NY{%o+7_SH$G@8TRv&g6dWA zacBmzrelgV`Zz~R@`->jdX7rmOQH^E<2Q_Sm#lZgd;k4A(X@^V-F=P56ZDi2CZDmV9Ac<0EPN%BhS*Ap-_0m)7l4 zwB%9ycfW#-ZgnX=Rd1ce|B9F*LL6iMak{^|Pd< zwwR-(DyylRTN04(+#88^!{7FT1SFmgc)8mZt4F+Ud)&9jJe(bhRUaxUzIzn#TOdLseP2{}p-dGI3XPzDE(KB9Bymugel}#<}E9Y$3 zTi8^_?}{uPFqfp^$E^eAJsewNFDEV42O3=&6f!2Uk-S~i1!1e=yr06uYE;~x=WbGk z=syN}5~*k{4nm=7Q^h5Rr@s30JJ0vi-pHnX&3Z-kk_;NOTXGk2c&|*Ir}7(M$Yv7z zt=W*P`n`o2D!ZbYkZWwpl=Y1<)RI!k4@pqWEK}uF6UCLQUy-;2?osWbw58K}$e5@m zYT0RaaG%Y$%)ZBCKxdTtSTeu8GK~zt8uEI>^_oW$48{aq8k^SOYDH(zc&oS?uhyGv zb zAz3*hQ|blr@4$mcBod2E)vBB*sw!^QwpffV4~oCz$5Gt3*}5L9Z>fEc^MJOpuw{N5 z3gB7=8HomuS2ra1WAj|u8P}!ZI_^$i4@kIluKX!deMCdrd1mR4TM|Cq91}FY3BNJi zfuL}HpA?&j-Q{n>ky%uZio>u{Voh9=|vLPi^05U zTmkt%85n#-B;7Z-DuK!n1BM-a6U8g6BV1u%XVgL|%#7qXwcIdI2o<ug7LJVHF1zK`e~umK zYZ!2R4!kQFM|};`i#i%lPN-y$PN9fjxN-BrFCQs&-^wbO>g&{tZqg}~7=`%_qv9#c z;sRf;8u)Q%9XU5Md8c=0{5EhR$oA~7yoLblQzU%Cd4VIsq+EZRB`diuNUu@&!a|wG zF>i5D2y6=Y9=A!aiN<9rquXWCsiV!ZM``0qPeC}_y3?+{?_M?eCwM_-%|A4R}N*s{0ENC93sTnfn* z;H3pR`1SzpyYw6INFFY;guzLD?L@q@EeAcEmt|d{+hDWLXEJ$<+2r?`PN?8YS<47; z-Cz$d+QWcYe`@j6-_<7A-HQin`|Li*Rxfy9 z`+((#3xGpk=L)tTh#Sy$r?ViqFH9tsHP)c@uB!T4>7?nnAd2{8;Fw)zGg=)tK)oB{ zI5)=Xkm)sBte=7EpCLL|Av_%jPrK|H*$Ybga@pRWjkVjq_ zYK?3e?{K6z%QiEKsssagj1t%D_8PF{pI>DE2gz_?d%h5eKX^iRBHFL(POzzxv|^$& zCh?vipQn5Y&+G{~xi40AxG!TEoYdCX*FqI=3)FZ(%s8;Y*)yX;a866#-wKt(tyZ)X z9>?3PQ~mS<5y%=?;qDeCc|W+$lP84S10zu^4u62nyV2_^LiJk6`N5hkPLT;OEcJ?C ze&VTNG2dsfy}O>TatlpHsPIz;+8W@9hL1W_46uY#33J~+pRO}G=Yj6~h;F_)XoRIX zzqOO5(Iy^VqT2RMwe=Z@|BPZ|I+lP-b=GW!+}E0Qung z-^ot-BtPHt7RdcH&F8xF+&MMMXU|jFoUP>Q!;$k^QUFG}FQFDZXzT@fO}+O!(Os9o zHg4PD$oi&3C}4L!ShpfV`#_@0^ZErxsy?*(UvE+A>3qqV4|gjMb@CE?LL!-HF}ROQ zJc3&AK)D1MaQ-FtJJIovfJJ>jMUmZxE_vopPPfyoU-8CLap zFsQmK(9k*QIX(fD(`Me0Q955FsQDATW@kp(0?XR|n4$^k z-@#frdgy~_UoO+jg;35Ts2qLqzQI#U0w;@iQx>>DC>aD2bXGy%pg<1Oh%m@;1 zaigaGUh|xG{@co?eug&8^ouCYLPn)i_%Ipib|pWJL*7APxmANSOqGQpaTu9GEgE&x z24VqjWY&}RB2?Mux`Ax{$h(n@pdzih2=tUOa=7=tOf?Zd#MaJ!^+Ot(S_9T6^Q z-q$Ji8Sf?-pXKtN?G8J^4SUw`eVlw>;@xE1Ij-%TS-1esM3W~suZbkA_x3p8?Q~y{ z_tinMXj{H+HJEvdL=+VW`1&brZ?AaYCNV6##+!aRe5m|Ds6)Z)-+RxD#LBE{HPk}a zRzG<$c>NXL&d)zz`0izi5q*4xNYpPfT3lUBbLHgtxgI*_g#5H=(Z=SNf){7_qBtTa zW@LU;Dn=$5G5cB&X*=b_Hz*HN_79VC_ILsVrb7*NTwH(t!S(C?B+;pDpyyDY-q77F zcX6mcQ3>lkf!Kd>2meubc2df3-;Y zfj9S${UmfFzvmxNC=0)0y=LbR)%AV4hCbu&Fx-IFm4iRd1V}~ypml-ESk7VgF$n+q z%xF&Dni?VHyndxZaXDBjL{Ki6rtw~Oqkip0$5ZRCg<|&wE5go%VLD@0TjGS1o_^j? zna@H19Ot8ct6FnkC{8vR#`79dw8E;yjHP@!R-2Nj{J1I@g#IrOWgMB9}Cy71C)xHxLN zH_5Xi`~GMcu0xB`rr;6q`~+HBOZ*&PtEnY@1|DKe{n^B~szx1&&pKfjkkvL1cnt?2 zh{YsJhcpTmj984aOi;6ka+{2b#X=gTh=z(qBJiWn|Mj!#A4~POD8QPmRyY?Ci>2fv z7C#OkEP+rc)HKIj$~|M?FPIZ)co&*YqAqA6-|d$pt!d;d>XuT>#((L24u|=0(t|*{ z%%cLU6xo9hqSqfSLWP3BDqu~3gD2?E@8ARMwUzz$bsCfTK22k+votMtAG$EU$w~K$ z2Tv%~2W^0`6<05Hj#FsUbmCE;@gT7cu`64mauxmJ+1G>L;l&PQwPOfF_@9T~X9kzC zet0%yet7InmemqvCQpE$;2;W<{rn%670P-#e>>Gj$7UX_v-C|6ef$dC)7O|HCD}== z|I?wLy2sh++u6=%_}U}j+ydbk$!Tf4Ge)KNR{usXx^epCmt%s$bL)5vQ8kaFewZF= zhcSyh5tIW5^+je@`{>}x=y#(Rc!f=&1K^}4|KbI1tM*ZF)20TkB~=k> z>uX6jz_F60qz}Vuit;N%7!swveomv(834qF0J9)UlWSHfDBJ0lkNOKC6*s?gkBM-* zkvv8Aq_1R1WP$)tHjsX_$bZo<{ey7QqU&3BQ$jST0aLfd6biK`=8hudZ;n$YUkiY? zfggjRkiI1)S8>X}QeIdjavr2diN*Wb#HUavDx;c!TSE{ZhV1HWOr@mm#1s+dT3SEw zFUXs$SweWwM41FZC&o&;SSAR9nr$qJ^79jGX$ht=fTEBtm5|Ggk8<%-q8|{&IJKKY zC$`O*^fUoRc=e`Tsswz?=qmo}dQh9IPBU;QNqMMmmUhc=Pt}$!n>t=msqA2EMLy{52JP z`5&G0!>*@V0{7dlP~zs%uSCuYhZ0%qP>a?OtB82CmOuk@?dkU-Z2G*j2PIoq=bx5_ z_Znkrn!(zJJp4Fp32tmxm5-(CYi8Zv|8WnuV4-{SF3 zb8F=SzESd781FQZQLGek2gIL&=h}rL6;$wyh$@utKkI%yg7<2zi%k)};d2G(8$uNh z2-2mJ3YEd_gzef?Qhpz^kd6q1?QHg1sze}M1jZ1lxd2@L);hXQgP0I?E~Zj8-cM_F zDw%qWUd43ExqmasXD`$5cZ>u@2*UWqWoyVmCfE#Xa&fhsx`J-`n19Oa<&XK=(hs85 z_4JkWF7;2U{MjxN$xHpvYfdSjzE6KYw-yG%6!y~qYG6xPE%jUro$)jt%Nq>{_;RmY zFL{J+d8af?>S?Is1+rX;BBB5#4MLXd1yWC3TO5KlEN>Xz+O^584;2y-Or_+eiJiT;b-W1?1^d)Q-M%PL-c@O{Y`amM@Pgng8Wn2Lv_Y z88sDxyS{l!2SE+|SuSC@=dVyHPSV7qa@zWqE1bFJpv!L8rW5iP*dopO=`tob(=N-p z5M|Pn{clvaHL*yKVAOBCW(|`U^3H^FUZ{&vP^lBk!PODADqd zJ(uzhhR?We=*M!3^)+Gwek@ebI8j9g?(NL!b$+NEZV5Y-2sa=X{>6}?LjGEc#|2Q` zz`UuX)bX>!^gnuUbA;Rg4YHtLCqgxCyB9o?#)Y7LwW|;(OLJ(gYMhq>l-j zZo+?td&HF5W8{R=+KCNi4utEV%xVANDEOE#yLdGiCaiwa3ZS_4*@gm{j1fE)We}r@ zE`%CU_QZ2N&5LIdrS$N5Ns{cy9JouTK#DOU-ysxx6l$}C?+{763S|?REpyv3s1MzU z+^-LYjV_s#kILrXnJcwwm1vBvAuSCfuKq`%6aG0C%aJR-^<&-K|TA4b^ zWkGxB()a+ISFAf^!77PZydiATUqf zKhu94>6q!Cs*wdukB#G^w<98cuJ$Dd4gbm>+;9TvIMqKx9tBD`Q@E_cGC$AXB86&I zc6gN-K@4Rk=2{$PzwRDFcCW}W(??6zuXh$AwKs-dBw`(~G$_Q{PZo2*PmG3Pv?QJr zZpP+My3oRgetCWW@`voVEsxxhW#Gpe7U3A{7u-;vN-sx_$PzCq%)%BRG0|BUk3Uu| z(Zx47BERXKmaQ{=NiLLh+7HH*R^`w(i>G%#--TX| zXFcapzt6ASKk0wGu~c71@8;4vaP$PDpUa(jxag79eH~A>Sx!rZSLz3{xbKrYIP}g} z_b`?fXOcVa{%(1^Q?UV1MpU#wS9;N`Q~{-$LGPNCC=d}H+SXRN#Tcto^9pu&pwr5V z$}X%sPpPSTba00(IC6(tDk1PZwCQm%_3>??{T1}^B$7F=YtnzR+q=&v~;&=bs`_9BA&OWV+iRGS2{Gag1E$? zKp)(*a`IKTxBg%pNH{`cL43YjDScviYN)aUV9NRac7MT(DqR3aoV{6-rz?dNJy70) zh-ridFBcl}`Nx4u>|T$QY?z@~7s>+vTlrNd{TcXdX?=IBG}%;K5qP4lG^Mz{(@@`a z_IZ>KVM1M63%79=xZ`N&yCw%g&V0D`>}(KrI8OZl+YKCHMTqvF9}{;KS|fpIQ{yk5 zuf+<^Hk@Elzvl?P_#fpT6`LFhubF!^-?*>o$d?9bzkA&MRQKJ%oB&_^U`Do6~brczk@og%68wb+Gc=pqb0emwi{4uLHr<$(oT-X{gv>6Ago;PJ0w}Y(3 zxo~#E`Y1ZjQ}~K4AoOLm~kOv#-UBX+dwbj0S(Kl;# z+>>g`eP{IVA7)f}&l=u8N|*nt%$xB-qm@OpLI|$sHx(>@*Z|&gf2$$<{jl7@+Z6GB zRKY%T{N~K9qqIGZ5${J7X#OEICil4t-b(-Uc!wG>ICeDSNtbHl%tkPua(`=o3six& z4YVR`rh~>p%sseeSrv#!q89rAeNre6#(N?W4JyV0AkKMlc%vRl&#$e30|e(lh3JdH z-Zwe!vJR}~Upm`)aJb{vycZm9;t-??o(tg%CAWNC;q)3tgdS3`b6SY9Yxu>PkMA#X zh>|1+3qTv?!`2J#f_%bQmVY3rft(#*FPFsq?_eJ zvk&w`%5imIUwC<%KYdxS*98f0(@{RyxOQl0^ve$pj*}A@(gN`{{3U1NB|NT`K)QtM zTl#)`i=*rh|EYf>oLQwf2Mqv&{zs|`XhCB5(eQ!Y12VLd+>c%54f*dYKwx*jbd>|% zSTq?2*sne|&7VFmczINgy<0tmfn}t7)=OQsagQRq^vQ5Ex|7Yn}06ECn;qNO%FpfaFD!@m8pqxg* zposPjSuiA|{sw3#Y-S3AlDs>9RN!Z)zTHqe)<<7rwV0>9K?5VAVtbNv??M;GB2mAKu1@N*sxQE>Fdx z9%yU|@@fK-CC@}Li&M((*>PTGNGNWAgz~Y?geemfVj$R_z`QsoB9$GAnT*1< zpE-ftv~zznMYNQ+vNg2GhLZ*DPkedSw!H^5bQ*IK?Ohx8igG1t@`upGeL$IAjo9o_ z?heY=CzZ^$xZ#vdHsWeguhQl$L(G}I)py6xp;?m}OpU$lt4V0>S>_zn!yWiyCm1#V zaMR}({5B^$^o`ArOp?-JU}X>M<-a*r!f5e_vI=NRqZwGMRX@wG$yHB_6LFuYu7uzg zhyl0y_HQ56PiT*TIU?FRp08Hg;@8U9|9liIb9W>D$W|4TIb>}cYb~QsFYcS_=jO*D zsjc{u!PBufN+P1DF;SZZi3)2z)|@VxmGu6L42MMYm$>}r#_@&qp0 zZicGxauJ|9RF~jf$oz%bv!b(B2b4RXnq8P#QjG)WGfUZ7pm7+A1ZG9Eik7ej08i(* zJkcTnxI;6UN{LS(=F{il8si}*BUnp4HDXL9nvY}Q=5Mwkg0~^_aiVDNsc>G%{m^_+ z6au01HrbF&rWc%u4g)kR2D;R{r9vDAc5`zMML_j17v7>3L5om|vtuMbIH7i{_b{3E zaC7bXBH*seJJq`aySUj0l0R+EC+Nt%sr8$topWlbF-`=eVYm;D^Ea(KxM@BA-jNDC z0oI>G*6~4jOT=Qt4Rwl^Qw;SOjolFB@mvJK-3WsY;AA=mES3QjRTzQ}$DqZmFk(!M z$+QuLET+@Rnj>=_SjS6Lu=Fm)bjTc?mf3-dK3!Y5|gGDs5vE;_AUNWk4zpsWsvtnw2WQ z)T~j9Lpp$yf=*b_@nF!4P=Jji5i|--N^VF)u)?5d)M>@R5C$C~7h>}viG&YV0WR-X z61No4ub{2^u%^r`77+9VRK;Se`jlU9X>RCONHW$oevPp>T-xNv)*O^5tcz_p`smPS z;`YzM7Az^^+3G7sHb^$$#W?n?$?N7@8b2-Q*?P6|CTk@)j(0!7B6mCKvU);ylRSHR zTfNv%k}>e`*dbE2yGahko)`-8a|Jn|0590dB4Y?$QqSuyo)u2f$=qI!Snwc=f}#vb zJ)wKFOt?10*X88^9~hT1P3(xQAq?s|V_jCIM^lgB>JhI-VT*Qk>Ij3@ITJg;rtt_x zGvYN+qP}n=AFI!sK6v5TVfB8Czl?$_qioD2@vUqkL1y)iG7%R8KD?_^;&~+FO-UFOTABiy}vR zKlrGlm}7Rr%ogPSy*kb)>Sa&8@+L-u`PdmNx#PodgU73lvB>3fKN#TXO=2N1$L-9N zk#QPk4BnjR=(`g7vb9L9VV3FgkzjNKUAZ#My|zU0jr-tZ@57_o{B`$|5pHY#;gR+( zQutHmPd%RYCtgHl?Z0ff+D0L8hryvgxaZpj^@D$GFvxfWh-6sVWRW1ZbRxFOAY)K9 zz)~;h&vX+*6MTxph-zg*1L7p(U{)mhHeuFNZyPhl;PO=jtb(*rjN>YZtUwT(f0_9= zNfH?jcsaVuo(Lx1^go>2L2e+B6vtHPxFK@4-L_{=^xBX8TwKyplXuPzUz?5VOSC;W z^w1Y4@Sx)|uyeE1@!#gy_Ed3h_Q%l08jNQyw41Q4w^$_XwVOedE4&#Cv^Z)(T}qA@ zANvg7>DN=!u_j%lZhbWi>?LI}?3&FyIOn5(7kxiF_B`TmYxGaE zM;2b=zI!Y>5^8F=dETeG;h22=7WuztzdRLZPg#pCDC-DcRt=+p@#v@i-BwwH^_-`l zGlWKuEj`8opA)CZ0c6*dvos!41-vgLPBsrYxXP7By?icR==sT{A-nQm=~~s#n4Hnl z>TtC-*V9>NVKU|yrp7!hpR+{VeKINhCVQV;=}X; zbpsNy1HW zn{gWX9M)bn1c++zy-1Zp@SHJVA=kBPkwa26t9&32heK9SD zSUA0saFa;RfaYvMxb>SrzEPmOY*)LZv?I2X5%~1Dj4?F61ca8hMoOg?WJaf2QdAvm zj0ZN`(PMcsGJ09bMnsq2cwja*_$)SSQ@FX!G!W+cl(z_N$e7$)wiF7edN9Lug|83u zkEO4)j#Z9uZpg5IT{qk~*n|ijr`RWHiipm*Gcl~#fGec~p1(2@Z7 zp<&XTH!Ii>l9I7q>p%rKIJVKd3FfNs5p~aD%ii{>r*=~2{7#@Xc5b_4+Yz1rnzLAf zlI?@-v2h_$gJ?>$xUc9G&bgvSgS2l}%ucgL3FDhti(m#Z_J;1<0&svsIN*H^%cuqm zBP&bU-k7k*uh)F4<8sUlZeONRJM6pIX>sypTz zP0kqcQg<}rWKcFZYen#TsKef6_55@!LJrSxhTC-oamOVn;WIR~#VB_E!*mM)obPZr zY4It5;f4yT`1fh8qTBzFq&7tQF6MZtfM>kOJXan<#`|VSPDzfD^9~?r0j%z)V?rJ) zSs|5cW#8?IFJ*l9_hCyv>1Q#*0CKk_EmP%su?) zg?Z*tzt|?{UfI4?j=`y1BJCJM^0Fv%>Fz+oLmqq>z-smJ8ai4faFdwd9`-1{TmdE zNc-#RvQUWxo)M)Qx*G}p{knNRvkN!E4=LQcf5G3}kJxyUE#*f8)Ikpf*slxdJJZPv zeI5N^z0>uYq5+vB&J#s7*f83Ss0hOzl6c>(>PyZ86inuo?z~$2$VENguZ?@tQs80| zC#!#;uVA|4LZ+=64IB>hDEVa;AZUoQ5LYMvdH&0u;eGqZoqYEJrW1Qmww=mLB|kFR zJ^45-f!pExqzmG_1V-U~`_ny4_HUizt831%>G~Cog}TW2-k3f>63Gre-aW;O_}i<# z(nGjYLdtt4;-|iovrJ#j@e09ZRsYwv%M<4(GHJ`F>ARx1R9p|0nAj_?QiDWigpj-9hFMY*Z{)1jn z+%{l$-yS7Q1dih4#mhkY+&>S7T$RB1a$U#}Yt*VtE7N%(K#1-hww#Sb){iTn#MClL z`#0*7nb%?gZfYcbkm#}YQ0Y)WbljeHw%`tjFD0vYqR?o)^impiS26gYu&{dYK(18H zouLkR+Eul-9DTsF1D`l{Llwo9(jLIvfX06-msk7JwJ3XU7i{lkCv~(KRXq{+qb0;# zeh{mBdOB~@L;lpwJ69)z1$a-tn)GOv(mcgU-~5q;UW!^=$~v|l@Diq#FY(-5Pznkp-DxA9J^b`fb{00)^@FLlXP zMB6$>BB8VHs7+!~h5y!ko)jY+8d#@cFV6%-%|id_xQE`uxX?cM&i9_h&Y94Ecu`pl zbC#ggWp7w@W!8F^ZqUxUH^}DOSz^v?!Q)cHa_~y79mp_Sm*2J5f1t|@PJQRaq?5<7 zLgtlg)d9cxk=Y}s1lRC<=0a22?RqmO%cqnV+`4F3{A|l`*1f!M{yUqQEYYf)`<1^@ zm)k54t8={05)+k0PL=~b9-nw{{7fc_3%HIq5)bL4oGEtIS@&Myr)&T4*t7x)S4**s zO|bOSQP;JerEE#}UeO0bv6Gp!^Mq<~Mm>~BFHi1~>IIe0_9?r0}g$V7mKQ+Bj?vaN( zTEE%;4po8ySCBFeY?pnBYOnfW(fd8}Z5`V39LU;`y+BRCkyhf`h?hv#Av#)CReKFq zUxuaFYQD8!&X7rq-?FMYCj<6{Lf3`{bw&F>5$x8d#)B<%eV2RTwb9u13n2t8`^P-` zKjbAYg9`lnIQ1#LM}D?Hna|sEbDW;@$g)-H2okH$eD5anhH@=DgagfvolD3kK>h6* zGt_tC;Cxxl9nC>8VsLJnae6FHSGBA35IDK-%}j9l?)(0dd6PN-qCv!m7&gWYC^oHy zvzG4(H=RORWtI8JTFQi6E3)NPNAM-($`OIEnu?b#GYUY+_qqn`UIdMW96}eAYLpt( zBsr%b>2{Sk;mVawS)e19<|GdSyuBO14RUgX4lahi=(Q{CT}V;wiVQa-b7-9m_)gs@ z#|NtcPXwb;B4~EF`7t0)y;QlHGQ3WprJ2nXeeo1sMP>zx(j7p`mQac+9;6g{8J-Q3 zRLTHQPrT0Lcp{3Df3ZjEXYl>e?g^-xBSTDv1664V2;teL2qXRJaq?qh{!z9=FJQbe zAGjdHT9rk;>>n%Pc(0 za{~Lk!tAXsJA981W={3y=3H1{+`iwA8g@&k+qe^J7oX9+Ei z=W3hO| z!6mh4ocQR2g^xR8*&lV}Iy-AGYI>h|Qz5SCU9B1478x5?)av)Lcj?~B?Z5b9Th!!u zzj^+K;{Py0Wz8Z20wLg5_Wn|FA2md+u zO~1JG{cP?;y_ab-wdGIN_H;9G;O+j%*2n8_lGDZ!+Z>Y}(~XsoP?jJSnv=qe!#u)h z7mi8+)6yaP2QHVmV8%2rC1C5>lhQrEIE2Ui{I zFXQN$m@^H5(?9mI#Rc0;*5hCxAg{T5S4I*yptFrJ_FWcvE&*Mds?`Zy!vR| z-qcr>l|NR4)~#itzg|H>hK9CN-2?sK3x$b5-m-=d#XG>L`wW7zVi~ko!+PNcoU+y* zl}>Xd0n#abQW+H<;SeYC%)qI#RKHPH2HBd)yzLmiL_gd!%(eque#=vRbq~Pw&`yv$TY138QQb5gd;zurq}=py0H@9q-u8Rf=6)BqnAw!D z3B!14I1ZD%CPD)}4mYCp)0ah`{P;=~WwNavcX1QRo865!Qx^5a%}*n4DD11PlseLZ zB8bwjQohra-$A`&t4s79WMYpAQvMQ!4ikW7`;Z}x2UtDXXgx4$MS9qOC_C`IB$7(2RWmCZ=`Mt^*jDlk)i{P| zZy_C9Tg9vnjM*PK$jRp64ZI%U+EX?&zNJmGj^Rc!%YIlx-8xgxBC4P~^C>1-ld?xK zqaSlG8Nm`o@X~SaCn%2x55hLwh9b8tD@ordNsI+c3y-{1?e4>)&Yf4~rC4wch5+R% zE2{|H0O)>(d&|;W8A-%v_nNEqWswAS@#JdQlTLQBWJpTK-_cY!StCeZJN}#F_7lW} zWh&!ohBsiFY|zRH1XXR(nxs2ZCgIF1L1MFtRjF?{3EcoP6qZ9x?jnvLVbCdx(Ufk` zt>nJjfK_gc@Ok^j7=r0>57g(mxxe5e3I?QQh-^3^J2LIGugOp1LW?*BJlpB~ZN~&c zZIV{&2;4U+74OOp%8eK&T!{6XAU|n@`E%o1{%wU*Ipd}Q`MfwkDcFQEM8olf1(z^l z`SL$OaMmLQN#{-RXVrE@)|M0k(?CgGB6GF)5_49eQ3Zs~F~&B)Ivo7td+sKFO~s3>e0IG{23h;mb&#nesag4` z@_kFs2^qCMA+wVAJ8q84!5WP9NU`2&g7hU2DjG)NM)Q$YnG&=9e4m&G@jONGqX9q# zjtoI)W??OMfj>ehq1{_N>iwhhQ}a#zZJA_|!fVChVI_sHmJo~UBk#nYTutvWZP5~I zCWUONz7ihkxs*v_kt}p0xUiDGOK&_WEYt#}4hf;P&S#DenI3A9ce}X%OaTm&Sk@0w z6#p1M!8m=`j?Pls?7r@@?USEYfF6L49Z@<=U|-qXl?V2Du6{2v#0&hqFt<CA9bxDcrer!V$z`hL$-a6_+Y}r#CO(e@AiTW)HmZe`6I( z=2N1FZo_D$pXm6-X89MfP;!sCGKzm~_|jE|u2^NaKaKMJ z38J4LE|CeZUA=0;_s-)@U95UU&_59rh$&}WFK&N4HGgOMiqVhqSLO=Vg#VX)lniw4C&(!X5IZ{1P6bN(?scMAl1y_HFauG98RRzGJ4gI4fm}q)@0Civ}hdCf=?e)zradr#O&-%ID` zlYzl+EW+o$``Pn+tZ5SyznYtsxA`ryD||PwUdUZH2dt*}s)EoU49)6O1dstr`PBq6 zIeN**@qbhSuYw4gAo$J!2J>zr>I^I<>n^JJUE$$jM84b%W~#X5T+!>7``ps=ywjph z*ziXkuz>K$IDx=m7gL%qmkjk_R{QH)332B}c7vykP=4!n+s?9s8fkVG}81*3h$1Kho;4@eSj zZ%{ze;Ab#%bDp;iXr)#!D-Qh_u2fosM(yQ2*--cWXuq*YIZHrq8+=5_%48C&0ABS; zwN8Nahn;uqaMG-#(##?bwy-zPhty&1=mk*9Lz~aqCod4nPP&d+8 z8lDqa8@aVp$%AbS24IwH97uQkp)Frj@QY$bvxA6cV5N;XoUaWm&UI?uN2W#-Jl?AqR-{LLDOj?w zbJp^D*$!B|8XNOX@4;sjKIq!nT&fUiWw<4q#oG%NNz!pEbnyBGznUvewy3C>H#*8% z>AN0~VB0ah^|64uhQNm=*MzxeS!Wt&YtdszCEHf0z(XcDIVF2$btH{*JY7oOj@PD7 z(`+Fam1GNNs_g?UUtVb^JsHgzB}pu-z@tPdLqu)W>+y$;3Bh?M1gm2_J|+;m=D)#@ zV;@>o2SZv)`%~6|?X*_iF)w;ieC$kdGA1a0Rl^gUFl@`usJ^CGicuDWQ#gTo2PNHR zC&P-Xq}7D@ zZY;ai8C`0+b6w2F`YOk-htSl^DgMF+M%&54@uvS-5;chL*5vF41Z*h6OssejM=W(i z$xBe1d`S!%B+uATuCyyow?Z9cgUeZ~axMLGtxL${@1)+dKVZ*lVsp@c z;e6lhTK22%u@V5(kCu}=;^arKLEcCz7I&%p=)3PMhG;cSxx08Ye+ymbW~27@o|;cU z=K7&N(dsjMlNRg-r0-#S$kyTZN>BXRqo_?Sw9GLXH6#+%v_m$tTFZ+Q*@gxQu52*v zw0uT?{L2pHDRL4v^*)A~D0pLdOu`pj1j_p$kUXOhMO=x8%oOhkv?9VAim%dI%I{-u z$Yim^^Z+N&4l25oG-||&yDUH0j*hGYo}{vWHMrd(IMPh%x7Scxb6ORCw;SkW z{m!sjQ_#Mft?X#Tt@?DWY;w$(*3Fk7>t1V@$oAB|VwN!des_X;TRm*(y7}}{VrTpd z#6jx6Q~4u*qs-$@_;upv0ajIaXgw`FP>=5X9Q@%hJ<1HU1=5mn@; z_+|rgN*YDT$;ETGmedeE?KUIlm;hkTV@pCC!nc#~*F zc)*A21pw7?u1#XOfpuuq$dwb_by@_Ir0L>(l2KNPWJ1ZkSPNQXKd(8qZzp_J4Q@ZIdA=2T7g77l_lOv^$=_#c_QJ2 zEa8uW#c-q$6MCfD)e=tNj<|+vFghlx90y?*oI9-k{4Q7(sdAx^lORino{*1;gvKX# zyD9rMWGSh{Bg-;2Iq2nW30Y>UTLNK2Cn-mzE0W+FjE`PH^udruXf~n{HMRhpWP4=T z^T2&oIPxm6$97H9vD^lyx>3xSh;&AY#F+T=K0<|b9azkZp_*KXv*c`-xg#4RLV!5E z>&6z71eHRmTA@;hkEPl+WqxzWYa6*-zF0h|#zhQ$cUq;Ey)^3k_-HVc+vmMo{SrA( zs#@YVYo%DA)yBS=(iWS*)>N*L;}jD4GO>1E*0zjgR#kMgsY02SKkpS|mXd)+mK3EE z6S|5Hf8n^d4E?~E?${a2M4(`Jkts1P$z$hsZm`anKyX#cHVRi54ACcR{e16s5tZm$&loStQ62UaYvC{>BAc)>+v}hn9@06mF2D zyh~PWnu+BbL&EO9B-fZ(fyG$p+2D!5(+N(~fVp)+Ho=`+ZVXfY$zpEDFe>Z~VYMqy z1J~W*Z_FV({>O#Z@ZxUsvgw{{1&{ZNcD-HiOlm#Zr)EdyBhB3OVn@0&DR|Id2VO4U z{UX95Gg_;GKB30WYxC9Be50y;>R+hWaL*e(7hDH=h~i#7Bw0cIgzRl>ormc#BOVMUvk1%sLdwY z8mAa9ZGV}$t48w2oFD=;lu_w-I0Ol7f&m&)q6Wb%aZ!jjuB^|`H*5eBp6!H88ATKfsj&^* zl-1=b3C%X1X+{u;IKm8%UIT^E8Kg&Gz!eP$JP`rK)R0#bgxe@<2?Vk!QwITal80@W z+ zdMQ!T+(So%)%pw1GVNhz@AIDiaTFKCyDf4w})_~)>Rde zSP1M?`U*f%xf_nmkw{m*?WA_!`!dcH1sBLMyNjYy{%a3---<{VbnywtFIXA-lteP` ziRdZ4UnfM*l;qFBfZQA3ZTsr)8OUWt;qKthY8_$B6bGEdv|~#~Y_ii9 z(S|9=K@2Cg-Nk4xX-;SFL6-sI0^zu%3x_z~C$vb+V!1-sVJ;w5OsR~*#+s`Fh$MOE z0>XgxDLsFVBTIUL!R8uG?Y}YMj}iV{jz>td-@d@S*lw3?l79{F3Z5>=M$b^l`!F@V znU=$$Ddd@yUMlgTP1l*ZI=|+tYt90VL!82!)+>fL&FXV0(d)L@m^iPMq!=Di0Pq3} zH!5JqN9Prvz(f(#l2EejJ~HZ{JkXpIly5syO^`p3PNmD0x-go=ei4&8dr=GSrW6o& zlm!+qtrz5)gan{ws#6HM+00v~zb#x*GR<3^Ke2+)fmR75+XC}J6VIgz&oJlF*KDoTUeQWVU`nbd zo)ML3nB~sb=PXol$fn|_5w~l$d(q#ZL!L?$rK^O&Tj~`^v%h8xnN%rgkQ}jND8nG` zpdwX*=w(|EZ>+>M9yZ#0ZGl7Rz=IrJ)w|pjEfeFr+Uo@^4Xs$?UsWi1ou~EmkE;vO zNzNOa<$Mg99qFe;qkrFEzfN-1At*g7`}Hd&b!r9dWQ&#rUJ9tvoe)@;yE_V!8M&!!4vK^$5z7UVP%fH`Pp(wx;*~tkD6+lcd^ypqC8nBFQk#9KZA+*rM*;s=pwn`(R638) znC$L+VGA0)@IgIcqY)f5EI9OJJcHT|uR3lG3F|(AOr>2y(Q3qsPH(UtFzB%&t-3_z zg2~jHR$cqXWm!{w=Ve)2{|6SLT0@W&mVJ@p^3247G|4P;<@%JR&11%15L$cL$XG1; zRG_HD#6`qJ$A(8o$VntKX*?p6E4nF_Tr!(47R~F`yi2DwyB}kLL~i7G<+NBV zmr9m|J1$&U?0dgKq0p#wiY*!rNu^Q~6*^@I5_*4gXrq=_)cs;uMHx)`%a@|Lm91@C z))dWkUDk>yOn^a_LwzNoHdL~k2zz3y(+!lEKO8Wag(snjIC-aQ}0+8)>kk>D%Pg5DzC1SYUV?MW0|0xSQIaeQjula zL@o;p@H)e-@fanO#8ql+Cw3uV%Pr*l$e_(x?nUSolK+p&k7B>KWaTwq{_P2p{i>6`{^S4&=jRr8eh7RNG`DK% z2q{G+H%C{iaoTRWoG-WB+$?lyLGs-nQKe5&u^7z98xo7f0M@>CNh+7lq?^9_w%23L z?5LUDE6DtMX4(gYplM#iIh6->f{WAS1xd`(I3ccls*1yU-+}L44DRtRx*S2YgzU8K zYUAVzH0J&E7Moo49{)?+vn$-C_tnMH;_?I&BQrx&V{?U*qr1KK#qaaakFO6ePj3${ zR#}V3LwGq~Dbv>#ZmPg&EUGGt>m989e(woFUf*Z|_%{;<4xk7vKK-h52dtoxgSA2G z)p;rGzM-YqeKj6F2@|LkF>?k@8@RMFbbxS%15m|8RMn-JU)I3ieLqwr(d2dxT|mI* z$S#$$(wk4i?X(Gk34HmRE}E;AmzkTLpP{3rrzvYeB|bjbkDsS6^;!vD;wO1qic^Qq zZM?cUe2CD&1dD3UT#44=#S9zk+M1rCrAiF+2$gg*j{?~bgB*C(o#vgoJ-@$yzxGyO z2OuI3KqMDnrXB)CsFJ9YsanLUmawDAnntXexU=cn#;%^g0}C8Tu%gHlE1bc?d3$_* zUc{PKZk@e;2G-u@?(hMG7y^wr1eI8ZoVp358VjvD4YgX2JbeKqX!wScrEPs|TFH)_ zN4dv|q08Ge>+yEZiAv1D7X*FqhJ)~Iu1CB|vp{9nHga-aGc@-Pk&%)Tr7xyNNAh6t zdlqtvWRGYdz1RkT-3%aA08aIgmZ&gYiN$ z;_2U$t>nQ`Gv9ZXVe^w{TTPeuX|7OnCAO+C$V;7(+87&|`{-y>>JnQP4hDsExvvaw z?Z=P%VJ=~_kkQV8FLS)8N10^7kqiP9nkxCE7fW9^^P(iH?fmWT@3H)mVg2-;IxP$3u%|0r@)VU~90jIm zFN~ z6?rLfvs8FW^Bc$7yiAUY_@x0gp2~q<_xpk1iPt7D)MXsrVtpn~q+|TXa~qi_uK_$Z zaz|LZDm^Ez$-rt4^Qw$2p@(TltNEEuR$tQkrK6?36EGenb|}_~rJ6KoSCdkqjPlKn zOW$@j)cbwK+)}=5IlcsXGD}{Pl@-=bYl6 z_5=E_E*$%qA+mBf0fr!BHf1{&V;zZT(}_DULLedva@)B-rDX%bmi7Y8&c28{`2T{& zNF*bPH{|{Z(fcxi#TIDVvG4#P-cY4*AfUK6M#@S>9;oyLA4g}@I6vS1aB_?;+TeB% zs9M~#g@V`p)37~*w?k7KOH@YS%Rx6ApM&s2a>y@o`_G_aJqrdbSh8YG3xkyqhZ;q! zS{aA>TsG+*DQirw&QIzdK?U7G%jn=yv;)m>(M;>1&+4v5gt>*^XP5hSOlVWy%{n63 z$Z6`|A9POdzA`Wk`eVj3 z#g|us41@Rs!uSLD0~`VX0{|cyK!d)E;TV7wS2-JJrS=XHO7V;Tq+-Cv>5-|YQ>YeJ zWORgR8D9jcm9cARZmr9KV^$pgi8oINEO@1k1O2X2MnX12qqh$SViW*yYlBSwEr8*s z!*2e@QR0X2VAC33J0D_b(}n-+#2@uI?*zB`t;1n=f2WbgE?Fn$(T`xCh3Jg)h(r}b z2t-P(>hO_mt3|jxyNg?mgKN;tg62v|J4Oi8<{MRrVaS$@ciU&m?A$G1R=aHTPdAk{@W!+hwb$&yAdMJPqKYrFVC#- z$yt$y&Nr4A`@oSl$cv?^NQk7?`$oqzDt}*M>^U2Qzz^-39Rwz!nLva2Xi>^h7?*pWs(83NeUdP>1Bdb!MC$`1*#q+n8~)mpY_a!pyrU>$Sc+F{vd zx8iez2o2FOh0}OkQn|^(iC8N>KXG=PJlVZ5Ns)EU4`*ybfP418QZTX0EreABqN8aI!_>}FBHGLkA&l{R+JCk9~KFW z<@m53?1%mP;aBU6N9UVaif`)&t_MIZlCCf+OPJDnolPVV3~9QJqGUNWO9}X2nCZW8 z1;Bq{s{aT7zusK`g)czD849Aags5ycIAQ%EkSE(Iix*RQXMvv8OjU8^@#%gJn%0iT V7)~)yDZnpu49h_gZvJhn{{a>V-DCg& literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/SourceCodePro-LICENSE.txt b/src/librustdoc/html/static/fonts/SourceCodePro-LICENSE.txt similarity index 100% rename from src/librustdoc/html/static/SourceCodePro-LICENSE.txt rename to src/librustdoc/html/static/fonts/SourceCodePro-LICENSE.txt diff --git a/src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff b/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff similarity index 100% rename from src/librustdoc/html/static/SourceCodePro-Regular.ttf.woff rename to src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff diff --git a/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceCodePro-Regular.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..10b558e0b69a74b8329766fffbd5f64356c7230d GIT binary patch literal 52228 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 z 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 D0=ucW literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff similarity index 100% rename from src/librustdoc/html/static/SourceSerif4-Bold.ttf.woff rename to src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..db57d21455c94e80aa7cca25cac803a08e1b01ec GIT binary patch literal 81320 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 N>ZPvCW|kqQ1ONsnDE9yW literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/SourceSerif4-It.ttf.woff b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff similarity index 100% rename from src/librustdoc/html/static/SourceSerif4-It.ttf.woff rename to src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..1cbc021a3aa22e1469542d531e9115fb78d497ec GIT binary patch literal 59860 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 literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/SourceSerif4-LICENSE.md b/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md similarity index 100% rename from src/librustdoc/html/static/SourceSerif4-LICENSE.md rename to src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md diff --git a/src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff similarity index 100% rename from src/librustdoc/html/static/SourceSerif4-Regular.ttf.woff rename to src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2db73fe2b49e8cfcaaf1d5311a610e730b8ed502 GIT binary patch literal 76180 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 literal 0 HcmV?d00001 diff --git a/src/librustdoc/html/static/brush.svg b/src/librustdoc/html/static/images/brush.svg similarity index 100% rename from src/librustdoc/html/static/brush.svg rename to src/librustdoc/html/static/images/brush.svg diff --git a/src/librustdoc/html/static/clipboard.svg b/src/librustdoc/html/static/images/clipboard.svg similarity index 100% rename from src/librustdoc/html/static/clipboard.svg rename to src/librustdoc/html/static/images/clipboard.svg diff --git a/src/librustdoc/html/static/down-arrow.svg b/src/librustdoc/html/static/images/down-arrow.svg similarity index 100% rename from src/librustdoc/html/static/down-arrow.svg rename to src/librustdoc/html/static/images/down-arrow.svg diff --git a/src/librustdoc/html/static/favicon-16x16.png b/src/librustdoc/html/static/images/favicon-16x16.png similarity index 100% rename from src/librustdoc/html/static/favicon-16x16.png rename to src/librustdoc/html/static/images/favicon-16x16.png diff --git a/src/librustdoc/html/static/favicon-32x32.png b/src/librustdoc/html/static/images/favicon-32x32.png similarity index 100% rename from src/librustdoc/html/static/favicon-32x32.png rename to src/librustdoc/html/static/images/favicon-32x32.png diff --git a/src/librustdoc/html/static/favicon.svg b/src/librustdoc/html/static/images/favicon.svg similarity index 100% rename from src/librustdoc/html/static/favicon.svg rename to src/librustdoc/html/static/images/favicon.svg diff --git a/src/librustdoc/html/static/rust-logo.png b/src/librustdoc/html/static/images/rust-logo.png similarity index 100% rename from src/librustdoc/html/static/rust-logo.png rename to src/librustdoc/html/static/images/rust-logo.png diff --git a/src/librustdoc/html/static/wheel.svg b/src/librustdoc/html/static/images/wheel.svg similarity index 100% rename from src/librustdoc/html/static/wheel.svg rename to src/librustdoc/html/static/images/wheel.svg diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/js/main.js similarity index 97% rename from src/librustdoc/html/static/main.js rename to src/librustdoc/html/static/js/main.js index fe1ce2e8b5..869aff5376 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -683,6 +683,9 @@ function hideThemeButtonState() { }); } + var currentNbImpls = implementors.getElementsByClassName("impl").length; + var traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent; + var baseIdName = "impl-" + traitName + "-"; var libs = Object.getOwnPropertyNames(imp); for (var i = 0, llength = libs.length; i < llength; ++i) { if (libs[i] === window.currentCrate) { continue; } @@ -716,12 +719,18 @@ function hideThemeButtonState() { } }); - var display = document.createElement("h3"); + var currentId = baseIdName + currentNbImpls; + var anchor = document.createElement("a"); + anchor.href = "#" + currentId; + addClass(anchor, "anchor"); + + var display = document.createElement("div"); + display.id = currentId; addClass(display, "impl"); - display.innerHTML = "" + - "" + - "
" + code.outerHTML + "
"; + display.appendChild(anchor); + display.appendChild(code); list.appendChild(display); + currentNbImpls += 1; } } }; @@ -780,26 +789,21 @@ function hideThemeButtonState() { } var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true"; - var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false"; - var hideImplementations = getSettingValue("auto-hide-trait-implementations") !== "false"; + var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true"; var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false"; - function openImplementors(id) { + function setImplementorsTogglesOpen(id, open) { var list = document.getElementById(id); if (list !== null) { onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) { - e.open = true; + e.open = open; }); } } - if (!hideImplementations) { - openImplementors("trait-implementations-list"); - openImplementors("blanket-implementations-list"); - } - - if (!hideImplementors) { - openImplementors("implementors-list"); + if (hideImplementations) { + setImplementorsTogglesOpen("trait-implementations-list", false); + setImplementorsTogglesOpen("blanket-implementations-list", false); } onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) { diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/js/search.js similarity index 94% rename from src/librustdoc/html/static/search.js rename to src/librustdoc/html/static/js/search.js index 35be246b5b..76e7295bce 100644 --- a/src/librustdoc/html/static/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -73,7 +73,7 @@ function removeEmptyStringsFromArray(x) { * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode * This code is an unmodified version of the code written by Marco de Wit - * and was found at http://stackoverflow.com/a/18514751/745719 + * and was found at https://stackoverflow.com/a/18514751/745719 */ var levenshtein_row2 = []; function levenshtein(s1, s2) { @@ -106,7 +106,7 @@ function levenshtein(s1, s2) { window.initSearch = function(rawSearchIndex) { var MAX_LEV_DISTANCE = 3; var MAX_RESULTS = 200; - var GENERICS_DATA = 1; + var GENERICS_DATA = 2; var NAME = 0; var INPUTS_DATA = 0; var OUTPUT_DATA = 1; @@ -289,13 +289,6 @@ window.initSearch = function(rawSearchIndex) { }; } - function getObjectNameFromId(id) { - if (typeof id === "number") { - return searchIndex[id].name; - } - return id; - } - function checkGenerics(obj, val) { // The names match, but we need to be sure that all generics kinda // match as well. @@ -306,7 +299,10 @@ window.initSearch = function(rawSearchIndex) { var elems = Object.create(null); var elength = obj[GENERICS_DATA].length; for (var x = 0; x < elength; ++x) { - elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1; + if (!elems[obj[GENERICS_DATA][x]]) { + elems[obj[GENERICS_DATA][x]] = 0; + } + elems[obj[GENERICS_DATA][x]] += 1; } var total = 0; var done = 0; @@ -315,7 +311,7 @@ window.initSearch = function(rawSearchIndex) { var vlength = val.generics.length; for (x = 0; x < vlength; ++x) { var lev = MAX_LEV_DISTANCE + 1; - var firstGeneric = getObjectNameFromId(val.generics[x]); + var firstGeneric = val.generics[x]; var match = null; if (elems[firstGeneric]) { match = firstGeneric; @@ -354,17 +350,20 @@ window.initSearch = function(rawSearchIndex) { if (literalSearch) { if (val.generics && val.generics.length !== 0) { if (obj.length > GENERICS_DATA && - obj[GENERICS_DATA].length >= val.generics.length) { + obj[GENERICS_DATA].length > 0) { var elems = Object.create(null); len = obj[GENERICS_DATA].length; for (x = 0; x < len; ++x) { - elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1; + if (!elems[obj[GENERICS_DATA][x]]) { + elems[obj[GENERICS_DATA][x]] = 0; + } + elems[obj[GENERICS_DATA][x]] += 1; } var allFound = true; len = val.generics.length; for (x = 0; x < len; ++x) { - firstGeneric = getObjectNameFromId(val.generics[x]); + firstGeneric = val.generics[x]; if (elems[firstGeneric]) { elems[firstGeneric] -= 1; } else { @@ -375,26 +374,23 @@ window.initSearch = function(rawSearchIndex) { if (allFound) { return true; } - } else { - return false; } + return false; } return true; - } - // If the type has generics but don't match, then it won't return at this point. - // Otherwise, `checkGenerics` will return 0 and it'll return. - if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { - var tmp_lev = checkGenerics(obj, val); - if (tmp_lev <= MAX_LEV_DISTANCE) { - return tmp_lev; - } } else { - return 0; + // If the type has generics but don't match, then it won't return at this point. + // Otherwise, `checkGenerics` will return 0 and it'll return. + if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { + var tmp_lev = checkGenerics(obj, val); + if (tmp_lev <= MAX_LEV_DISTANCE) { + return tmp_lev; + } + } } - } - // Names didn't match so let's check if one of the generic types could. - if (literalSearch) { - if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { + } else if (literalSearch) { + if ((!val.generics || val.generics.length === 0) && + obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { return obj[GENERICS_DATA].some( function(name) { return name === val.name; @@ -801,7 +797,8 @@ window.initSearch = function(rawSearchIndex) { results_returned[fullId].lev = Math.min(results_returned[fullId].lev, returned); } - if (index !== -1 || lev <= MAX_LEV_DISTANCE) { + if (typePassesFilter(typeFilter, ty.ty) && + (index !== -1 || lev <= MAX_LEV_DISTANCE)) { if (index !== -1 && paths.length < 2) { lev = 0; } @@ -1058,14 +1055,14 @@ window.initSearch = function(rawSearchIndex) { return ""; } - function showResults(results) { + function showResults(results, go_to_first) { var search = searchState.outputElement(); - if (results.others.length === 1 + if (go_to_first || (results.others.length === 1 && getSettingValue("go-to-only-result") === "true" // By default, the search DOM element is "empty" (meaning it has no children not // text content). Once a search has been run, it won't be empty, even if you press // ESC or empty the search input (which also "cancels" the search). - && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)) + && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText))) { var elem = document.createElement("a"); elem.href = results.others[0].href; @@ -1166,7 +1163,48 @@ window.initSearch = function(rawSearchIndex) { return ret; } - var queries = query.raw.split(","); + // Split search query by ",", while respecting angle bracket nesting. + // Since "<" is an alias for the Ord family of traits, it also uses + // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket. + // + // tokenizeQuery("A, D") == ["A", "D"] + // tokenizeQuery("A)/g; + var ret = []; + var start = 0; + for (i = 0; i < l; ++i) { + switch (raw[i]) { + case "<": + nextAngle.lastIndex = i + 1; + matched = nextAngle.exec(raw); + if (matched && matched[1] === '>') { + depth += 1; + } + break; + case ">": + if (depth > 0) { + depth -= 1; + } + break; + case ",": + if (depth === 0) { + ret.push(raw.substring(start, i)); + start = i + 1; + } + break; + } + } + if (start !== i) { + ret.push(raw.substring(start, i)); + } + return ret; + } + + var queries = tokenizeQuery(query.raw); var results = { "in_args": [], "returned": [], @@ -1242,7 +1280,7 @@ window.initSearch = function(rawSearchIndex) { } var filterCrates = getFilterCrates(); - showResults(execSearch(query, index, filterCrates)); + showResults(execSearch(query, index, filterCrates), params.go_to_first); } function buildIndex(rawSearchIndex) { @@ -1442,6 +1480,10 @@ window.initSearch = function(rawSearchIndex) { if (selectCrate) { selectCrate.onchange = function() { updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value); + // In case you "cut" the entry from the search input, then change the crate filter + // before paste back the previous search, you get the old search results without + // the filter. To prevent this, we need to remove the previous results. + currentResults = null; search(undefined, true); }; } diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/js/settings.js similarity index 100% rename from src/librustdoc/html/static/settings.js rename to src/librustdoc/html/static/js/settings.js diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/js/source-script.js similarity index 100% rename from src/librustdoc/html/static/source-script.js rename to src/librustdoc/html/static/js/source-script.js diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/js/storage.js similarity index 97% rename from src/librustdoc/html/static/storage.js rename to src/librustdoc/html/static/js/storage.js index 2eaa81a97d..78ed17e689 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -22,6 +22,8 @@ function getSettingValue(settingName) { return current; } if (settingsDataset !== null) { + // See the comment for `default_settings.into_iter()` etc. in + // `Options::from_matches` in `librustdoc/config.rs`. var def = settingsDataset[settingName.replace(/-/g,'_')]; if (def !== undefined) { return def; diff --git a/src/librustdoc/html/static/normalize.css b/src/librustdoc/html/static/normalize.css deleted file mode 100644 index 0e04262791..0000000000 --- a/src/librustdoc/html/static/normalize.css +++ /dev/null @@ -1,2 +0,0 @@ -/* ignore-tidy-linelength */ -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} diff --git a/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular-LICENSE.txt b/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular-LICENSE.txt deleted file mode 100644 index 922d5fdc18..0000000000 --- a/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular-LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular.woff b/src/librustdoc/html/static/noto-sans-kr-v13-korean-regular.woff deleted file mode 100644 index 01d6b6b54664c35f8180f7c245514d22751f9307..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287068 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

ff0{w-vm$aC<^ll-;r!22LyG(71$pSamDnpqF% z#50o#v$G3}(P{`R6}-#i@~Q-*$GFSg<7aRfdz@>8d=39pYJ_S`iBkzR3APD2 zAqUpPo+PhOREU-2${h)38Ip~{6KD&NCG(QWA*{=ySrjE=l9LH5P*x-h<|TTP?+Nfk zxyTD#L}-LtLS9i1xRsKU^@-agsZggp3ks%qO)So^&a}=v2l8WE3GXBbqBF?O^mpGO zyvUy22^7Q%;(4Ln_^-&$zwY1;AjaYo(GG|Y{*C1)$|O!Eeixi5RuyPM4WpAuQ!-ID zQdSCE#Vnwf#wxBCx(c7hEyz&%D!mn#K#{?aVVJcjj$~3UDykRfpiGdZ0H@ecdW1L= z91=~y6jD-(QC^4MK^?+OAQXNGEf;1%EiZ_=3A>3r3fG2V(=SmjVJ>kli58X>u#4J7 ztqWJ!DQ*-#iC)HXOIBD_6f2Gv$RnSzE@@RnE2S6FOX!7nLb>6b`7H%kl!ti1KO� zE#XwOD_s}y3;70C74(XK256Hn5mflkP0e3~9EBW(9Z|FZwOCvB3&Ti63rCB|2+9cC z5VxRP*1Bp_6uOC>$F1Ph608%pu(s$H9u~%8tdq7_S>A`VA=)v8>OF=AQ}GI(g8o~O zD{_rri}(D%CvyEABzSTP^Z8IB)R|{HHs1_{e#Z6V^XIHMiO-@@&bi=Rop~0ZAVm;y z4>I={v4yp!!cs8iRN0RG!>P-_gmw+9#;n7sI~Nqxv4q$+Vkx2~hPXva*2b~$I3V~V#jX2%+MRUfH}g?2sh3P@Pt0%VcZFRb)dayU^G?=GXqMKYt)T0<4-ea zbRL<&qj9MDXgG^r7Ow$YnQpL;eAKKltAT0si;ab2$6Eaej}5COXq#@}i_}AO$7!S) z-bQ~nS>5UDhYy#?Q{(;P@=uXhqed^zz-}ML3Z6s@(DgUGw=&-cI&2ApE_3p&Py?_4{}0G5VMP z%Y_Nt5OxSNxRGqc9n;$gH_8cYWD(O0_yP1cGNPy;3-CJ9Tyg*xC^#Z#W*-=69kC-p zAQ&h*@=LTek}8gTtClKFkrzxALfM;rl|We-2iu#7d_)L)i(W!e3;j@I>K|p3)Uuh2p|4kbEL1 z3IpAc(d4x84ap&?C|5$i5%+ST6exVy_7EZ*$%Xedr(;NnuJ1z#;o3VG08jk*^aD z!C{~tggj-ve;aUmaMVta}@#Nhph0WP6XKXCATD5 zFN>yxa`FoYByu2@>)~bTR%OLnCRw#bT3pj8R{X(7&z6aj(T6Q91!mZE40F_3>JpZ< z#cn*>^~J5C*_|zGGCC6LPsNwqUvUT5W*_@A0y;0paF<^5SDcr4Rsso6)m8?w;gH-@ z<%1;LE2aC^+?fkj(7AbwTv;My_rJHawm7rP)+l%BSpU_8cer$ya||8Hy!X zyl@N4srV@7Ck5-}AGk#vNO}+!-VuD)=Z{f+A0MVm>V^LXKD;GafI`HP4nFh`BYkh`F1 zaW^%MbxOL^HKix)i_OS?!R_z(9<-6RXBfd?!4Fa}exQBhj6@iUZxS;^bXOjvGBHOb zvS6A`R}9C<8$Otd|22|z8ObrRg*K63Vb6C;#rl`!)P+Sb`qC;ZX*3{9j(TSR@zpgt zq)L8etV~88Yq9`F?qL!|r!vC099#KEmao6%Om<_!6{F0-SX|EBlxd%tB{*X(HnTeO zHAky=O4?)v&K$=4pV^b~Q3hi5P}3ec4n)H(d$xAtDSCExqn6nuWLvk%xnLW= zp$`29-CA!N9{q)+$*8aUNJDdup52;T#1{Mo{w%)E)0Bk+rME%@L!K|jTK;sPBz(@U zp&Y#5p`t%LnloqEAPQ%VGifZzGZ*&E{HtnBzHOYx{)?MDD?pT=BAL@OLghB+ZQ_(H zXS|@unc!F#``CojKM@Az&uUWizdx)AlkU3PQho$?FdcxA)ID8K!G2iiUMIGA8zbH9 z+17g9SwI*R$D7kWA(|F>b~bYRy5l(}+ADwy4a%6(1K)`w0@}iVvPbsn6X3`E%yHM3 z0)fR#d1!=ypSPcw2#x1GuuqAvaCqyT*RnU>2yIuX7|)!?Ry!AX44xOi_o}AfvOnyj zFWG%DHF+tSCP|YJoIpYJSIjE%4(QQA6>A#Dj#T?ss1WK*@ePky50#gclSfp$qH#e9 z2HCMET7UIpcijG?_O|MwoXK|0{xsV5nP>LUhE})lV3*)F-0qgx_WQjb;kChiArgW6 zT_ZOE!~J-Y0?3PN?(FhQcO(P6kJQm5YVYQLbz*&{kFTH=bSYQLRgr3O4Y=7LC6D+Y zhQmdw^jGxpcHrLkyB>j^`g@Wr0-TrA;aU2R&4JnckF&9Qkq`M@4+cL5z%$#|>a7K* zKWkuSL9Ai%ZupBp=urSJI51G3tzEm&f4(YMtKHC#yUK1o+Gh8Dl-Ib6i77}7a>OW@ z`HKkl#AH_=9Gl6KFjy1|wSRXFmfgq^M&yZQD20d*mak8dB@E6qgLP1X>4SgJpUD`F zWC{~$bSyAt$;_0cSe}VGYF-4(H-0`bMr#PuY=o6rJ*9Ca2E}O8W+ar^4|e|$E5AR4 zPL|OEKu%u9Vug~tnaLY7KAWjKkwPb%Xd(?31c3xAZV4|84+%qb5j!R>nu26yb_P=h zXP5=Hc$V=MacVBBU>1hRLYiUJA7gLMZ)#529L91^*bJP(7qyn2fj6AfI`ulVIXv}f zWDjyb!^n{Lx{+}`8iYmLF$8Rf{$aLbdBNXtJ2*rCz0r`oN8LaXKZSAm!xDO5w@Z9xXY@<2akMSO9Z+M>NCdT<&km z&2YKs=ia~Sb_|E|)A#Ng6Qsxd>5iK`)tx_-rq^h9Ue2g?i{NdA4Bh9TGOGc`%CKYp(r^6#r#YZOOrJLUF?)#3Z*3h^4?$uRN`&fk43f=wXy zx*A`Ck_0AMD|kkyj4zo=*n?{YQ=*gjCtMb-iF^!CYzFnUf6Rt(CuqPMRp^#33W+jS z=oDOfn-ZqDCfu2sdZ5BblngwTU)7-~D`XvaNmX$t){79kc_x)U=CHO&zcG5)tMgPXtSG<8!|eGdzZ4!~hcRp%d(| z6|sB~=P-a5_V|*MW}g`~J@%*cJEW*%arBL|p|!7eY##N+yK-=R9_WFK5B_ZlK#D&$ z=iLEd1^lDzp4mkUe}?b2xk((LK-#H&8QE>e`^)*kuZpfFI|NeX2P|B1^$vc9X zuqx}MOVkGGGxLPrcm<_cHb#J{bZCa;iNBG5D3<&R)=7E@?aqoLf9i!dXZHBDX6l&1 zXRSY-wpV_yn$^rDOWl#n0{AV;2-nj$r@SG_Bbdcym0ChTypGp zJ&s1g5#J4Q5S>sj-wzI5Ly0T62N4BI=_RYgH=Iq?R@jl2B$u+PtSo*CEA2*!Qeewq z)|L`q`T>8Ks2Wow96S-I`liAbSM^U7P1!f^jMZ9S`96EycWGT|LwF1C47(y<{!`^F zxYD86hybpPRdtRtd4z|xbAdIE+#(CiGOgrK2s)GY*L-K5x}7$UrMIXK&82-y`=XKf zu`IXUNtTQT&KAaLT)71SU*&^+;WLl#zti)AZ{E*uBv1q(qn{&Cp#Lm3?0+);6x&bs z&tCiQ&)Sv`##jIoY{zhbCFl}TN4TJXZZI}zI^jv!oM;F?(NfHfZOC6D;`j(0;=f2e zQ5opQ7D(sfAJE7HlDrbiDC3wVw22c!Z$t|{V>RL<&{}Gyc8MrrSESBtWBC&Ncwls> z^o5l1MQl-*ly+j{1cykJ{$ggl)Xz$45|5l!dlh!V)A(*|OAf``!C_?BYnJjt_i);8 zmRv=(aZf}oD052U$IRS~C(s4n@LRwSOY>bJ`t)xubMbwKc;Hm9x&wXG;B@A57T`22 zFVMlsm__{w$*`5i6-**Mm}Mgk8?YKi9Uvs8m`*`Ra51{mk~HF0EN8IA%2<4f^Xf53 z##8bmzZu;bO#~R*qMfp_Fos?lW7^GvxKXwll`H#kgs`#*C5Bug#sHWn?uMMiNjq z=`QR{cdVXT8~nN6NjM9}1HExo4+~JjLAhLGL>_V3j~r(t#?ooVDXt3^O&yvX~ZbT;5U5hdDZvTog0a&R=90tR0Hu!_B(3`wMjR zv%7aV^cpT^>>B)zYDv|%y4n3~6m{p0pClaOPJ`LmRh!*Y(?0fC&NLw#iyd~Oxni5I zQ+h~O_`7+i&)Y8bf$ztE42FZ7c`J7J^zqB?$8scUdHIL-$@60N#&z-zZd~yd?0&Bg zv5@2)-ft!x=XKBR4P)qA-`o*0*m$}H|C8>9Kb#idez{jqY1i@8>FWyZ_8#ie-e%bI zr6HJlL7b2<;g7tx;>l-zv7I_r?zIKTkQk)jEay8|`*aPpqxaSyd9wN>fG^YeXN`poA|LO-AOB)=+v2WmcMaQb8Ad z6`Js^Kr946r#h?RmoaBorK*A{)=Ia+uvIN}7pP~hD=f(sT#>t-F2xspQNj_kb}V*8 ziPK>7SaM6NpiM_x#g+YZuI)dYa3imsX@OdBPivE3kDuR`8inHaTl9>dk?sszd&C>n(0UL;M^5ZR6)lVj%MBmS*tyu|4G=@ilg10pZX5YBRN? z`BnR&@N@hCypYlmv)1?9Hgrw@CreK2x9N%emo2aC#jfAV-ZG%lescBeQr+nHxUA+{a~D z7|&xycWIWHm<2Bz*Vq{422ab{+8B95cX_Tpk9={%Pdj#mo8XqhQnn^8_)_}jF!!fu ziLH61y@b4EmFN`9oGn_Ynh6L)pshDg}K&uFE$- z^jm>qATLBDe1>$QyoEV8QxYh=TBt&n57y`U5aH|#$8gR=O?;CK7%~J)>e4cy+(tn;fXV=M{W{I`SyLyW}pFZ3aN#OJ0 z%&~;#U7w=K)muEkmp`+-xfUuQ`4*pe$NJ$v;0XSGe{hig-UxXlyP(=Dj&!6TPL*^a z#y~WaP{p2?7eyfF4$dGSvL#;0Ty-1bLh?v^xf(JcDTIP*m#UEmcqLgUxdt4(kzSh! z(t-1u8)|_2na1789q@=?Ft#KZ4PwF%#xoj&lISxt=P8xNXiuMD z$M8>On8$EUu6o664Xkd&+#7Eqj$9h~kd5RU3)_%y8UxhH|FBR6k56ZO)_R~U`vl*>WDN`pf$EJ*yu#>ydSdmHLD0l&# zo@ZQ6U*Jtqjpjg2QJLDy9OW75vmITU_<0`Xn+MXt6lpp}hO%jPM2L;hVviP;)5e+K zdZwuwjpLo9yg}C(%)I%qx0nwSv8x;JOS5Y=QU%F{+Ftb^5x2#dRtxAj zG}}>a{Gtuc1umjb6l>ToXL$nfkNAr|b$6 zL)>v?Oc8;=$L=>!g?qS=CXrZho(;|q;|811ak8hIXyMk6--6`?pbY->MackD4*5Jl z3PbqFg|ZqInDWF6j7C&9mePQ|nw?oNv#*(iTr19b-fJO*!2eeCxO z$h;hbeY*p8Fg8#7a=lG6lIPQ6T$$^VPesjvGe^ho2yIxk7{=lVd4juoH|37=(4Nzr zubG}@T>f%A$2)%GAYk7Z@*vdy#+)6r;mztRZs)C=+^6HE8cu%Y^_*NB=Vdw4g2>C= z^Tf)dNKy&Pi8>%nZcfjsKUg7rCjIkw%tmG#`c6M#C+NcjwL_&LBFGzcT@h1i&nzm3 zGD~D0B8r5vcibQC=-naAx6X`)Om7_ET%kAiPzPzJ`1LD+ zK<~vVF@NjjHQNB?6|e6a_-pF09>pJ_LKG}@Oi4;16}Ku$!*rK2*byrS?F&$VN{lwy z&v6ho!r?Pf5IV0xoYu2vder>iR{bXbMtp`tc(4Zgp<^1C;G)lv% zTY0C-E1kwuv#6U*t3I{mc#Ty`&afN;sM8;v-ICA!{`?uY%iXM=_zd9%A7>HGdp}s# z(?>Ym(%X(dOs3o+e9cQX(0J`h`}P7$Q5Wn4u0`t*6f#3|mF&+&{SYFuf^Jni(NDFh za}K2z&_kQ39*|JmESHv3J?){+S40Vj#aDGT;8aB!~dDaN>$zFTbEU+ zYb|${ttYFMx1Ft5U!gDCRCp<<`v1X(RSTZA=2V3Hu9!Dv^Qs?_St?1&(p6iuw|>)^ zR2j3SB~av?Wjy6S-Q*99L!^=a;gSrXT}M5UQK zQ{kfF=2uVuzTDc?DYZ3I{m$w3U4gH%M54hLUS(0|6|3UF@`zu(jj&Xn`{tvzQ+SqL z>}RsXpz|rRU<(Cdn*7{z+Js)#g?Id93^ ztncILA@ui&+RmQqc+-2`{|eWS2U;gVxS&;d*DACR0$QjVEhq>r2%ieHUIlWy7_nP} z==Wb?$0T7#sJALzc4kwJI#y+R7KZXtk`o&7v~Q!)QJMWS22Ju;5A4R2O>`e&MG3&c08(5i~{D`Z1(s9%YOs$EEyL|DL!fP zw2-ooY5s50!d(*r0c1$Ta`eb|o+7i~dAqUSTZLI7fdcD&n}iGlVT1n2E@LE%kcH~T zptd$aXtCYA^g-X+ujHA)8xhl0{gyaR(Xu0#0@+82kqtq=*E$lqp|3)?uwpi$Sfjg{ zSD^ZHPstg^AX|bmY(7G4?TnEb*{0Is4PQ@i7?;nF@ZC>?D;J9U>yE;MAH+CgdX2KA z*0CV_4UV~WmMua&4`fdInyll2%VU-)$W55RL_{HvhA`_gBY_LK z5U?UwI=LAP91`=6DV??y&ldK)EuKw@4n|h`^42G?S9Jy_?Le~GH8|eMquHw*RSs5Fjv-Oe2hH zna{9dnpkPE53EqyKH!>+*Vb0!Su`4kF09J04Q)tk1yj5UHN)^Mg`XRqu|(TUAoJ?Q zvUB5b$_$h?F7P7p>2h=T@!HGOR~R{TE`zI$=w2x~3GDw~o>I+;uoG*8w} zU&$=6M7c|@d{A_Lbed>N{-apxkxxCsG~bvg9J$EZ^m&i)S_^@|PuyMBj=2y@Wz&f4 zBtnpapoL&iHF8)@7-YIlR3@<&a&1dcCa;hyX*Q=|W6(d8E8J)XP7~OjxS=(q^xmk= zR0Z-DQjSh=T~Z>%b#rcl%o5ss@#v#49ztHuCu8=N<&)v<7_AiRFIXOHCvaka*DlRK z)MjX}xT*9{UE#={83h87*K%j5Ktb>nK)eVgw7U?cOK6D(ElhvjA3DU17jW$#p$Pn_ zzTS$X#i-z7-RX}pA4wPZ3cvlO!{gPxTD^;j&OY!_`Q!Nk=6kC2EQtXD# zIB}i$0ggLT9-bI`X;nVdEIW({=)*b;pT9yY;6t&m>~&JBaHSu=4l+m0jAbPWzc6lI zoCl2~=*|*Jo4n8Eb92!i|M`;euVkjnxdeSl`+e`HKJ7_AGh&}@22qfd0KahZQFaG* zrc{+}#6tJPg$|&Qc+pJq6oM5*jD!N+p#h?4eNUBxv+}9GB++eJ26?p@IO|-lwv&qz zcsR87B)e36yDcrLDOOa-&+JUjNuhF4+YU#CHC>OUV5ff~`zT9>W7U#=Cxyn%EO!br zdjTE-F=7;P@DB=q_fh{12|pxZ=r20Xq>R)AHzJ!mr8|uJ&m(?fRC+-w==i=@vt!&D zGw{eWaS%wB6V#YXyAHUR_kJ}u$h5vBEj-B+00G9~s6LPZaNQ#b7FL*knjMicbX`6T zia=MZQPjHjAel_93(Tgb1S@Y=@ zR?W!;1~yuPzHZJmzkkF%nYy(6T-?)okIy?s&=oe%MGhR;4sEXHMjP{i+enQqlmi^8 zboFG=e6)+M!)z}-sF4QEZ>@h8xM?qa3l*HX!>LDSwx=wgRtI6Vu2T=q%!mmia2M=k4vV+?UcS0< zxU9C@EA&`It81;&C&#QU|3$mIlkLz#k|TgjLwv-Ukvy4$GxmQ#~snKM}S$P#~R$skf5 zSAO*u`Cog$LJ(FC8-qp0>?br!Mi(&ZGv;(9Q5>|PJlqf;`4zOdNFrBZJc)E&yFLv= zILzU(BRnj|Iybg-kyq$#n4>OoIp5T5Al7g6sYv>%7zS)a7Tb^_a>fdcDyz`f++9t$ez}K1 z&Kc}emYz!tXNTs(Wzm9Mry(zWmHgtL>*ooh)iF84V z12Hjf#C}B0Bp~#^Bj-!ZR!M$?q&h90(|S!%Geb9%N=SAG3`Zsvc-`6{_Wr_w90@uu zaCF7A6KbnK9v-wV0T*&^ldLe!;V5_Kt@%11e+Qmf-ZXkAp>o@vS7)I2)s? zLMBo6M{qF3%=?}pPy%;B7T&c{48=nXHZcGTZ5|83{fe;r_bmwY2C|qywcda#C-_z~ z=S1C_flNPI;P@8-{_(mrY>&U>xzLpp6yZ&xRno}qf^T&V=FjtQH-?USh?g8`+WRwo zbuB2EN6U72OF|hT$AU|D9474&sHlctG5!$9=I-gBzs;Ku+aW8ng>GG$nns+s;4Xy) z0zp54(rO$zBZL{)l?JrVP!aU`_6O@$ORL-*1S1b;Y+~{d346<%+gjfbxdkE%NeXpV zFPLc2^IlUII9D06vHzq4(4UIs*Op#O5LY^t;^ip!yb-MZfgbTQAHL@MV`J=Acfs;e zSl_DY0~z{ZW$}OgqHd=&EsN|GP1b}IfygY{Or}U)t$;V4ZL9VE99lnLba-zpNc=!w z>XT3vCi2e+&?~{B&rB5Ph8{BBBeJb4v+rOwe>k&PJsF$>r6#QrksIPc&J@95a{luN zO%kc1TCI2u8C4Fx_#doppaUqOh+h)nAc4Bx+eINzdv|X9}BHP z*0g*gGJ1M!@^wU3H4J`>Iz*QgnHfi9;fSI&hWnqi8h; z_tf(8Y^M>)nyD}*D_my}8jNq7a{Lk%p0uU=&7X^R$!(%5cmj9ozZ68`ZK;YBNNn6> zrcz7myJX4Fi9+#38zT6H41cJoT^f|0@qET}gRbGlsr6FX7S{|baBHA>XHp6_W>$tZ za%+`%rSrC2N4Wh+ZY1Q?0u%;#XzQMQF5VH_7MAaXtlxO#=oy*}Vw&lQR(1O={Xq zjQM-9QKFp0*&PD@4SbF{1iBy5uR%R=7_vLX41JvoKMm<2pE}w^pp__MR4(5G{;2x# zDw}jHz0IpCV^W&@G>m2a>in)_n0nT+Ok^=}mrl{U174|lk7uw#{V?2k_{I$W5FgKm z;54pA#BcpmuFcha-UkT4z!;Dx0r6|V+%?H1_X@@}q^GX`lGYQPZ{zSsM!$3eL14Io znkE*ihXDfj>IL-)tB%9M>Jce3$~^oGYLB?k`E?h?rH*uIh4&8s%+XPsFkJ`au~8n{ z=(V1N55(}*DDH4K8E~TK+au!1i`Xzp6Zev>ZV;q|6$o2}W3$AB_VnJibff%ULB#%M z3qvWH7=yO|fvMs4ybgc4PMuY%o=*hV+}TI{!|WahsaJ;|5YEzj5WD^n&}p9QEWG9^zU4b9#5;#ktH zQV(ODn@BoiRwX?IU#k?WWVEp>l(~hf0!aY^i$oh^L+ch$gp`xDH?U65$Q$J|5q3tc zAg(`l(BvzJpB^+aSy|M0Ev>Z|>+r=dhD%eF4>dR054Hxv8>ix;d{qxwQ0LzXm{NBk+VtSho^*4`M^w^@%ck2Da zeYbft8?4v?G_3JTJyB^iZdmf9p`sNu_wT#$#FZ-(o$tL+<~VNpQFJLCflku%1=aSh zipny_4H>QYafAk`bFe;R2%#}|WLq(>u|RqcVtHSFBcCP_f5s@Y#ta@8`s_&CzK7Sv z;PpeqnkRW^Di+;Khj>9UV1XJ*c%B>D4|_ns6-KjaVM`qSiaqYa?|%R%K-j;MF8sNl zpfmMIVW=M^4BS8ocO0a4SW_{PLWF=$Aj)5c|nON9Ri>|BSHl z@M^40FDzpB%_5N6t3V1J#L5Idh>1*!)TiiLY;kx)4rkS*NySO=zwExi(x-mAOVIVF zqN9(5icKwD)_KWyllt>3g1&-xgYXfO)9v8ZKLML3e2B%l^?iHilRq`nw6C$Imo{Cj z6cwapwUy>X24zc%ZW8Hk<|zhZM6F%FMB{;XPY`=6tSNMp$kEqpwUPbR97hR0ow`tj0C}*B+x+R}DPGEdkzmE;5evy_sA0Qx^rmQA z42jVd(KXRk)1g5QiJ*0`ms5PsOP0m)VI2nS9w_>?@=V3q8cpTp|k?IKw zkzlKemf)?iUA#_475^}laMA;~*4<`kdiT_|iaO3;za>enuqPL}`5{Gi#c6Y05&haV z(pC3>#6mz1_Z&!YbMpPi9pdUeX+#OHkGVD7qFUL zzjvdKX!Ql3(pU@^4lz;QYjls9uNSS}vBgvpC_h-{wOwsh%Hx9QMD8odV@k`fwdb=o z*@VN^ph$l)Jz(Pae6iTxZp&JCw!()fy_%AcCZ-b`OXoeo5ptVb0%`{%Ki6|WfZUj2 za{t?%oEBk1?i|%3=)^+qTqdRE4Ho)coN|w0q*Cis5ZBVbL9sVeOVRr$n>XTO8Ezb<~O_5Yr5M>@#nc8CX-SU-4$?+WiW+O?x zeZ)rWJy0NzMjnZX5G`}l)peI(L(XZ1s#dp1rTT|(;UO*U0|C?1O9W>Y?kE-)6`f1Y zWP5Z<%U5?2S2NEQR*EWj6oq6+I=URnbypH}Z?dn;ITx{$%Z}j9tZtu!-5q@*WOIy* zjmYL#*Q>sgHLD0XRK=_^yY=+Rt%lByTN@THG&5U0_DlzBt2!%rupJ}Zb_^eD!Kexu zb%IePT1}N)#mF+uKEgiK8mB;LRYX~MnI>4O%q77HeIU?68!%Xf46MO`{P!S) zKBkE~ZA|`;HwsPMIUJ0}4KkNTB}nM@x(j>n+ji5PvW2pR%#{Wr$;N1~feSUff)>zd<-Iv znB41V60C(uu*x$7%|ok*^@8!L5@+7Y=gh~dN_nH9>p6T@MN2`J2eUG}a~tz`SBnOU zd&|3u_z(v&JJlD1ScdYvr$~SV^A=)#CcRh$0ya-UeRbDg?>f4lKkv|+^22Ira_Yj>WKoq{f|Fz^S&T@g`??_G?2hoQQL$TCZ05yHJkWqLK4{1m zFQw20F02BKD|pfx(5~Ub1}=>0zFqU^u~ChlzTqa#CC!_<*a`)^%{f)o89C+U8D3V_ zo4xE<;e|GiYFkUm-g0hC8@dn4>rpbgzYg0Vr4>>H@Mx4`J_fFnVZcJ++=hC%e~Skf z+WB?d1_mnY<&SnR+S(q7hBuZiF|+oy+bk*cB(kogrDTgM(|j!q*Q`VTKtfi|tXFe8 z5)`B`t5yjT?^xZT-+?oy$2@E=zgy>$Z5PkdoHQ{lqf*pqEY&l04s`XA6nGKWuB2T` z6PI2Oa(8ywtj9Xz^3tR7AX|HnKnG{fD|sQTqYq)9UgvX1{P`5TTYd`8lQEjq?n9Jp zVceeNdpq?&Pvj{2{Y1R2GO)DX?u{!FKGMx z-4d*=EP03rmK}Vs#D?nN49v+bVL`F>KPfsr7YNZdZcQ!xR>Mob1NK;`3l8RIeeLii ze7UksLu2JS^dJ^cZq zXmJE6mxEI)xIc@JRDu=lod0cldj^&DaVk?!(vjS3*&$*B8HQ^nFw~v z?Q$bX(h_W=An{WWTDZ0@A&ywx~48cF5Z$tFXH;;v`gvYlC(f~mJUyp2ZO{}fCW4% z3%0fM3>u4uVAj$5Q#2Hza;){3&ZeY2)|rlR#cH2+#d$25OyvDn%9w=DX6bh@@732l95E+=GnIbf?dp#)N z%3Hkb+e~UR)h^Y>f77H|)HDj_R`8B+fAAMl`Xy0R?lq)nMG2=-b**Pxl-@PKm3sQs zLW=$$Ag*JYi*8bZHi7-i#Pq93Jm!Mgn}Npz5%AzE;9(iY&CK=7Noi@JmjVL9!uOe`I$*6BsVyEa+dKmj*v7Iz_Z)fIro?S+(IPQ2MeJDFW*aCW7IfoSw6*oQ4X-g3iM$1QC3#nh{kFiPlnbga(Pj49;T6e$Bb@V!j~T7;$%LiA!b1-ccu zlEPn3>69=ae2bsCK{z%48lvDkVlIgk(Rbr?kASBX0Tbef&%p$GcsWIn8ZG0vX4zi0aSu^;H1TSxm`0VU zS`Wo??keD6pOuXVTGcF!zArgbkeL8)F|2BXv8`!RQ(5l)pYA-!TS0S0EmPL}@deeh$a zCQ0uIK?m68u3JbHTN_-_*+Ho#FDf=-S57BJ;BN*@9s>cBYRe)#vLvW`bQuv^8q?Sz zqSGM|RWlY2NqOEZ^x%hv%MS6Tt3}9I6H#cAL?|ylVdJGUdBtcUOtaZQj1O&-rE5{R zCHMTxVfe$8Lf^?UKRf@Msh`pmQ^P4gL1gj_s{Spae z)lAyB%l-eAmH#R!rEouKQNQ8CqINe(yW!hN9Bt4zJXW{Ume=i;z{C!i4@(g523pD@ z75H{OIXsGyRtjGUfNtEZHr3P-F|6=J>>ck2SxA@Cv!@_@6hD~$h%VvQ#2Tx%bqup$ zghI9gulG$3@I`d&pivk40dJ^9)@;;*)v0v*DeQg-srTq02#;mj`!bt5S*!e;j?cuMH?CYS zWj8kx!5*Gb*5diAyMf%t!aMRv{NW21MWCVo28r}doL9R`?u1zvYl&CrWBpk=Qf`5Q z+SHrk!6bvVhgcN3b($IaQbY&MY1=d;p|h@ZGS+Ta8tya~fqoKuD2Q-B;Tj(#v9dSZ zVkd?uIKsR?-O$o4zF%UB2zf$Z!7>$gke2JyvzOFn96= z3N0U=0pCTl?wUm7u1n+4td61ie^p|l5^juz|8w-(ADW*@;HPE-3Ms+&Oimny zXjnijAU_krWE^-~fq#7HBupHurM)u+g1Nqr3h;NJ(pY)01jqJpygR&G1JLl857Xf= z^Ji_(>+golhKq_SDj(ey;{qBgTw`s%e*WvZ4#qNvu2^WXc>^RfM$iE zwiF0)vguQf4X|s-sGhzP7fjKeaX(RXe%#M}1f8p=N5Y*ql@v}d>n+b$is`<%mHtMW z``LzlMD^kGndxFoQ)xuuD%yFjTUUPF&UI^2fw3(Vw63I(KKG8v#isdw+%$nR#?!mv zg-<>FR`2_q?)#CVKiuQ`nclSKfg@!U-Bm-4$^9S~J42qmn0n7x_U?O5-@)WB)wrh# zR4F#stTvbh(|Md8OyhI=Wt&VW_!||^qtM@I)^vQ#j_tIG;C6T6V_3xy^gN~0VG5)$ z@J-9W^ZcwGfhiKS8x;}J=|2@#i0m-**R&EoMb+DC#fB8Vm)s3&@-CI!>Llm@_w-Hc ziELNPix#^mtxHBZj;z@#0*gCZ&A9uVOATgWHxv=)H=lN~6QOU`FH@J-$=YO7bSWU4YXkpOy!=?HG2 zG8a02Y&+YJ&O$Ua_K$jyC=#jQ?-;ZLRFEo!vUKL@9tN$Q{~k=iZ1@eVWvfT~Ng>>b z?b7c7vriaS@f_*~ApIU438k^j)7Ij_0(N;pm(75^60g!WY?Gpm?BhN#4E)U*KjEZff49;2*axQedl`c_k?~D=;Bo|Nesq_Op$txi_*U zA%%plvzzfEk?~cZLJ21SB;^+T;}Qj-u1t>|mF=>5YnYdJ9pz==B`3kc$0?FNQ)G=% z_|#FJ7T%bm3^XB$Cxs(?&;d=R`DXRqd*;=K1{0C7 zR-+selrJ>&y%LvXhj?6Pt1F2zPtzO&d|O7-r%pj@wz8}D5_F4wi{L=q!JRurF$ZH0 z#YznDSf+ia0Ij+*G6N=yg*}{m4@~JXtycoUZP01}uLimd1e`i^8*)LR9u=5^0tq`% zF4F+>$)Dj1tlm8oNK}&az55VI93^+7F9kbX09_V)?+v7gqErP-tg#pDEhhFD(`>QD zo_1qm)F>A09gW5UY{3dFEMV`wJn!ZV-v7*EZu#5S(!kmGeNI2;ITK5pznXVe#I~FU zN;q!3{rLj8p}qZS0)K6C=Up|anLF|LYj!nPj^tNO4k`Pfe3VzU^5bFEs=Ypy#6Ob! zM7q_}Rj1GkiQ>7IASUaz3&kkec${cSwE7FV5L*h>zNpS0tLqamix0?ZUp}LTW-QUv zz6to){V3FZZKur>w+qqP;f1P#$?Rag7UNO6B+^%F5fm=f?nj>FJuvt{w}KrRmd#fK zH%DhA7K}M?Hh{bi_k-uNAV1V*kYuM9Hej?Sg2VKo!dl&gDpuULdZLvRc@8gEpn)D} zrTYn}5-HUjM&;`E3ZB2U`;3(NDT@L{^Duqte%Wzx>8}p+;^mviT-kjzdsBYk=E!4- zc_R;>4dZ%?F-p zx5ArK^?1Bw{X=ZH#fEib!+ynZ4Yx$9O+TcM6DRq@+O`Bcipo@2SfCza@%uCkv2mKJ zGxU*%<)YlB8*ZAvw0E49Fh7B{IE1`K8cHzOM!WP>>|u-mJL*_ai+vQIFY4ucVJ!xX zHHm51qMuC=GpLq6jnc&B9wwL`nox~(XH`AdI%X8zLFW=`zFPOS2zd187MYK{kJF41hOrcc73sLa~f5^Rh!(f+`I$wR|@ zK5D@1nnzoX$u|p^{rrTrXgjOZf({Hbc%JxpiAD_(JIaJP-W1B;hDPaAa8^ulYgML` zCmIyuy+X9*WQh``oO}^d!@;%d_X}R|d&G>G`O$1p2u5N99nv=_yfn&p3YYzQ-~7vj z{GG?LHeCta+~HW4ywQiw1yH%eAHFv7(rkm-&^5@Kz>#WXz-JVyx%d>1v@#?~wHsiY zj>)&3%YV7c#z#yq6LqhOx{Kuvv(YdFVZ4ow8|HJ=%JdClU%Da77v8&^e_4G}2HKxN zcSve+0tQf3>Q9@G$hQiX{c_Lzxh-l&=lLDk9Z!TO?rHgSFH%CoD!7+nBS(A&-Rl*P z>qgaN_q3r__6W}JHQD}XQuw0q6sP#^9Ccg?KEpE&T_tr=34WvvNl4+)ccm>ys% ze!k5@I?Rk)(3yq&P$H_$#eVxiN^)k-|! z+ZCj?sny#g1h=uJ!lN(<6~f3@ZZd$`iQF^zXo_Rs@hh7gfty25v@0G`wC{vtbJ3>o zjLrokjCLoT;CA<%Vc)-iR~NWLI7D4GbBN1Zqvlkp7S*I$s8kEh(E^p8qZVpXrRUVb z+}Rt_jp#bHT6Q3bd|F<4{`AIGFzpc;R!`Bs&`Yck85%yf>KO@`mn=~|@+1#xG(31u zA}Xdoym|k6@|(90DnP8NGWiZ9mEQRv_;}Kl^kZ3Dt_E&tbu#hJ=-cf7E!Vbm zIMVe}>hbIVDt~$iRLCr2tj%Avyx+p9o)jy^SPipmlDdID$NOQ-_r8di)RUMqMWUdZ zyy1)r-kpSZ(;i*g_d0NY$fFok9=C_V8t$t37(tA6!sh8}!1>wJRZfc+dPqqUeyoCr@U`hzC@*nb!`^s1alY&)I(OnTE9{72erM&b&gm9}%Nk~8~Q=d{0^fI?g z>RkkJCyL5JEq4C;JWR=FOPM8X*P`f%v?wNSaW6Mo1$1BW8>*Y?Vk>;!^Q&4;^J(8uQXw9r<-Y(Fo*M(k@2ph)lH(0%~OPP?1lJV zD?J*IH@fB&8ve;fbhEs;#tG!agCZ|iQ;{;k^a)K_L>(8ejSH|}U9!w!roWshmG7>& zzv}jS-)s@7=_hD(B1Y4Ccc{_Ba^K>K4f*&w|29Wxr%2Lfk(v5`MekKzo#=DYvUIuK zOr`mvoSd`VzUurM-vjiXhCma2k?+bAMG9V=_XM0c&KhFf#cO@{iq0Cx!JUEq*!EwX7{fPTh#%dyjnS((MU}t5OkfjX_dM-7 z>UCO#Yh{Tr%I@hJ!sZTf?bY5$MSn?hXb*IS-sY6x2j($5npln@;bp>9SFJ3eG9Cbu0$y>UiY!D~Rk7XKhr;4Z@u8)GHhKbL+ z31w?1mT|XPAfScmqYq2P%oJ}iU+Oq3aeh2sDXD^67;2-v`dA#UQAYfjL_cL-)Li`K zo@{k^vXvVUJbzcpjIQ&$E)En8!}N&<eJ?qZOh=GZ`AB%l>lr53dLppY9NrjPK@9Vq>3Fb2!yOEh)k!wmqmRcC_FS+f(T3{Q ziS~y!|Dqg+eRmFgY)^94T_@29k2TcAFElY8On#^yZQdTViJu?0*ca9R&1#v-m0Vr=^FuQ_;bR4bVMHWVQb(O+%)<#7 z%~47Ho83QUm$iM%?teHb8hoY=9JBL}6FYVtKD=X8pI&1|4>V)3cdPiMCXH=L*Kb&} z@7+zvZfT~L=%6LwGP|_4;nI%Q2Nr)cyMzXpnf}+yQ%{I5I5YJzI3>nJQ5&jrpXU?wF|2ZEAqqvLEB&w#Bmy3(dK6_#ss@K0^ZunHSw# zK-~|kyLntoI%**7mv{Fu@_X}t1`WlVspHa$N9{RvwqIn3(!+hqk3L#9+}Xt}I>Sj8xqyZ<%;@52tEQ;7@UBUC)d>{AWO; z^V5t}Ri7M39gcQey>TJC&nW#wR?_~!>VH4yMb5LUPxB)&R6XH=4J@xFVqb7!dx%Kt ztl=K(I}fT=;*V*l-c$;;%w#?qgu2nxQ0Bt%3};Q6$5OkRTsN%9{Ga9DK4L}A{cI0p zlz+shrJNbDH9cTFCb6Av@7}N`Tz%^vgyyS{U$A?M+^%_y3(*=hE8R%IdvOwZ45aep z-7ok^%GLB^7JhrM>HqomfH9M7T#OTJcWiG_59X^szfc&F_bPUFJq;!#+b9_tde~?K zH}CZ7CU<@m+2P5|HrgNa^OhJXvNTtH;UPvMBT7*p&ZDVfo<`5Owx6|^)tB>X&=Hv* zzcjw5Xm1=LPdf58)$(mnAek`8emv(hd%FG0oTGNNu?GgZCTk?H03uFSHIEu0vRc7| z5n6jtd+*nzgh*<=4H%96#;HZ_Qt+wk`P_=?|}$K`+pV(`1ZZuRx6DG^x&2u(JSlct~Ey2u;)v z(_6{4GX@*)ngf*Fz)kIsBwk6~b0T06_Ek6Waol97TMJNwZ{+h0+(bVsrRh!NdMAd! z<2m2T3)~cC+}e3KUMu|HmJJ zxroo*d=>FLp>V?Gsnw6GYwUUUx{n^&pBOt{+>`p|2=9~W@eS&y#`o@>YJ2oB-FDKf zeu%#cwfgby)3*QH=|6Vy=~3~${&m{VaRK+y#}lLSP|X1o)AJFiuhomX^!QQU<;Rcn zI@Yfj6;sc=N9^ECcu%5Avzj*|{~$8Mt2S!z-`>w)hT8N#Rr(>=4}q7l6dgSgkeiX8 zaTS#vUKF6fd5bTH8BB%iGWbwR?#^SGZbovfYuQU0&%^y+KMgXj$Jww99sS<|sK<=! zhf*|k08hXF2NT(UhO5V6!&ENcqt0GN6(%{=*JAV&jT3s`UQXzP+b0bl#y`v6jQ-x7 z|Lvo)`Z}H28F{%$C&J9CtC{f8(1E5>2kysJFg4$%&yBxIQ(MQ2wKh)V3YqAhWxN+{ za3S51mUAj+cYa!q7mgrN8$4n6=|8vbKDa+^WRITXMh-P&g?GCyNsXIibtx>!%DQ{6 zOLn+;Ytw%rE~Y~zdLM-DMAhL>F|D9q%GU9;Pn_dnC_ zM7l3ps+%5XVQ03DGxJLa_VHfviA&QG#K%^d7Equ@TI04)HbOZ6ojvgjR?;q z^*Dm;lKW9J&g_mku~)vgySJ^*c@J~(KJQ2B&!W9Z)7newVA?H@TQqj@I2N}*N>+cS zgYx3xBfl9}b@jh@CMMyN7K~dsc9HQGcVw=HR!^ywEI#q3Z|mS|V|&7hr&L_F-bUrb z=J{h`A>JuOqEkI2ei54usyl;r$-@^8Up#^(?Q17988}d8*xR*gB-8yQUaN+GJ$S(o zUaJztDeaBy{7aVoo>*>LGkG%_ln3v8{OU9q_-KtjaBoL3i`T^k>`4D+$!@b=F;Do( zyO!==vU{no{$9Qalyg>G_|~?DSEX8-K8FS-U|`+xpFtZDzgoRate;6K&<+muy|Sm8C>nmAjcl zjC^$Y;cpMD^gYmAbEPT`B>oSD<-2l>l?qNztZ+heqPu&mO3Vih!{6fHuZBtEt1O(fA( z+>27s(1OSAGaVfwlh4$kb(*MU(WmN@#as(B57A#d<8yvigk_@jc|OXHM$r|t=hFfD zXpPND*FQ-X4XL$WpAL(!t$I62jBr&fLwCGIM{YhsS<9cq3r!y&J{AMy$V81ClnaMU zDS9bu%kSt?E*Qt#=cAzP`1h{Ln!Z#_7fT~4mI@Fn(-LnKPzn`DltjOWC><1`Ucx_F zn}^gvi(z(1RU2?kHy9YaHwixJ*YgfM2|Q5mS`>UzjrUsh4>v?b1O;IQtYs?R%r;~; zyC~!fXmHj`d?R#?>QK3cREFSVl|vM<#~qJ~mxK?ibDPpMOtk3B5;4AyME;COb%zC~C&Op^t;+}R2Oes8yA$Lw z>CCI@?X8J&P=l}*#ZkMm4B7nh;x|O=cJF_hg=&%)atg4{uixgxA*y=o{3*2ik1wneXvAW_GnPu53?&n$XtNemJ% z`A#Pb4!T{q-hs9beD1z8gZ67^O9!c~g!wqAJ`Z2ZDgKNwAop(mgR2;DR(&#$K{86CwWyxQEY{P<^78)dpODz2f0P-Az3H9i9ct9P z6^(aL;pWvBFI!xp3g%eTZY&ZPj$IbaK3aqc36J5d;#9l(M z0rcDs>{EF?q3vXB@% zs@oA`X#TVSF@-R#H0?eWVv1BQP;U(}`g;^3g~u@&6+h8Usiw&lLzdd65EJ|0x?A0r z(pizfNR2L{jeYJ#L)Uj4=$Q{+_QJ6AQ)EFaSUVR11QGuH3}r_`4WHHkbl=Cu;FN~GHKZc^~c z+vlCGpt%B5tq91i)<6qLd|8nr3Zrht04o0$}a&aC$ z&PPR-GH9>cdbH8+XmNuJP#NzYEU?=ThSR%Ld2o1~S$ynGz8ym-k|HlxhcA4uyh0=* zJG>@eb4`<2L-}s^RH&~UGcrxQ_jh7^TZ}~in4Q8997e$u8Yiib5H?n#YOz#_D)tUOl6-T2R^GOUfoTo0 zqHYd7ay~$PK^0HNq7teFi2+oJ<-KBg58Tdc!18*qyvm$4?nH1LnBfm1ONEI2Op!+Riu{HWj-RMoFGomYp zro|;Run)>XQ@7{5oFa%lm%6lUd1#q#+Fn*!c%S-fP`ON7~>b2y>sbjvGP<3^j4^;GB{u>&a7n~crVAR6Yg@F*LSKGv3 zB-dBc-5sY|Ho915Wn1iV=)*!EUCA%HdKI4Ry1pE#+#D7gSL&(7^*d%Wt2O4?j~}($ zkAD~!%pb+~>(5`)=HZw(l?&?_Qo|XIa_p6>FJFgUCNJ{=tk*&%wR;GuloBTf*eO{S zAJQVtBCFBeNW!hRmAcPJ74{h%hF?X6Yi*sP+$r@TQkj-P{RN68~I`iWS4CVkm}fXtGtA8GlR$oF=L zOigbp;zUz9GD)Ldl!jfh;39GB-#ruUvxLf$M(1N^*^O=DmZlF9iDFPBwV|D8Bhx3| z*h%earzBn@DN%_~L`|Eh!}k8p_QsPckwMc+Cp^W+)^US`v|hgfO=1st8U~i$uEUp`n+B zdU3VDFZxRp`BBeA^qeC%4R1{W~-`t5~H8<_wY^Fmqk3sPLN)4Y({)^sX|dmdbx;iH`-c1z#HBaEL4J zs26E)S;z$$r53%59xi%WbcuuhHd|&`u)>11?x1hKf|i%Dll>4XKGV>WR!~a`bFe}y zvFINqUgsZsCW?Ppn4LDF!|v;xW~pb6XLUh4B!(&Y=0aYcBZqTHMTuB|dRlz{!)MPO zJ7lvT8XVY)7_UW1e5)2s>>^fY(F8eF zFK~Mz&JG?Uk?h^9!gd&bKTR#g5LciUhbc^Ynl~eVYTo2nj{x+8@)*$=6@=l`w}+wK zrF-S&?!D?dAzP-Kx1!4j3^G`M)jV9M)rH0_0 zgt8#I!?2(b^ZyQ_2y%7M+C@mzJca5~rG(%UDc6pjzP|N!;O`-)TV3maf@`9ZH3fCi zJP5he+#S&=7f{cRdKXaBFz!VzKD_$M7{E{6rai*vTG!NzXkbden3zgslCB#c-S7IDVoJUAP+PCNfR~fbBBoJzwN)KFaJCB0__NO`|*1RX0Yl* z?sEo-hQgttmR&CwhnmR}`E(;6l0FPR*sXZ?=?lM?1a4{bXXm1k2f0&7N4voXK0(Ng zapzT~x9%{0N}e2e6WH^Qhro|5xmy-V(bjGx zaJXR!7XrKuOYX5H80o6Yl{8mgIP&Y%d86q&H)r|im!YjYb|5Jw@MLcve1uActn0WS z^rEpE&bKQaT!=feVT@bCYdXw1I)@V2{3 ztXzOECG|uOIpoocM=c)1R3#QpgR0bsyCU%sDq^ZK`Ylya&|~>VR5vd;JAT2Kg`*Y) z;xqJOXBDTTJe%_1ZQ75@WHvwI{0RuFGnhZln7}qkV7sDq@P* zq2af%(wa`Td$ZEjirzN-YJb3J$%UepGwfPx)=`gF)W5_mo1RStqQI&zmQ-C#6Av^@ z3DZ|Px#_E}H(^Sm@758l~}3q+$de+G^^8F|BD7P5eVf?TgEP zDqX|b9D*g>nb3#MN_?_V_|or^XbgK_6NZNAQ=J$#%aoAW&2s;IQD*XaEXuhf<|#3k z)amK>$`qL14Y_-j(r}F*VK9c#?yeXbN`q<25oU>5`h2BRkA+RDs=Iy{GZpnac$sPjfqRQ--?B|FT)v$PStPYO~L)g|iEK)tTi zEuGDP)cVhSY*F#grE>jZlRS^Ek-3Jn|;#=Qxx?C zq;{l>Z0KP!#=*+Uj1JRhIx&=$$wK*?Cakqz6CR3M6ms9S#xT_x!oL2Lef=JJ)8t;; z*w;T;&>W4}*L;d9m#)&N31@#3Da)IhFu{t3M-;ulIlO2uBWJb7ds0NS)VfdITKs>k zlCSJIety%1z|EbGrCb?vkoUWy=$eQ7J-uOoWr!dR!^8ABPK@E;i={d6vHFWdC!)As zda6$!aCRpk-{2W|tzcHrT78ffHbP=Yh18)|lY)07B5)HbUOM?A@MJAi=!AeNygE?J z-zoSpsu=I*E^1g7rr&YmcUip)&lr=~Vt>L8`_++i^G?BM>ppW==JR{BmMgO{1&~4$ zx*I9`qfwcmm=UDDM6~`1mtuGqDRyX+w!MPe9v@y(7?c&!MQ#~apS*|Rv9j}zi<_@( zjmqqDecZlt#_l5RNw{|}NPT`mRMapnOkd(es;oZa(&=cyq--p)Keqa#Qz2U4L@PrF z8eFKp@wn?+=(czcHKnTLM`OBdPYA$z-VhPax(qapC|#kE7Pilxn4Px64AfX@84Y=s9rNw!dDGlOFXa(E7e>D!%{C$}@PG8kaR`kWW8c!j<2 z@*el6PpK})zC3-@!-)M)7tjpN4KLiMK!sf~SC}=-3e(p)G2XDJ4L5b>-_ht|FBTUR zb+5;L*SAI@9h!$+F52qGPqCzrdvA-!5#v)@E2&dGUWdv2eF&{hl-2znSR;Mah_p7; za9Ub&0JIJ8)n6#6GA-?V05#k|Rf@lQ;EOLrgoe~G{Yxh%aJF>KymS8Mc`UR$T+z&& z*mFzRa}N14GP6h@n%3X&+>hs3`?~lfh!&PM)5MhX`jnee2=|=xx>ffS*E03xMhluQ zNW%#31@yDh-HKsWd}qJuI>)W>fng1DIUuzeSfWwAx5WyRqP{^g4WncUKVz7tx=`7w z-%UVeeio1*$SSFCsOnVH6Y*%cDNJ8brgFz~sCITgv-L0{m;RM6FiZMM5yY-w+Ha9GRI?jLMr zeO3X+huA3l^|y)PHdM5F;v=3=`A{5Q z!X-Y@_&}k<)jWbW^QE#xo z`gkh7#RUCkqRf$9)m;CUX1ctiOet1yXgAqziY$h|?^^g~hC(&gp@1-4tRuF6Q$1J`oSjvrW;y7f5c zk~-~6X8Z0yMiYz)Qj0wx6z+%c2qPg%AY}f@80|KgmWquUO(3qmNPR@Uu{qIThnOw< zi63k?giTRzv-Lk1*6(zPq6qq&k4}!%XS4O|L^~~>t^bsoG^9$@GyEW%|LHS$A{^tm zO5vf8(A4KflYEEj)}>}21*avVK(PdH1-JN(>OR3cL4IPB?JhULJq|?WFDuyTP+zjZ zO@_e94zVVJrm?`(Nd0qn*iuAah0U6JkA2+IFzX?{)u(CU-RYrHTo`mFqPyHGu7Sae z_obAiozD_em96bFyWAY_DpERSV^}uU*dB1ROLf{xZW}q$!5M0V_eVqC5{EbvL7%a_ zNs;sMns!0_nsr>;XUmid~TedF5bg^`yM!{`%Te3^`AQ;t3MkFP+8A;X5 z_|==bQTeVls-rv&RbIU$-%Ls|`|)_hKzrU>M)$G$^#7O9&B4kb^{!B848K5oN;UAc zLFsTw;?YsVF1a5KETeYqtx&D&-?BSqVuk;2+^#fH`EOpwV|=ji(5$kmQvib9#IA~@ zIuKx$j7O(Ty=-`CM`L^1ze%3{|3mWHWA=ZNJf?21#06H~fRAu}F57eH-($UnG1h1ESRbN=4R??Ax+qcJj`Mdq z^Els;#p8UdG0rt(5|`pBTPGN~Ntk}ui58N&&utz*8e{S+o2@l%&}^&!YrKx3flMg> zzs75>d%W^n;m6Vc2lI8FXofqQjk^xLj~ebN`~FWRyl<0?C#y{O#fD^C1~|LBwxPEF z)vU)cxj`pg){qQ8;}z;`Z<;bp!{x&?Zp`q;`Y}?-r_kGtSQJ_&n zQqWMQiQZ6Xw7d02^OI(grQZ3x$Z{1Q=jNOIw)uv=ZN7RnCC>Wv{5=cmXTQi^#(kF~ z>YC)Ltkoptg-j8QR>R$Y{YZHgsV6WNqPYXtdfS1`b*s}eg`4g=chjA0G~L$RbQ^Qi zonbUx5n@9>tEXt|#0aO?9oJaCSitU2<@9P#Uz1`KUk2*F!gSuIFyetmM5*ye)yKZs zsGz46KiJ@H^K|tq@`9I}D(5&9x~gB&#CP<45eoH(lK4(!X*7>Mh{p#swMhIb`|+lf zYW&1ZPkiDOb&9;iI&pyS_NGfkt_Gp>yR6^CaDH$}o=L5#Iy0W3aXUE`Ru-czVvM31 zT{?qDH|-GDjnRZ&R;;u`;))sL6fKHEOH|#}4_2*6tPG_us81aFNctlzWz36QsEsL* zxQ(QwG3L6fXn{7yjyIunnTB36SLp()o=^GWUX;lw$h#Iyu)gA;jxR)|8yHv=#vO8p z;@)^XXl$RYT<&YK(G+ztHHb!){;a(aU$VEaCdxc0ziOg?!4>&D%+xirtL5SOYsL~Y z%l4A-+B#6hG5N;Vm+*d(d!b<;{-hKg)nEe+F*vm^C| z3XPWxXjQ~p zoDL6n*w`y?yW^PT9Z77@Wwb2Yd?)LtGkPBe|W#w-+08_!H_KXIS7A(|G`YV}oq-6hob8SLDSJ9?ube9!e{yS3G)2`h9nV zZAR;2aeg#9eiz4PbrBjPjI(B|v7Zcss?-t-6lgqXf3d$}ozoonw&15C^)4e?7;#l7 z&7xj$2I5^9&E4YO|AN>%qut(FeHpFX-cbekCuh3KE7uBwED?!vtM~>a4GZ4iwRrpa z%(P2^TRNPKzc#jb=N~y+E^m#_>Uw?bzRUoUcPHMv8|2s7f{EFfX2Uz23xf(#^Co&1 zMe&}&YV2b*wy|OEsxb^(!KG<8cm=CbfyO2oGiIH!c(mc(q?XPpT{6zpW}n?&!VMSi z7Y~bzYdehIH)E$aC6aF)8pO(=aXv-Eg=P{@s;9#v)H^3ey|4DxPA7+M&8`6agK7R{<(tDz)k-adaL z6VvQQy-ajMy^cOyj=TY|QFqy>>7g`@dc>iJq(8)0Y}7?Ist&0n(UcF;4A>kr=D&F- z7+bnpyDg@j*Qebu3h9eX{j%;MZe>aa&l_sx=F0j5baE#kQ)gCPrcph%85wbbqu0Wa;i+f1d=*(O#d}u$NdmajP_+b?SClE{ z462^p$Ll}@ni^ajOG>U^>+ghLNoo;q25im~HfM4uji$cw=qqu{n%2r>tP1D3bZe8J zk?y^IPvCUVL4DL?Xf_A+|R79;>lYV&Rq9R(LdBMIgIv} ztq6}ZZ*opspRl(k7h*-;BWHvo#KhS8U^jM0jiT~Id=w3!YVtphuRVP(h#nkZVt3l&qXI0?dt4adP)m7; zemlXGCuS!qf8O;CC(A;UXiq)$_ELC)#vhj;S1*yox8gLtQn(pPyefQbgO__;pDuw% z8BTFD1FhF6K2MB_qRA8@Z}?;F+3X;Ckbt#DXd99bb?dyBy`UYxbMf>|-&hl#>#H<9 z5)zH$UKVX^6t7s`D|)Pm&91?Um}iAA7ujg%GWNEb_eN9ndv2HfL!<6_Vqp|5G6bDo zlWB3g`v++@H8YYZDdK=3=+CrW)%*)s1-9m93;%0;t7C zs`nTbxU(&`!q4j7A-d&#>fRw-8KoA5CHB)ODNoFZVp?BA-uUObEPD`f<{J_l)*^+H zIv(IC_?^6a>C7!(-X<>54BjUAKMW0N#Hilc> zh0T}$yJMAT}*!&o$epu0uxXqubQGYhyP{z#W|6gpq1$C0rK5rlq)RfjUK-)PUl;xG%6ct3@lp*A;h{Rjha|X^T~ow8h=!Om=R&?=v^u z{qFz${64E~%FLNFXXZTT%y~|~xrF7vu+WbZzMP<+(&3O98* zqJApO^?&K+>+TKD%SpQ_)@DYG2`d@KuC%vL7)Z`R}=t*!hR+(uPf8_d0L4<)a|BiOh zI`@@BpMex50MCXZy6OQuI79(_xbBO+YxnbmGVsQGxHdoNC*bVBGvxQ;68YD1lEaa<>cQF?^KntAp!~95JeGEObp0NUR}O_;~X{gdNdHmb^{J;3zjf zE7F8~$G=eQBz40oYTCB_1IG--82+`wYid#;ozh6dWi2=w4CZavy=M1b%wfhHnwP}_ zruB!WkSra1hJ0UNpeA}gNPP}$_AfANr~$KkHZo?u&HULepc!kg;WBJ(6{P|HESf%R zTf{~OB2;=`7i(I-bIs1(MzsliIZUe|f2RSTH594pKobrBlT44!VMF+U(klNzH;b+} zpj*3tpc`(B(OJ~mPF3t%|AU^M(jUO7h9^KrqcwDd8z-M`c)$@zp3O10;pzI_Yj$CU zt;}?l=gNFqUtl0)s0LwiuP(UrWG=zcNWg58N&%#&m(zN|Qm`lv|GTG#r zsX`I^GLW|vT06F3k7gImJae_?^#x+rRHtgHdwGEx>uD^%0`yhl6zJ;%Sp!&U09Z#n z04tL|K)J1*s@eB=AXeksGzbt&maS9 zUbP%+4LV2fy~dQdguYWBOgD8smTfN>sGamZhuLfRpaFG0_1#b+qNc(UX&^7rX#uIKy&> znxrp&U;FzXM*dj%nNK~4VGs}lN+ZLcKc@P>P%AybyYMb%>cTS$+}VH*=B;JL@*pk5 ztz-LB3*AynNXmcc0T1nPov&q0N1J$8Gj)ZBaqGgNjas@d4y`?WMDuCi36(a6$;5;n zg@@^K`OVAYR7c-H1xtKx5dRez0>}D=NHdx;Uu6EMp@@q&$UFa@3x4_SCIKYI6-s!_ z=4K(hVFwIkI@o#k0vA#HMn^4@03g6%9T|M_H zt*E^CCkbhI3j%!yb)CpU1_@~4t>w!b<6hb7iQ~V>zh4du&as#3Zn5-E0g3@62(!I;_8ZmHQ=0l%U;}S~4StJw8^m7$8obh>mq>6v zl8rkR74=Qa5Z$!0QDxhf|G|WP0w%n~f*NVIPYl)HOto^(KC5@O85#PJ zasD2W$U*+`F;z01wzJ<5WPz#hIb3BAcik~2E3Y+`NBFvydhaKTm1K?3EtUc#7^>r=t-u&EJkZsIX z$-;K%)Pw4;ih;5HJi$e0)xRZjP^f}>8H6pxWq!iqPT0u-du#8a<}R87-u8TEQMQs~ zy_sXoP??$S)S0cJb9hBxwKHF=1o3Tdon8G!qK`y#%h(_u%S*~m%W-xx+rb5-&*)w3 zY+Dz#6vG*w3F*j7R{NB(zT|fHw_V+j>K?R(fg1`9g3sci7=_6(SrpecpJX?5;d0CGO)OU$uuCtQaVQ?V{Pg!zU{d0*mC(D>yz9nNyz1d(HV58c_Ro@l(tw{I&EOJnC ztNP-sjG|m6JV5F&v`Is%BEPt2;_ z+(DY{z@x@yJ++%@8NGwOav;TsWe-vMSS@qg`#P7XePwlkx=k5kVuN|CI#{GP7*UQ& z66H{^0=F3vq#I)55xm&!J^|ath*c31cE656!2yLI>*%7UB6}9*#BBh}{8-ug$a>9Y z%=8#$j5Ts@8&qm0Y*asYE24i8RTS>~G5r;!;}fW%V#rRQPC>^_aHl0^_bE(5cWjiY z9iKr(6zxP>VgZ||Y!r3NpVB@u58T3i?~;tX`Ah=s)EvaknreDv(&!9f6-&v8y+J0rvp5V9E{~4-E4`tk zcD|0K-rMe3uU;|cVP3=21U|oXg2EegIGmn&=P)%O|2q?-V>?Xb{;VO=f#j3^;uZHv z;{*J@r52Bb_9z6}gGJB~M1`N{S z?E-2n^R}C~@%pE4^;75*#c)EiF((hymOwtD{3RxbCb1ea`-!e9+bG0JRjwFMsKd;x zimqoeuP}$V@Z~khUkOH4L9*GB60g;|bfU@NGR65BK3#dKeL}MpEfVW78?DFdIB&$N zYLz0xz|x8{`A`SjeNhrzC7XP(-AkO*yzHh-6Oo@{8`%V93stlhpEDj;`Pq>1Q%U1?%vGJcicD>M%Y;Ve9w;7yYi@++=c(rI(LP+#nvnPrGQzCX@EO zu-k6F@;sZ`i6R8oOeeK)kdG^fCW)HmO)LiU$=2H!jen}~W^{;%PYPeq*w=78fr4X{ z_MbOd)*?|)12Cy0fe+TDL`Gq~Uzo*ur?1*&E`2)LeSHG6nV)VG6--Aj6 zU6h0Rf{3!`a#Y5{OE=Opv!Zgy3*>1uDtCPjL9lFy@wNnFBrCYX3r`q-E4wd`NQzz* z;A?nVLcv3nwx2g$-W(!y4%Xo(c~@PsIob*lqP(dyO`ud3rtunu$Fe^<^i(}d9 z&Z?EqWMvuZK8aZwQ)p_Cy3j?V#T7=iTbZKM;?i$l$Vb`~_L}>&)JqP#LWvDTo|>Ke>0JT<}2jK=Yb@H ze5t`KdC@_7&JXS|v37Kox|n!vniZt3aEa~!6)Jd*Fo}dyMAm(~`7%k_@X_GuITrq7 z34FW**B^}GBW24=t0UF;JG3%1$-JT< zwaf(m@MSuuUY0~!sXsjx-{A)OEJ)q!qEE$l&zfS9?Lcr4d>JylMcoo4aL&i3cqEvB z%V!MsWtp=1h1GG=_?z0_%qr-HCq;>^v6oQDK&5R$6K!icVr#Ca@c?X1l+|M$T}pqI zQ`OpvA`W<=TJm0<1^xh__mT~4`z0}rJJ%-*}um@bPu3Pwfw?zfv zCv;PxtwAbt(RQ8T&jd2GGWE=&A(>aj>GjU08W1k9=->0pM->^Kh+UhdY8YD=K0m>jfQ5PjelldQ{IfInED1 z78^8~*Ym|^qG3@Cm-;nnL{dMB!C%tFS1-79k;nL9V)*Prg;Ijl^9b{uCLt~P=k&Qs z;5oOo(h9}At+MOd3I;C{ZX=v}27iUCpv z46%*@QImZor}bGHxFQ(sb0&$dWHq=K@vzd%=$r=xFr@T>z*GmYV=wL00`rW_>sj<7 z-sD%vEa`o| zP_3`rVOw#pyp2V;{hVzNR=4nJZo@)xY`n54(1y63DtYE`zWHYkzKO-NMXbJTUfkZ7 zjB!c_6Q)`zrV8%H!?ab5s{gfxd{$BXI%>4F9?eoKDF$#g`;!;zFJ)C$`#%fj_a!mZ zD-!=r4HjRlX6QQbu|G`>R~O{dX!Lq2WNYEr^KpTZj4XmC%KE~c5GBEJsL*gc0*e0< zil1M|_J#5!e_9x>ehJ0n9aH)FiM8OO@tjBT15$c_+#V+gkGK{ka*0PX-JqF2Q+fB& zXc^+ltEm5KYQC!;MK@MLK9IVN3+O!5*YIm<*OTLJ<{Nj1exPe>Y0Guvk-WRHH~rEc z(Gl>Br3A^lvo_R8MWpq;J^d&OjHSbt`wxvi-N8@EC={ZvZ1GSAbV*Wj>JW2R3U)`T;bM29y5Wvu9j?mJjx$kC{sm+F2B? zZp^1eZ}^vmEE9^YibKxE;#U09Nv)jZ>q6t0qm-{~r(i4TvyH#2Bg{)Umjb8aSwx$S=J~3#JEd zbjJn6Wc=6-IwLB0)-tD}9&oV(0#d(4Fcp#^#{Dx3V!0M#+(K%urM*%y@F#RkhRNGf zsZX5JI-&7$vE~k#<=Q5=v6NnYQetpQ#U4&uzmo?0WvM#FaD9{7<1OnU&S(z_w*MlC z-)DE|K9Xjef+Y-`!j3BNV$2Hj$D5-kITa3QXO_+Ep1meKCoWTM5t*o zlUo;S6`q|U`zWnHZ?v)rL5&ICq!yp>0T+>hxO@oyW z_v5X2nIbl)ejprJ(Lt(D#v(W{{CsTSWN!4uXTpK?<+^@N8k4Rc^~GPhi!Wbr-9=Hj z<4F5PdktL94@Bjo>-g_w&NSq|&)6!~Y_NR{56 z=?fXJ_P-*KT2C#Y{PwQRPEl)7&1rBT>Cj*4X$@P@(AT-ldlPwCU002{r4`KVkWL+_ zehU1$*{!pQ7~e^5#c-VB1kmPjyfJFH{{3PcqJB@jUVv#9z0mrQ?$l(i>I!utU*ulO zzEgfIv1VT~rj`CI$6Mn*4)#?oYN%qM)c-SfFJ@yD_hgy->+o;Puu6{2^2CJMnBxD!JdV8pteeBgOi#*jS)GwXmN**LAhFp2Zbk^`2;= z_ihn;msON}J~mOHoi-rC?cySfGu(v)5it{La}10dq|I-vF1sPrjTyi(WA z+GQ@+`>HQ2OyV<88%uwOi|fo{qvkeR1xs%2q8K4eB}mdpu_14{>6Nt*VyG|8Y_rZ{ z4WHN0SBzGXH|IZdo4cY-Jwz6^+r~GdvMDC(=|z-@=xsD7OBfl&6k)JX7s`$>U?0UM z%8qJCKRvSM2~Ykaifz*MPwBI$wXgcx!jK>4o1#SF>z=kSwYi$9J%#ywz<(mWsr6`j{VAb&F zSaw;Ij9F^)y>Y1UH`ByGK90{sD(kU`L}(lhyTBPCf%PBM)b4wD*+Hz9KtwY1Y}9Qig5vE^nb$~Q{g z5$hCn2$|UsiK1z`uO^S{|M`a1~sLIgObR1x~cUMBDk5D@vK4$Rx% zL_g3t47f%#iY-BSALTI2V@Zg8yUdW9a=#GXd7s$V#Jt6pjcsy=`kEZUI) zkMuM5EqG<5WwaAVsgl)|WxR+}2&0Wo37h9Rl9FMDm~P& z7FN;BMg7Dn=;ne-dfZo{J5T2Rym9A)nHe_@Qe*PJF*(MU%ydE6Nf{3Q7TohrapYcL zCQnKiGd&aM!(ZZI%bNCYVZ`fhUmD_TD5Zf^<?oGs%P^i)gUkRPG06c7cvWBSyNvs#a5?20bKT1YtJb*u)QZsHDJJReu6wxQ zwrCnUR8cee`%$pxA4Q#AQyWR{Kjf!{VuojQnAWsI%LW>tL*>`A;YpUo9esI&WxP=e zuafe$xo&R07_~9~O<~(OYH$vzZzZ;kk)lTOVX-tU+{G?yZ@}?CoXoNp_Rgg_I9!p= zBd!t$b#)2P_cfwvuzYz3=3~ zYw=0rezl8*?rt}w3{C2>xCQrL!W*V=osj2B(Wv&Vyz)KR;>BBqABUZPRZ{$W?d^@zfUg;|b`F7a!kzhZ3^EHui+4hN|nb%ufnHH^Qb7=DRxQ4dKy zB181VX^HwD?pbq7<7GoZYRahO*pGwsOL!yqZh1|SA8WzKC?T_?o)fzSA$GbF5qxrD z@ipU4fX>v=SyIQC4!rUN-(zt_doEqveYxKDUZjov z&@Ni%dR_?4b}s_XhH&+iI2zi`#j=CcJ~~KdfNGxr-RkbFzyHO}A68zdJ8k9Uq$!E| zpC4JTo<#71@`M{Y!<$XRJbMk@Vy~r?uPk-5^H!~O`2nZID*)@66;%NI^NWD|7ZZ)l5P_VRK_NbO&XJ^M=Hbm@}lve8f2jdx|F!2HgnM!S}6kb)din``ly{6cYzr~6E1i`|+bq_Y&`Bs0PO(+YHsgI4?^E}z*075jJ>JJi0 zzmy&en)@!{4Y)rxR79dUEbDIg@h;rQ!Zz_QTwpvj)zMX!r>Hw!Y^Qc^d+esp*|Zw4 zC(3!rm5r1Z5coC`Gj?`K>exey3w7|0_0BKyzguys?$ni26Q{zK=pF0b6UKdNpauNY zltD?MA2rnDkP1`Mi<$FpuUhxOudk{DHVEch-BoZ*GoPm2&7j(s;YY?mCxd~}Z#e+A z5Gj_umenbkZXJJ%I<0jyU5D#IZ9#RVTWjxbDE?;og}Pvo;xGMAxO^SI8~3X1EL4mO zVq{|ECn%L)&iyd6c44h@tSUlJt=j%EY(sk;2FIxL+?A)8$~Ma6Ux;(`DGX&4PPY@f zb5E5inu*E>4*I`xW8JMUi*X-ep_3A)BCB~9SNTV2O*lpMvjyc5i~rU2(9yk!8W$lt z+S=R{Sn5+GsY^EE<~T`%bnd}2w)n?aB9VDUZ7b*q23No22;}INa6ci4H@_nr9P~5y zQvxSST+dCNc-ML5nckW(6(L-AGrU*&tlAXZMpzmEY-?`aockFsRu0Dul-|9lFO=fXGjzFO1CYSJ_fsW-erjX`M@ zVB2{I+vqszL`ySTh)m3Ww~t*tDY11dOxXmyQF7IoEuiO?6kQK%;C${aoHcFXGaNYo z9Xb$xlHt6cEC8Av8WF9Tv!Vl13D=8!y@2K3&_UKA0 zsQXH1;GEmZXroQ`TJA7`e(qBP>Z7n<#c94?s)u6OBO0l_#ELQ@YL*A9Uc+ zi2K?QhtjuNT*Klqz-Kf-L9C*3enpF1B({phV~`3~SFX|Kk)XFV1PyS-7}XFpzfOOe zg?Gr0G{v%kB9sb%=OlVT`V*Opv7k zNlEKqJ}pn zMn!j?$Q%06*2;Vkm*cos1Crxt5Dg?b4GkQ)oW=+G8C2R!JusiQ^~PnR4Hn?gF} zrT~y``5ZwQ8LUH6Vx?Wp=MHvXBaEco%VI{Hy-6-=aGT;FS(vPj#(06Oqef~GWO+ja zK5zJLA=oAAM2*F8i#6uR3Yw`FM6twn>I(i5d(#?e+nCJ9mx?oD(^*RxMrZ-mDOhmp zlgp$O^}39QI;!mcF~EehCS60#Q)6C-dzEv;en`jAO$7~qr^b#SLlbB`KNdriy7CDg zc6{clAJE4=!~4^o{gYdRBHxdSX(d8lo`{&MSBxUYKgcTcgA$Dd=TV(iL^Vwsk%Wcg zb2#ZBvUav^GW8jMweV+s^mh6-)1e$DMZiX1&t^R0VE-;V!gEdCuE! z=5K<5ru&?98&c9pG{q0yci8$?ti))%ymL3^>%?=vZg+6lr? z4N=gg(m+0m50q$o9l@-BiRV}Kkwx6Bf`N_fo8TRe#j#5&pwN7(;OW3oi2Eawf^S7%cztbd|VccCOl6-Z`c|5uo5ece$KHsi2;9!zguJJw^a8Q(;e)f<;mKRb) z!4qv%-1~H1p;lDmIJKbYvLW&k?mLWE0JMCEB8|L_dhM*N?sm}v^lU&8Hf_#+u8pwW zndKRRPeZA%7lz4JFhaGH)QqAqOagyzm_M)DPR|#!CZLH64u41Kb8Z;emFv2t4yj8m zUS6b{VvZ;^M?r&gn!qjOIRg5q;F;D*gn1KJFoxGzQm8k`b7u0x9JPnE=TeBCf6gkFc9nV6*xpSn zXE5V?_p{$nPj`Jm9ZzVheg?^2W~rMc4D^}1vO+_Ha6{5ysvB>LN{`KWlvafM4%8$k zPFmeUw8}nvd04?y7g%z?gSHZam0JErC zOfQcB^&g;`g}NIXmIf;HKCZ#TF*Hsz37L&+P?x#tdzas`4DZi8okEh#4kZ;v8x<}Wti5kZ}xn_2?{xvu+}p>?VG z^NZv|eT?*?bghDtAGH~Ivt}Z@*o>;1sA4cDmQIAb6%h$dqr!(msxd(--Y%zoWMZqc z;j(+mu)o(>{hu&wEWPG&oUmxMlPtR7S8Jn(?`n%Z=!A|B%Aihck~p%XRe=4usw|@~ z$Tq6Z%j7xxvPvUmT&(mFIkjFOk6g4L_XRAE?a8@s6X}7$h18^Qr+N-~8ZV|7>TW62 z-2(Ot=T7f=)a|96#1V;#;h`6`e0`p3VTpVRL=a{scAErx=`GA%mpe<2rO6 zh+ZLr&T=MnkS@Ri=H3|JU-}mB<7u+x=G5YYsqPHfQ0T>_qn7&*jF>!^DT>&gFK{w- zhWrGy*FcHM*eu$V{lp!Gv<4sR!j4L0<2kZ+(+J7@)pjys+6e7#s57uLn=Dh4(r;cv zsllMiI}eNU5y!-6Km1Ho$V8Nnz)Us^+oHpwo5Z{zb%%?V>Y9m;AhBt;E)}KGSJ@@7 zhQ3ak16v5X33?q41>rotJxg_{myypfN0@LEm7m7XSOr|!9dRD2#{BOe@ zn|(>0T_m0#K1x$FL0l?IQ&)?VIiHmxWv5kRO%%;6eC^a1xMplF`CZOKVM<}8Ywq_k z@VmH}1E=x;n7k=#LS4uazMaNXym3z*GkNI}dH7r|ZlsR(Np-0K4g8kY;%M?$T zaY*03il7P-(yEhqZOY6q+8y54iQfs98_aZf8=09eWO)L|h+Olt^*i@-hov z6hSM0O@S!KA(e2CgpT!;8$>^64fwuCI{S%ok3r^%wv1x$ds^TB;6YX$nr zcCZZdX>7#xc&C-3Bd%xVzjTHb7z(D)eQ}l4q&nNEAw?Js`MY>DW_L~@FKIb9PHo&m zt%Gwt8`@vOYmN(U8GH%auSFFPkqkw#p`e`_3TCSjB$tkt4S!5|8_eD8Cb@NnKV}C@ zm|+durtlg5G$LG`m`@|#@UaE#6CK#Zc2rAVr!f)Nw^Cfh^#s>)VJg=Wus@rzKSv6g zGgOoXO$$>$$Nrp}u8={PN=IQT1qqrd-$|fKFqKAAxV}*XJs-$=!Bj3MkRnWFVuuz1 z!c+`YbuZP%;%L7*w}Fg)A&>1I8~wI0l42sR+wzw=_7@s5BQW)LOg*oVeTTjwFz|47 zX}-iyu2Qh#IyDjlGzPzlZn9|zkh^jK`o z@xiTv^zORcq=bwt=LH%vQUi~V0}toV(2*W$AgYUEOZNRk4K&}JRs%G_aV!}`&!Y%m`sG>&*)=e5bkPtk$=rs7P8+$`O=0oCtOX0z^O}xuIlW9x9e#% zycok{gh7>P$Ns&^+^cDGaje=vSDJkVrj3Gq(ehHOuqp1>nW!$4 zxXD+T=_ZjDmtz|>6hU-<>PJ=5Uccg1JiNga^qb4M{{Mri>i+>#yZ=rT{{vI|kLSaP z;O{A)Pf>DoT4%830;tl}xhC{Yl(g@R6kI|(McdI)bM1do>l8!Le^6^n4Q?)hW9Jot zS~bT8)G8X6eC?tF)d8639>sL%z44USA!88GY@Es9qB?d-`%ZPqryR$1%6ev7{x6c# zifAV~I}0?Y{)^^%{fp)d|Dw4H|1X+*05sPFXbwbz|H3(~u`!*8>5!rezkm^|9$ zzPzJtbln>-PLO^l$$ILc&T;)!+oRBJ_BZfTOADx5zWAj%4)^M^?J}=3s0-JJ3jEvh zt$+t+BUjWsW<-?AJL$eTv+hC~W`N^F%2c43s%>x^I(vzK!gdd z5d{=pK)%Sxvr6=nQfNPUb&mseXZ)JW-6V)_;hm)KGuCJ2l%vC?yzxk0tvoj9<%tbC zVJ_pa7QAY}87(%@pCW&K`3@hO=1+mq|hUP4*VEKg?h5^$u72D zV`5f8daxILW`C`vCWaO6qv>G< za5(#jK0kO92-wMewHyfh(MFXt`=3y_oTi88|K|7^&#t&bauf(`-wiop_!JlWCWtTL zU8HZ%t-qLIG^9iClHnftN<#OIv=C)9uJx9$SO*!Wrkmbfjn`2^2Ee7X2R1k4p_AW@ zLgTs60q9`W0v<){tC5~gnR4u{|2EQq3z?pYmw%EW)nMnOf_;!mSPe>x+zB`rnab5m zCv1DJp;VH8=3>7F@nqgr`tHJp^emW-CfAz?VH3V18UU?RM-jCQ>_T&7gBwM1$lBP8 zk5YZAS3KVAhaW}e1~46;(O!|f(MLBBjL&F_p=hMk$O|3+GkLV14{L6xKDdeA&n3g< zm-)8~0GP)BFe|zhJY)tB#3j=xbFzSbJ+{$g8fc_5JXzs7>8qQo@!HHo&5xxd9=3pw z<~}?ib5h+aPYx66;VSFt9ko}!J11PC;4R=~QjCpu*`KT5%VfBIufPSgJj6r=bVjk~ z9J#*5si&%ZK>@Rd@ktG(uTs~XyI|yzmRIoirpes9aT9%S6OU$HU>hMO4K*9a1-0oS zaFGv5ho~ln8bd^wS5=AaXE}0?~vb^U%pae=5< zJnPO-!b;l|Na|;#Q?ha)39hCZ{91uq7si)2kiNRK7CTTbNyDkUYD4a&H@r%KERp|1 z@b6A++pJUiXaRew?V~yZA>T{*x%2}CF)7|DEBcpX(J$>((GE;Fs{6G;ju+P+`rfWGYB#A8?|#VnrN z$)J8CLkU>FbO4&@W;DD?W#?p!>CTbW?+e-YKz-lY-Uz+dy1u;lhx{8TqIaLOn$(AQ z#Qroxv0piyx5XvYKQ*5vqMd}l^wrrl7cLrkZ_5iTy1`VgZ`??4c!XKQvE)2$#kD5{ z0O(=GwMf68YGGp9gC>_Q=`g8ZCf}X&ck=TODJc+l`tv$K=#Ggh!4PFh~*KZ6W%=(BhN7qfwJd(5Pis*Xq zTy$%Ix1?8gYHmNE`OD!26eOlKa8?2S^6kA-ueVYakPCQoLhai7E_d@F-jlbK*6v$% zV82mxyQ+sBX(YU6b;OqQJYJKiqwtzTTkt9YXK{(PCjCi|*W@!x=MFFh@lF46nhkI# zWd5M}O&XC8wjB_cL}f~M)ANEeH@3b)IWv4wXf%bk)V!y{n@OEbYj&*KzDuMyL@2Ke zL&ZsmxWOxwdrmpFPt$04Y>(%RI4R@NffU<;f84`hOeEfqyy*|+c}eQytyD=YQ{fS2 zir~>M#)Eh`SfjiJ*1CE>);h&P_2GRQ49C4xrL{l^?f>-_0bC!hd5br~TSOwBgtwTh z1kI8#qF+niS<9Upk=DsceOWKH2~~@vdUHhXJYWa+eM|=UjShCIW!qNnIjDC2pTckK zXO#)b(I*h`fhJ;SUW<1#Q#XGX`!wdo<*_4thRvi30Br z@6oy3dng|7(XR6#U&BGs2iBo^kMdR}zr+>qP0xV$h`BZWKV1T1({H2|r;DC@`m8Nl zBg8?Dy)+gMq!rXRhW;X#@~Y^}gKa{%Ag<>T7K*_0+{Zz@0dEf!H)idwRbXL*WX{LJ zhnJ3_+EN01coQx|$eGMnY#5aI&R`&g?ix~fah|FJDPZ^y(VXpuNW6Sh%o5Yp0#589 znEU(f)YX3ZAJ_3J|JHw9N2tejH2l|fOrk+X>Z(>&zB~KHnRRFMR2lA#KC0Y6T76>G zAHV+NNWvHJQRR;0_l$k^&AGzv(mie@NVt*nc6Jz5CE1Q+PU?Z0-g&fDIY_Z7^v-Q# z8b5ELdAfiUUSl%v?#nNKs$8PkDdd0IxCf=VG(wjWx{NDBcuzh3z&k4RYcT&+HK0)V zL(?N0UBkBLIF2|e(AC>v_{;qn-b=PqP3ztBsN^|ora7V{1!Z}9p0z|lUj^%vlg7P# zo0$gcl7}n+IzYw0?=~H2lX@I>qOt>giHpvcdPxji1BEQX+@jX>FvU;VsYLs|(O1Px zy&RP=%}`8(n&gYdU&^P6PYRjOD`TDnCohH~pqS4lolU%Z=Q|E#M;vB{ zfi{K7e7l7P>5@k+kDlI6KUwXj6~X^VQ`KitY-4BjCltX~&r(lFw2O^aL@{97;O!>f z7GpE<D{rLchn91MwGWh3}o6*TftFPE@w$ZJIA* zn;)Mjy(kY|9x=U%9<}nUiTbI#Hpq;ruY&n2cAs7a>v#awS425|7f(5T7xf*B`=m|h zLpLD&QWUQWJKaMh4PG8Ty`kRl zC(Y;Ml)y2m@1~W{cT)=m|9X68o}FysslT{HtRu9z zo1=jV6VAefHLQ2fX%h}g>NX#TLQ~(n)+Z;#p|H?EkNO(v15FgAE?SO5@=K@>xJZqVYYgVy)tWGC6i_@6dk4LiA5$#8 z2(rw9EI!tIXN`v;%iyGl`HjnEQ6S5|x@JrGdBvudTIf67>}K51lQ&+t2akfL%~Ufp z_34>rR1;hSt;s~=P26zh!{_=hX(8Cw*xzN?UMPg3ZB$dU%sQF~Ki}w5?Ae2Y1RSWP zI8ar@fjac>f$FueMfqic19htWK=qm0T+bHrJW*3zn83ff)3pN!C9biFzLFB!abqZN zzK9Q$(^7Ay22iy)s;gD^HvgH|D@eGn$6VhNP|P0*Fl`;a(u_M^2EU93X45#_VWabR z3MGgDVxkCf&MM8#zpU$#j3liFL~6d2F(2_j1# zk=*iq?hkSeEg)}@Houb++jd9^2c`5M+G~FlSoBB;T^YKv9!sWmcnswA1s}b(#z%hw z_v}L*ZAIDiPL9Sj8C5n}rf~-HVmsJyY!!+GPx(v6Z{OX zK^p?qGez{-S0<_<2nqKu6{TmDPL;XN^?v@A>n{taqWBGFd@Ra@W|y{+4XDgPv;DH! ze3V7P7gUp4n=G?C=vn*-1wRr2=3gSMTgBtP|7EXo``y5F^3d7w5wi8#>c9N_m znm#Ph$AIJr^dCW>GbI7~sAYY0+IRrcY5G_h@j+uvABKBg-Is){3=_1j2;PmoBU3-W z^UaiysZ#ebUAhkUH9Yd_a(rBIo^gNZR9!&dcD&*QIw7BRp8(n5aNoPPjhNiQB!!j) zs{4!RW1Zn{1l8zi>YYLH89Cy2b!Y*6kaM)Qb$pnsg9)2A7MoW|Y~G1-VX=AO*UDae z(r22q5C30jn?PEW{NAbA{qxWjp)2(i3TbtT?K)Yz!_pMUSd?Vu)6M7e#*Uj#h(8NJY6=Mn6eQUI;D`I^O3P)bZeRa8T935 z?5(28t>|rd>9u^;{*gKo&qKgP#r&LnCpS0$wkxav;RTz`CY835;llWkWu+@*5O5Jv zO86S7^yJ|ydd_aCXEnnWggx=gqe>ggypY4uZ0AcP{Apkbl_a*C-BEZ-Tfr>dkx!rB z=gSM&Nu3XBxkqGVWaF?20=bpFU}RS-!BM5wa|0-yKKF3pRX!l7sI%$P$Z#jt5z|D{nYqhNOt zy?HMk)KX3-e1`^u)!4>w5$B5GOikXf>!I|_;)5D>c5<{I{$Om^NrE~H*!R75p!Z{$lKQ&rquKS_x#+gXF_f2EOUXRX;sBm7pT zg(Y-Z5xBA*opbBU0t6!4noSN^%m`Qi(gNA=s4PM*ZR3*o2ecojv;4NQ0_=<1YF-mx zo{*p%hP6L9gS%>+xHEBAMa;lm^*&yQC~QgK@*q$fyLST}KdE)QUrL{h{mnhC<| zu6k-^L3bSx#J^^xqImfhE-AZ>L`2lzIs7^MhyeyJ2XLUDz|Er z5?sz9ow;rgmZH{B8z{Hf54ek-#j>9Q!8*V*TSpHEw$M&#HY~~+k3|XcYy!(>6M1bc zFd}S8*X4mpmt<8EHU|2o8liQ~O-o=m>5O_)6uCP1Rsm)zW}uTeoxw;$T!S!@XPoK0 zsys+R?n4_1_7K>Ohv*Vpw}pfow8eh7o(Au(cb@;Ps6D76IIbDsxIPQw_t;&!7bLM? zE2{+pV2sSTluhXvexPe8h7WUL0{3q9rOap25ZpH?{secKTP;xk;G{nDS{BJIpy<8| zmJyl|s7)T)jd%OsKy-dtNSkr1#aZc{I|wX_&9p`fET-@tzQ|ju%M=?;uu`oe z+#BDT$*fBWS;4FI=Xk;Q=iv(N4&}Q=BN%Vm9m03>-y+?oa6w(Q(SU!#nZ~31l$k!zrI-_&%;dg$14GlKqZDSPs^^Tm`LAXaDy3MKH=cyg z_{T^I=CcZ_uZ#IIFL>Qh8wJ?u3uyD6BiTifE+CVaZbEQp=ZbC*8Lf}cmadlL69Z9X zspmV9HEU>ndD6I@AGLrqlN`Ui>r5```6>+jn0fI4z&N&>FL%*J{@wc~jml^z(HXC^ z>yhINr{FKWr9?3G@CwYhUEM9QrASQeMRDef3pgDI&Gf!5rSHlPXd|fy+Snl-rq))f zaN4+oA43tgF1g?G_A~Gq&KIJ5hW?XI`hfnLWr{|RwZ~b=m3hjhU9ZK0qMSV(hO!8( z$buEs((NSKdh56mT_r7Io?$Dy&uyvaTcte$ZT(@~Q@*UBD|_H}zsi`m6Hk!wOn2p}==SOASzc>=1)8e$XG~8m-D(v4Ypm!YM1|2u{s0r_WQ?k1Wb+OkhSDUlI%i>|T`a*zJW+#4Lf z^i3@EBhe}9@Zr5%!10?mapLrO;P^#W4u~Gzqi5!*n>RE6xNNA*Rdv|UU*QI|Y$MaWDfM)_Kcgh!1E$cg;Gvk@p|^B*Rg z#A}6&*NRBd1LCeZfP5G4zH0i3`{q3t{KD6zn!XE zZ)Y0M@|k98pfengO71d?%f7LRvB`1C`rTq%Gk{3uo2eNp!=jTqP6ururGNjF!QyxP z8}jmRtX^~5PnBJ0`@^d1Zm++);l?-MFO5=E8y^=1!1_HHiP7n|E;>Qs+h^;aLp`8^ zey&-CD0i-1K=m{p-)#0J@}&J}&=40xlbiZFHHcRPSLN+&Y6Y6(y$!d%S#hE6hsm>( zXMYvm+&}2rvwnBfu!(Vu` zJ91_8`~bb-$(a6$@k#xY^*ezAO8!u703TzpyvRB2^eOTGEbn!W9h!Ce(O8XMn8QuM z2huJ%50Z)eoRj;CI*K?%6MnwPPY9E$D^b=XktmGoN+c9{;yj zgjf?x@Df#&S3fFnUcH}xrx3hlwiz|WbCW*AUwVzPa2~KQ%1jmL9aF!g@DF(f-;qhf zlSjgW5oz2%Z~TqNnyIpAbC%LCDd+<@)|9d1t&>H|Aq;muXVuy(e*8&+=&?yJbywD3 z+hF@fe}Gq1D8j_&=DV|z@eJ8imL`j9y5glHwtm?ZZ&SaN9l5viog%Dwki*&mKJ=vy zee&5K;cB3c=kQvBgjkS65#TrGY{>j}#re7mljkSRPuBlbY|T0;gtkDe;mQ3L1^F5Z zbA}}jO&*@2-}=Jp{M~o}4Rv$41y|U^90Vqy!9~sQtWOy|&N`|7m(ccul5@G%wb%T* z@x2QBlh2hPgNuGCttPQk?1iFc6tE19{1>MW=GLicr3+6i|Cep1VHdn-%BkE=-!A0?B{Mv!?xO`~wA+3X~6^ zvzjVPW0Qs~?&&)m;zRpe?pv?n0?`?$x+eW!tA+GqSH>^w2JMe6*ZyB^&gHIx_6=`i zx2RK*lHW}uR8_RViDUc1)IEHHyH2`R8qhWC34JSfcZTOC6gV#5^oaf@0OnF(sC!U8 z+ZnC~Kw0x3baezq>Y0W%oJcaWITNsht ze_;qP`S-&Uhb0STKDRo46Q=ys$Sr29c}T- zqzF?+-VWwDl8~v4#DCul7GJDkS!L-m6+x}Nq0~`-j4J#S;!oc@-FdLUaCw6JM0;4p zY0WBXh?NY?XS;-spa2=FQ9Q8J6;!xcl$)!+}M z9%DsfClFbk>qhjB%Z&;BQ0f@jflHHpkHp^Eou0PmO1&LD&P0_=FW!3=*Y@u2>3#2f za75G}?6=&x3zDQGr>~vRw4K%!evIBS4yxiZ9B?;a!OE&?&BNham#zjWPO?ix4h6y&5)QJ%9d(M=X?0cG~`oqLZsJgCX-K`Bp->f`e_roN(vt<3| zC)T__AqT3N-qWRwNQ}lED%@ET{=!v-jLV7 z9Ga`#SbzJA;_p{pgqPJec*_fG;VI*<9_6JBMKs+?5AF3^*-vP12Xfc9P9k?bt6Y17 z6T5%dR1*uzixkScR8CJd`qIWzRV+v9X%UAe&=K{*6^@?)tI!)V7Km|Axg28dkhy*gN}8 zFn@?R6cS^7XIkcu)t6gk00P^*0IuBXDb$#lfprQj#;Nw@!=n2R>B2X0p`DruF zM9`hsbS5|H4Nff}7d>3h{~M4;iGch)1muy3n`wgDz{MKS$7+Kj{Aax6b19o`LsF~A zN&E2H7wK-Sw6t>LI36#$P#vRDDOC5dF`J(-(+nMdp!QPIXqlCo=fg&hn`xRZr7H?g z2Ju09K7&^f+}#1FW3kguTAWWmxpx=Ou852Ab2PuWAh)~6y6KVqSA z2*eWu0JKGfd%BN~`4GG{p3Y$gyfseQcI4=Rt*1^Om^*&LlsQBED6VpQ%gBfb+sM23vi`h&J?hVP z2%-Ckx5mIY)*OvQB@BIo1}Y+&dT;@ju_!cdge1;&?qmY#N6+v1iWR2N< z#;&!$@k)Dy=Bl*FF0v6Xp>}7O1C$2(j4CTgAk0x2k_xSmRQOCwDhQ@R3i}Mvx{vkF zNsN2cj0s`45pz)1xJlZJ@83U;kl{D8(9)0<5wr3A)zE)z`pb(Y;@3uqVq5<_s_y8M ze<2qHqnOK4Ci>u|LKA5mKNd@qyYLBoUg<8`;kP`^`?KEh$&KpM9kQZA#OiJ)hnZ+C zbyP$+_2>*D7vx(eBFtMEG|RK%gJQ*}AeoQ=A1nt%#Rpc9p?h2ynfdbKs0)YEK1#m> zLbR3y0kjV*wB;Uid{sCy*D(DmO?$0nKPKb<_>owe(3X$m3r^~oUN-ztsHHllZ9jHw z-?rl?_s$tNZu*DA{Ad7D9V5DhXO6geEAx1MUi5L%A3H_~>CBtOv1(eD1Hb$hkkAwL zLO9PpAvm3l;FNEc_Tz!^sd#n&-9l6G!3vb9;e&Nh9InUsEHZ#ouJt;4-c|Z*4I=fx*IuYFx2y&^|5wB%;JRfOYAb6>)mtY@_p&QqVo){M@9_RJ48+nxu`{a^cRjlb;^ zL%#F&Ts7eh_b%RW>2n%`Jg*kTEAom|%|h`sfT|%>p^Cg(7W!)&N@))TD|@iw=h~SwdoH0)vv@UeRUFo` z`lp}^?HWZcu;UEzNs8Hh)(#k(@g(g*`a>Hf<1T6|&fG>vB}#azu=Q!``Uh-hy6RSa z++G>#0f{BC+1Sfk+ADDRZKoMc1!3w3a1B03rl|Z%8nhfbuOLp_NZH*KMc!)*DI%W? zMU_fKk+&%GGRJFWUhid%(8|0{(`1@v+=asVMmnvIYZ$N3J7uHztuqbYPyZid{{bIW z6}%0=q3wpHh^&_um!9l8`KoVKXKNE|idsDbkS(C^D1m4JkZlq^9r`(~iZDLU zIY1z9B9FT2uq=v^+Y~sdt$`H9m0uOnNZlI>HKQu~p$WK^V`E|+27I~{m&JZELujzL zgr-&oe7YXnS{?28A`tA(JNcuriiKRM35n-H@(s6UhqQNc=>2T63zoP5l-d}B9IiK* z`GEr?CiE@oN}>Z8XJEc8;Sgn#DN84Gt`&FWb#NJP{Ph$xi1+eWqORjy8mar@tXOmN zo9J_a*~)i0KvvXZ4E!{3Rxz1WUZRAjnnIoq4l4Vbm`nQ8QxLD9um(2~8TCvwxCyQX zqRNDOJw8U|1@86a9U(48fVdbTD;=$=bio8ypDdVQ124yd<=a_nPYC+;?K}`RnWzj#9 z%UMDTsRo#z1CBS^p9jEu-rKl3Ms5w0>HQc6tnI_;7F~P!S86Ez8y%Y{Nd7k^M^R(x zU}Gh=5ZQ~~MI>Rc8az2}LZ5HYSbd@-Mgv2m;$5Iw^~~Wl?~oZo=68t8+;hd%9`t zyDxAP|1^w!+%Pt|^1sHRkDaaecs&>Q3T@@$&{*U%ib3KB2Y{6HgF#wJs8)?^2_|VJ z_32YCnQD+$8fQ?)^zv7Hnp968Z+}2hfpJQ>o^!?`6|+`=I_I30UgBe}&6R=34}lE_ z6KInUxEB3maH&V2qHd_8ti(drjO*#;@A$MSCP7;}tBqB-=19GVZ5uUo>aBRRqRo`z zRC)RZL`H$P=#Ih4rZGkl@=w6ZmU`VKGV-JuiUg6-sH?A?2Bd>)e8dX)MDv2_Ot@b0 zw3Ps6T(ONBIrT0)QlU3^r%LyDhlS2##s#RK(4=)Aeza|@Lu*2p&5HXUy7YM}eVl(p zjzSkQ)C@@aM%6-=IuNRz(|SPRk426havq24F32hBfS3kOd_9$&h`)Z(a=qX@Y9Aqf zrS-1-S5@)|YrRqi0uZTkRB{iwc4sH53tHJ+85}+NPYzrLo|FoTn|CRRnUR0 zunb1;FCL|6lfAl|bF~W|eI`_%pglo|;nHzEKURvQd;U(n?zxzLNm^dy(xC1S( zN6R1cE7OdYkA~|Ov*qPtb5MlO^F6c-{G~S*Bw=kzQ++bXzIQzOHx_(-a-fVti7vgL zO8rGh+O1Q5cej)W89ov7LALOzKZ7JA@4U7`FKMIXaJ>vfRHiB`Ln}UMOeyhcMC=?c7lQ2cv_O)y^yO3wn)GR!5 z(J7aX8dd`)OX<_JdnYe}(|zZ(&kHr)#?cR)Zn7Jc?om)=l_+vDTrX|*)l_8s1HB|V zOK;OK-jzUuTJhUFM)FpqEcn|00%3dCaPrYSg&aJe9hOer6toHAb}%N4)|}Fz${U6% z11HPtOh52DGHx5gnWNP;82;}AlNdA+?8K?sEL_tBX({B>Q!MsCP#}^1R`5%%EL7M< zDov4}qDv?Ra^7(@!x+59KCQ0bg@a-cR>*>U^u!yk+fQ4+aTxu;{-)|(6ulmm(&||} z#r1j?Y->~sBdeuqmT)VLAg_XN3nwg0f7eg_Cp$%WaFI=x}HjH)B zm5VFkLk+?P(pQYEx-+2=f@_v&76`7O!drs6amQp?s|w9^>6cX6##?M!*^FDVTCV4h zv0-`t4H=VUdDD0s8n-{b&Q-9Q+s0cu^FS$anidgnP%(<5?q6bIiPJ48ajIEhIY}3O z6Flj^PirBVIxZb=F{7>ahhRy!_s}T!b#nzx^=YAo$p@>jDkP4U^{KD7ks7YoFnYEf zCc{V|lSCVZD~29G&Wr<85k+zbckLQBSgM-tDb8KFWQd@y}ErS-m#O$w#>WyM?8Gjj~ z7UYJh)Z8ET!2WasZrLfGS14{?dEZr+SH@W(ZiVH`M*IrOo{itu4dui(kX3(Vqe|nq z;ex5b23GuE-U_DaS`=c5Fny|@K9(d2i7D5UFDKtVoomcuzgA0iU9{&1VI3_t_YQMc z!on{5!mb3a%Nf3_Xd{#Lk(UK@?9qd?iz)g-**C@qf`sj*k5*|2_Kgn7R6BWJD#~}C z6B!42nXMPbt(5)W=<&Ap4lbsTQ)(&1}Zn^XKVkA~_PCrv^e50AI=T+8{fY#BAu$}Hk<^PqbwIRFyPWC_Y zEZ5ybFQ?~v%S$U+R7w?swDz9%u~KV%vzd)y5+q%;AGbcei}C@%PW~2~G`!JTUNhFA zQjUJlqJ1k|@bO%hhDphLnm}cFO18F9ST6Ke`b94k{6(elSyVQ=nDzv23?I0b9cU84 zYw)GHCJnp>EmUeuXg;$EBwlmr4USu%+(jQsIys8(D@gCbzi9zUKXf1bfNSa5p7M8n z09{Ycq|#6sxyT-C#}s;r-^kVmMIa=8iDIMlgiL9;no@m2i&;(4@Gs%a$E=U6*b1uEoaqHu| zi@uY_I`LZt9c@|%epBy|KhmaMrd<891@BIW!ODgyIF3K$Jc-llno?c7&26(^gMq#l1MSMzawB*eJ~}!|pAG}nMqx^u{Z=*? z2ldxwFlOr1HyAU>I)O^5n`~OKjN76l70ag9nX7!;Wr{pPo**hG^%qt}@K`QKL!$K0 z&|Gz@Bleytx@Uyz%5m!>b0Bf}9nZl^cn|H7?PNp`?28R#U)(1o17lx|J`#8FegCc_ z8Ad(SZYZgc4AS$S7=y9qreSHfGHz%dTbKi~*Ng1g+1kDco&wn)nO$*;?C~;*%=iL! zlWAMZSi;}69AnoCLqlI-Xt+&6!!sp5dL9}+MunzRMoIr_n6m{HRJw{NkE*3xj34#4 z6b6a20grngC%$j@{XgQw-va$L3z|K|73mctP*m_ksl_ip5`?J{$&E;-#@@nU&LBl+ z|3AXHKRA`EBAh#@`Mvsl3oZz<6tAQ{uRyJhpzckJ{a300?d3;}EoGlYVDmf=JcTh> z{uW#3|5psw+pjIma@-6kg4fZ%KKjw z@;<+pW4|j=NOrVDAvuLn2-TA0Fa^>RH3;S@@6s2lR9?Gf8|o-q=vu!-fty0_8fG*# z2uIoIXWkXVupJJa%fX?d@&Dyho%p2TSF7T8{}0#dn~Kf$Hipj7Bt)3z@3?tRh@bj9wG&IQQ7^1S#bA^ z!W|h1wWa*C|C|G^{_bgN;Vu7I#a%gd@y+vta`Fb9Rs7mlVcZIMC0cCZs$BMM2jE)B z90D0vuuVfoJ$eb+I-GhmzopPeywyjy_^_l7Jo2>?-o?_SPowIC!9>m4o^-cOFE2s01Cbl@pIi+j`K~YY z&93tOL}EX=nATzP$wGB%r( z>?8T>Y!aELYoDQEg>7F-!&xrfQP}YJXcz%H-{efiNG$hr0=*Z;Lye3|rQGw40KLQK zJ?A!@S6Kq|OEeRuwdQe6OUFbbKHsO6D5!1I)_>^$rizyEDo~uQWhLF+?Neh?e@(fZ zLG}Jq=R8&LN1wNk91e}9DPx{%^cVcr3thGUbORcxqR|lk88^A1|6ep3I9x*>SzEMT zn)Yj@qb>H4qo!-i6mDQDv)T$#sPAq(`M&0UaGIK=LzgW%T1$Uh92PJ^-_N(%%vocO z-VZW*`MjUsR#oD<>V{SDX za;lt)=nn2)eS^E#UATKY&KkKyP-fh8 ztI?@KQLW_iE$0(5GQRHz`Qkqi*OKG6G;BErcw|UVQZ>**AAzs_NhH- zD61+7gC6-$`sfv4c6{&p!~RCh3^ndRjj>@6zdV+fLyZPlR~0!JYJ|`)VXVt6Hnea$ z+dEq8!rcD+uVGUnjyUYJulY`uOBK`TrGHO zyj8;MGQ%Cz_zX=>4}53~jDUMTbKF8f_m_a@>YSQU69EP0zgC%$8pt zLG#K@knnFL_sUPSg>seWF=HTHkC5gOGnRI8TfVH&C*tIv$^-Mmm5hJKHD z)7tV`u${NVyo8YYWgq1JMEz_xQTJQOby?}yRU!W;m6oHYk*E!id8Qwbo^Cg1au;*l zLNSx8;YcMK+zQv5NM{$zxb4wPn?ZJ3?p}%g@`lDsm|Yq1H*JzYyJWW-)g^moJpL=0 z@&r_i6iNF)mEo?vAk&HYD~q^?khlU zayLnqi#IN}eis*VNSEu!Z9TTF#qqSbE-y}?#r%%nir?%r7UT8|D&l_Pc^t~ zN~16iHe6wKUJ@r!OT8!4cw=t%Y|(j$gPFb5O0$5es7~PlM%MKZzlWQ z?sPTvVyY3hP^-s;D>5}wLYD{F2}g!CHbsqN^WUI% z1wGSdYLK|sJ5yo9-xU=H18uVuD6VaMv$^r7m78={#&KEceu!2)T<>c1z8KW0h=U7N zXe3#?IvZ{_?9h;l&r){Pe@2l{PTL7L+YW9P3rbRU!Og}OGUjo^Cj|lJ^m;n|hGF|C z*aC!$E@YvqhQk$Cw^{L9kj_y1J-VhMH;BFJ8seLnHh#k|sXM6t8G6+VxP&;$ci|{cAGbWY zw^;n-w2Yb)#J9mu0var6({B8-@t3X?y36khD$0YyPA|XP~1gt1f1yJzRhNxRrvh!ATUCk`E^pddJ0E#IGIj(hN^wS*l{% z94eyF4B8?!r*aV!(t4hu7cHn^Lu7Z&gIB5|)JCNaU~yoxsYfj&QOjpYm8k0$dQ8m~ zDhp;y-CQmo4y%=3Bg^7<_?fA9X~PcKVV&P>{GHP|U0EvC!893Wh?PJpc^q zn`uTkpTu`@?S?Y%c&|rJYJb{!$faQQBJY3G1zu@Y!w~!xNa#}0NqDQi$Bo)Qu(*UZaqC$JY?|{f%-rBj;qIg#V8;5 zxYUn(az6`gqn`R*8~%TvjjL)+hB)YZ4@P#Fi+?~H78sx$&@NQ|AC7g`CYYF z9@SD|$r^cfJxP1}GX=W?E*mx+IN(Kn85G$bKiG-i4DLFfOIAgNF8OtIgFz9IcLq^3 zwZHRomi#)q!OzG*QQvWZx+^YM{#+Y=HlN~^tF+mTUcBMruW4Cx%&pE~ZhOJp?&U52 zRDG(_Zq-GjQ5v)?O7I}a)orxH#rLQuziFA%yyd(o02!&xJbDMz*=?0)o$UB!*AAoU~PZk3LT7+6R92h?G(E@y$P_mC1i{FFMocs51Vu+9y2ebve2R@1u+wu`(c zNxFqorS$d?JvTvH5T?)Lk2F0^-y!e#P;>! z4gJA)4W=No{r>1V+Al6Wm>X%7fR3OKmuy21()HqU`KX6K)xrfq8ZK|355oDH=A&!4 zq(!o6v^!V(8D&}hMp@P*Io1`SO8#5waqUYRH=zN>V7M?CLwz|6ty~UsA->}iAxSH1YlIqf{kz^7apZ|}IntQKE?0_OI>W}i31BUNyF1}Y1 z)QInWmwuEsUY0gqmNveZE%q=4BPJMI5N4GB^-|?RCyZA51405f{Go!Ri-DqE6l$Te zsGv^$xia^+(9Q}}nJP(HMQpTRhVyZ<;uqr#ha7Jdi8$-M?=>AVT6tfrZA1mC4VpdeHHofwCLXm)RW>pn<*PvZcnai6xQ+crd^lxb*-qFZ{pN>U2*^X)8 z8F_)DAX3H)>nd>e99QV52>IidnooLGYw1AQAU z3*+;eZn?=JO8zkv&*U7HaZ8aSRK> zF|1u5dNbB@{dr)fQfD7Z=0Yu1L80ivFbp#$ns20o?M0TWOSFQLcRWA6|Mk}d(jQ5I1Vit--^-TLX43=NP9QfG9yU}I)ME;)t zP};m_sms;dahr)!TF!~_I&tJ;U(? zzb8^MQ=+)kyPm5?5C`K*5I5e|TyL$I!5gAE#A;?hNAa{q#w(~k)+V|44CtZ3EE7zv^3SXz_FrJ2Op0_a0sqZ>2ExxuqZ_SL8mAKa^9*5+cQoArC zOKKO|S*y>$DNg_oCk#9sWLNQ@tMYBc1Z&Hf7F^=ps(ZR$*_IqQU^|+&<*)4>QhQ$h zXs^_!-xYKDDz2WprzNL9@!)#SdMA!FXP6r^1iT zXZtRe^K}${V;ql}%bn+~=voPkl7%QLm!*SFGdttg)G+GMHiRmtN@pVdr#z#=W++B$#*Vy!NQA9EWc8SHNpWU z_%KkUg(FeuZ&U^=SVWD^!R1Ad*rD&J(Ke7qE?fho4c&-|ss@RNtt1n6+A%#hBY;=Ww`$P!|mDlvYkh0Z>Nuy}Md_ zp`x|FAI>=zw04s{>gwZtumfkNdxFdWgkvG1P7<{=a4S8N{q4j-C>L_`!q z!!49l!J7{v%tsu;m1DF6JYJ<=xfF$13%B2U-m~WRt8Ot0+(`lxa|7OF&T=$3n5QF` z3BP}j-ZvXWuDg-IBp14Ta}T!Ov&tSE=|QY0=k_K!outY4)IE~J1Ug=nCf|4Q4pYZn z;yK@=()6B%N;64O<47rL97BnUCqF5c05)eEAJH^A0)_XaN-5MrmG0YhfbeAh`q zG~bFuz+8^=$2-E1J_i-=t5Y?k&ymzQ)tp*G$}gy7!xs=?RIuQqaU-oP&!SK>UxF`Z>{LNeNV7?R!>W9937>(ic*-@2F4>wGt@Xr+1>d1r5Q!xqUJ>SxvtP8MQNesK`5X z(zxbfk#b)m6T!9`HT@~Yg);48TLsY&gjks0N7^4#{C zp@fDDo`1|R;;9)$95AAYl?uMtnTl(jWwLh0-ccC+B7mq-(9TAeJx`4ImfGhQ!+wFm z{??q64=uc&=PIEe7sk3_&#rvTShqf|d|oINDCq+AJ`{l_J7KzGTpwY&Yq2<#A}nC9 zp$J!(NsMS#YQ`8-SfW|{y!W#^9_o$%5E0<_#x+mxs(L+)fYpXVzc;{m5|hCnSOx|;!idqEqg=p|^Ki}SGI=*#&Bh1$^wWXS7}EK}TPtT^9J^C}0b zYPy+dYIi!^61Y_AG*xSj7ih^eRTsW*gisDO8i~`07AIj3CywKhbMWPrT`N)4vxEB` z{u|ww5H-Uf<_{Z{pli91X&O$Y* z`idRY%=zVMz_9AG^9v3M(N<~K(Mu^kU<0KlNY&P;0zI6le9ZOO0s2V@`EWKpYbC$~ zS8k&gPQ4S4mv^9VRk~yrO-xqwuT{DAhOq#VryxJ@7U9@t#8OUlsVnVJMlwn?AnRcW z-3`-QpuJG4uo6W#oOX?`=p_^y>*Ajc;G+9+@~yNhUbLfrt7yvuW<++3)3y8dT6$e)BZ`G9?bXOwAp{kAQjk4!kdFs zFiceNUD~DDq=Ml9ZH0oG#oBOjgHmOnnAkyGha!eT#(4~rPK8OUbH%A#*F=^;MpFub zN$Ud{%z6BgqJ{C>dYHk1(X~vvXx1`3r0AdqEHNH(OQivLchPA2J0FTl%6$poieDK` zSCFO!g!&4s0&>wx1GuJM);lPAODd(cl>Mcp)Hp0H=v0>v#N)`Zh02^c zVpKUS(}^6TcDk_v{lHG#1{hTiM|*OO9?Vs>u4*I}RQ|s|#JUU<57T@s3ve#8c`Ee!irn#%P|eA79x->WOPV`z9RzpGF$9#L@B zCWWZ;sjOSS6-VWGgp?c12LX@jou+tHb4f3MP1QbAT{PLQQTsr1g)XP-t@Vp%5c!jB z$@k=tx7l%AfljV%Cp`p=~PyPU_+=XiW_jI4x;!DQ}Jeyfu)+vFAF)j zpq~vn7WW&>7>7#f2&SYInTOu+{GI+J{gO1b8oX@Pb+tK-fZz;mxG22FRM?5ePz5BF z-vVONqq|wvd>(zCXgEd#(RH|iXB^K*(By-Zo9=9Q<1?P}H+;)-wE9>*)uh3Bc=sz^ za|U+^q0dFfYI@NOD`rp;3|V>LW%w-TDcYw3$TVs>PiYK1<|M&muC<_nPXjiEdb;$! zD)ptxf*ZMc%I8T)&Gp{!UKUv&=TOB$Ud;VLkT+4};f=k0V5W@{sHh;(941G}C@7w(YY&6hf-*wQXkG0^-Dh-{C%IdZ& z-iPVuq;c@|%4MB8{Y%awbs#v-*=YT9>11`I^*LtiWnOH3XfwSOXXiJu*;kj*TIyg= z6e)U<^5x{K_fjbVlz~LdLHFJCzteBX99)s3)s`ibFH7bfna*p?8Cc`Lb%-2yoX&lv z2ICt>4MqXxoFbooYOSDbuPWiV2ztimuwYSP#CqT%P{@s0=?~NMM9?yyRtGa>m`u!% zWTr1O})tbp& zLTI%)Fb?#r=hG!(LA>y@O|RL{;o9f%sQctbT74%r*7XioGEj1HY>DR}4kAlD;l-OQ zD1JcDCXHjA;SSnMeEIpKLx5xd2eRAPb*@x|GQxj{z&2=eTY&! zVe`RXQ#U_+m@;O-+ug>1BQpRTnMQAghTVD#u|<B7u-je3mg3SsQnBk)?&YAm=@jdw1aFZ%pH|c)%7h0(6kJF1B|Yt=g{oXzwDGBP zMtc46ZDw(4Kp4E(Wm#uC-H6IRo2f;TUH<@?bm76C;=h~5bmJ^4DP);^?DV~rdgEKq z;*!8aZJ<>izMWUYl ze$Jt(5Cz{dS{uNJ#UHQs@=f?-zm0qFYpCX-b>i3cPL{TD3O;p}F6dV++Dh%X!lR(i zph$r5Xbf!gX|}+B6HWMUy9+RpM->UbsVK@uHiI>@0aB2A7MD?`ln_X<=O)n{y^`={ zEct)i03_P*RR7)vm|s%31z%a9{h&zYb$UaPkMuS~y_cc?KW(uZr#%rLFoagB@Xe($f69rQWvx-T3&hVUntLgM^`$L?HJpiPTL} z)g}YEXGxY+wNyXj_jGzABjb6PIL5BO5GLjohKZa1cbNE3pg(!cLVwk0tOSa5YplZ{ z%E(XNzz$R=gFtABPA_s-)wbZw7ZYfqPd(Y&Cmp67FBzFVMO)4D{gkfXwrH!h9ECsQMKQF9zw~QAN+wHh4nPcE9J|o!YwB0W>2=lRAAr)t zS}ZVmr2uSe9zy$ZdZj$C-dqn)w@_QCyOHcpM2ejx^!$*&Q|SsHHtO5ad;A@uJNdz{ z7JTbH?Iaj=rp!+a1YU!yl*-#`CRQi@TtA zrD_=}q?78^o9eHjcM(q@{uL+xz~_Zg&09^b1lUNhP#LLF_eh0C5l5+?KP=ClKUI5M zdw`}F@npZYDvU>3xdFFC)0PIaxJ?MWQjSM&tcRlM4iA9;3WLug;t$=~Y@1=Tn+OrH)^<5L$7!9CJ$os`(n>!uQ^H{9j__Ky?#!;<4) z8hnhMTCz4+)UH2E#``;DI9x96HqmQh5_J-uBs}zl4>?b82t#R*!OC#)P$Nz(g*w-{ z25q_nNDznt>23E$bXRM5!U}Y3BSQ!d`AdT~q1X{vFRBZwx*EExwaWEy-O%`Ye zBag{}c1w>>J5LqW=yUBs(AcJ>Xamu0YrR?0?TsK(EP;x!ZY@ll&QK9ux9@tNFY+N# zaj-$t2;*Tq`gcRcZ*rZy$7Ub6O$Zt#qxDkYW^9LE^7pp(_+$ADZ3)yfRqK!Tfm|JF zJTLZeUzJ4dw`3}RpF@$dMB3)mbYPYAFsx>b#BOtywBbyfj4~%ET3ha+w?#B4n|KcW zrRPZ6lT_Kb7s;gg!mq8fmMuuMQAdxLtln!P0H9Wv2*BX`Q5H-aP$(fRguXW=G{ki3 z_`n!zY|j9KDnj0{8sv>6DkgPhGbw<8a6`BSZOj$c9R{!k)e^9nZZ>V=Lb^z=srJZA2DxvRNxGdMG$1Tk&O;p-; zo1z@;)9Br_zwk1TTT=7~0aI7$PlRf&mm7*Gvee*COb{_)7*$)X8Qctf1*{izFal!2 zpF&J|td|aYX(3J^DBKI;#88BU261A`EF0l2(09thnA>G1a`V;=?81!HP74KULDKcE)>hSY!Ssp1!fnYQxoC+-UL^ zgodxKqnDDC{70yd98U*%vSl{h@M4~l!*}HPIp1D?*cB{Q^zMnV8;ta8v%@gcxh}W* zZ}@&PH=0(MAl#NaY_V}jY@n#zBGgEyf$0?PDRR-LRnGi7s~EMF*lW25ekc6|uJ0}_ z`tG4~y0`I!wzJue*sC&a`pD6hUegmZ181Tv6eF-vibVBdDlKNe?W2K6v66XRH5j?& zw2QEM98b;E)p4`&Mqd9|A_oXDE`)2YXK|7aAsDZNF;x14dW=K zmV|!A5Gx%q#dU(Xmv0~hvq%VbL747%S=Z8KGrW=FcjtN@rTNeg^?)zuD3#B;F5%0+ z8G$1xFgFS^I?;9|o?>}OmiBri$5=yw6_{AxHJeL^&;nX1B3_1wS1&F6mV%s|fcw%L z+H!hVzaB>@474&#Uyl1yi;>jk8qkj3YhtuRIhjeY+6_b42F;Gm9b82opQ%j+%K}0| zm5B`_W^?%v+Gh5nv6wA);kPhbSMI9FB#7cZdXy}BX(AWlTCQ+1P6P(o63hyq?aq71 z;=O1H^qoESOki#X#wlQo)9_5~{V47Qfh{1=9H(zhfi)qpdfp-kwCCp0S9(Q7kED`X zq+IYtB6iC_UFoL~`xNn8p2Tk%3&26vr)O)^r5ce3%kq}kmEJzO$G;@=R<@lBw%PQ1 z#<&F=(kEnU3!`{Aq(>=}VKQvjVN(kzO=p@Z62%2`9fPy6-N4$E z6VApFgR@bkkh5{a1Bl9XV^WsLULyvc@a+WOkJ$q1K2osIhQqVofsPoa9%IxBd|J(QJ<|?*zRBb402bL$SzyW0rX_lVf>=F#+C#RxYLC zgz(u$a+zK9wTEx(EumI5tj{M-jQ3XEGT6~(cN)q|fCqKpuO0wKfA{7EiyC~j#1>_}_w*5){5yr&_!W2?H*e;%CNN`vL+x`Cx<2E5I z;Ay

k~yys!&6JFg;|dris-oOJ`wvd0TIza0?jZzud46eB?YjZ=gCI6{0JsI0`% z7aU}bbnqAWKZJ3ChGE>p=!rn z9BScco(HvxH8MCKDb^U+U$jbehoM17sA8d$aVn^hj&*$jPNw>$#Ty>r{LyrRY&eFK z$p=RPSL$5W{Ok4$&IVrKTTiO{w)+5<58S}T^%K1@G&>Tm!2WMDETH_x*|;|Dp|=5N zUyi`d$kkAOz^*v_wVPZ#DJxJ6Y%NP|Jg(QD7(S~u7FDkC$!Q)wqrY?1_*}`$i#Fg8 z$IbbmLj42+tMzj1O{d8olrtE+ z58-VgO~91XX^E86HqV*^Q1j`%_@ME6tY zJeS=R;ub1e8G;6y5UN*{C(nwh69eRuR zCDO3)+cq#hBf46e^sQahOEQ+2Ow)uT=B*{(mFgPyQh8f}5)= z=o6&9szK;O{+8CXfGx^N6c+Br9k7Sm7?~qs(-@VyBP6FO6s2fyaJc@4kvcL!f9L@V z-NRr%r0)%y$PQ|wZSrD(ey6W%>we?0-c3zCe|xC0fpU!iw_h3rAhE4c=Aw9Ej>x;= zd{etmH(l}^`4Ywo4c3$f8=DR8rLSw{|Ah`pY)w%{V-%YUoS(MQb|k-ujU8906iQ;x zqx#(qV#ALVg-o;hQ$9v(ISAZ>FdM?>erailt|&aegN6@CcBX|rEZaLRr)G)hS`lz!SE>yj_6rs4~(qUzus|~M;1Fv{eGcMni>rc!_UHe+= zxWd_qmvAjQmzFBGWQe}U5UuxMy5eT9QNcg9_+&qlv!BNUJ~=%y>my|0fZ#YaN70s_ z!gZduEm>#29Vn5k?~|$DR=G`E3eD*>7tkhJ(-7-Nykmm*wG8?|j^FnIV^Uo-&h7_? z$^u8^)r-?4%J=Bqxd6dStOZ9{^?2Zb%UlhnQKxE;A*$UMu9-r+C^p)`*Qp(1 zDZMqeiS}#-Jt6F?&L~<%P0R{uKUM~=j^W`Ifs$SK>MJbTWNo2B$6bKu(J3V9i>8V~ z!nl;|OHH6RI;Gum4^9^}ZYkf0oV|WZ5<&zI^V!es1}CBy0P3ML0l2?R(Qdv)mFTh? z=ZLQ<0xgYdW}Or2n%6O8S$qi!qxTkXr9`K0;iHN+p9X`GflMMpwT0pOS3Df73@Lhd zd$%@UduZI=f1%P~tNr%YXUvB<&+A?q;VFOFcRriOWl|6VQ@S9QZtUSxu=JlE9f&7t z#$7FQ+jpAR%V0sgM7?k?RL42%RPPxHv*Tu0)*1&&D)v9Yo(rNUQTb;wwI=XH1G4{7 z5QVO=y_HP~S&>w)ZO-m2`})O!V%h@bDSwfr9ggJ1G|FcGxW^-^>*Zgm8SVGz#rXi$ z$NE4fBbUDw%`TSMSWbs6%ydG+KQXZLmz*(1+m0^flgg zbdHn4Wnp?W_GR#4wOsmLPDTr~iv`QE2R}*!xb42zl;@i)Ajb^!67tGw5x`|eeqqSF zL7lz)H{{*)>fwkIqZ?XhH*X1ft7573d~k!P@6O5@od4LNM?NY%72R~PPcj z=VD(mttj~w>I-C$ zQxttQeV{Gy>KFOGcE|D%bax=->0eG!DMc$TfKi-kWor+AG3o(0D@lPI(+z0(!0NXy z$gy!L{vj5@&?rCc<@Hp`fb;C}-ttm{;l#pK>ZKY8woQt@of1rUcSh4e$JMv-YHV{$ z%~*)L(PJe>E5)4wo+r#$c6f*gaUH~AK7Z~I{rh# z0bc*u1pH%RMf9eAF=+Nb$KTZm@Vt3wHys6i2fg6j(J)fsD)=Qrf*^zhX-3-UpYk3F zZ0|nZa#`~&R1Li^f<&}=tf*FemK3c>bqC${T=GzB1O7{$^Foop2NF(-F)iHsXwYJ(?{?4wz8-=6l^(d=qE4d^C9}za-hrSj!E2q7Ax~s zcBzzl}Uxa z&z_k#GMi?g%uf3}KtIf?B-c=Wq)C!qgB<8@i~gC~!6?0(wHZxRcn6iC?Wr8#dGwEk zC-QCu=d8txQ48L?$h$0g<;)X$30qu=BcAz-&Nyj>-o&WyS=Y7W_%U?{)uFoTh~7?o zp_gj}*Qtu%&7NdFTFu;lJ(DfciH+Uzv%?UJMS7EKrqOa)f+0E#vq^5 zR>>guHuwBYt%oJO8Cv*+N6+J~Vu(zWx{#sLS?k3`m!+u43GF+fE_kTbb}D`9im-^v zQ%&`4^-q;fn6v^=7a|R4Wp#ybQ#f7m>TNg)dpIxUBt?DCp)Sq?qhNM&rSbflL0=GJ zp3o#NBh>9%Sfq1BpkxiiRo74Dr93@$HjQ4zEUKdp_w5u9AMT4ZCF!3T1ctQ==hCZ` zou)U!xw1LV{=7%upG@-qKwlnEKbeWZ6$AuHlboHbZ2wU7_b8VBTM z8#v4l1I2~|ym&YD($X2!t;b2+E7cJ&vN}w17M_A!>;&3L?Sdkn`Z7kr@70?D$J!b= zJpQ_=1Fo0KTm6eJF7XLvVvSCGba7>RP?hmJQb4Nv zjva=p>zGQfr9MekrCOmF;XQSy55YsbXTz*}p~@&qQTPfqq+E~QoOfw$ge}oQUx2&* zUCF1^UAXIiuY02FJzQ+mq5|dOqDxEjR?JE^)cXkPN!WST+)NZ}`_V%NbjR(DZP@#B zXMI?;EX|bXI(i>t5SIImLASUAuQ^?@>+qZJYxBK&9^ZrCe86QCFv6q=$a|dOqYRpe zX^X$!HI4*9XQ&vE42ToOhu-s1O9O|zMfUAj(=B+hZv#QU87^>Mz~a^STR4H_7IzoN z`3RTI9PgueddKjD*F0xEec|3q8D?I#~FggCH zV9+AQG~;p!xD$eFgkLm1RP37R8?QMoVr8M-NEJoahx+#Az{QGx5pKi|{01BULHI9z z2fmtzQVHtYpxLN3T*`Lb_>w8lXcFD3 zik~S+vWedr%)wOO(Pi||0X+<7V?xc3KdxHWabno7UB9nNC9M)ey@%8o5<~eUlyOKX zvr|H*M|w+)L;g^H&!9=vx#qYJpuQ3LXuXWE=a781ooIUuhR83;H{|x`6F>ce+n?s> zd{-L|K0o7)m*TzVRgYc6SnrUrjyJB9I0G_3kK76)7SbaVNdwG0QKGCn-rHUfTg@vT zyAG$DEa?6%6sE1i$rv`(@M@2#lC5Y+xuNmlKoO4+F5T*YSH5XSsi{qW zjl$4O2f2sIOvl1%kBP7K^h2SQ($Y3+FVpCR#uj$#UqC~yUU)52ovO>VjGYrgpI^&x z?`O9%=A6dGjGg6TM(7jusWwO@`kQbSIfB<$0TjCXy1MnKn2lTJJG}sQLAy^|s7twJ!w&AX{1TTwVsx>2Gb8!7h+Imve+*FiCsj67FJ854;3` za-wS?=>H!rU;99mTw=Idy`rfku%d>NS9q8p{(I_SW-`Z2I%fj@Pw7`|g-P4G=6Y$7 z^dD&dma37!5siK#jV>~K{tD~1VGh6ESkYUNMQbI?p_Ng`#uCoDcAj*;Z__rSzJ(yQ zHhM9>^sRyL7fb$)uD7T0MtV=nOpXVpf^bvi((6H26sASjL!6@y>2FJ`~Vljv|0=|->1dk;?bNqhm4W#F6LWpn$Pj##CgJ1^jg9& z*yr`;?xR-$?Lv;muy+L7wWIh_TUo;NwxrV{=^bslM3|D-aERN+(KfUjiOzvNJWD#a z$n0DNG~bg-qWP+l{=GfFuXuITBwt|tq5+o=2kLYipaqri#+7>b+Mms+WCB$(k`vVZ zjumz4o#3+6I=w5Zf@WYXl+W?u%7DI9UGyGE9IXQlK6H3_yv6>x?%robtiLW7FE>5E z=sRoRyvno{Ni?Xrm%qg2rtbd5dOc;q`U}qK>4~59nbidkJFn3!xdT<`i6mdvM&V#>aa>-M>LgeD3N*c^|b4rcszie6?yA?_Y385f8!zzXelNBv)ATy zLZ8MMa{1}c)*GkhugiAY;S)V+B77Xx^YD1qAUypmSloU;uQTUJ;+v0je>~9n$=ZUZ zxMm%v<-2jsiiWkX@JcIHB8I6nz$#e&l1OreEyMi?SnI2z%f_7Bg_h=ixX?iFUxTrw z=gw!w{v5`h3uBvocRn*VvU0|94@C>bMiN?xGP*!#kqW!MBM?uwm6~Gs(FSIDB7P=@ zm(9fkaK^dxI4Ix~1vdEZWYMf=#z-F&D5bpvWArhMvDh4h3NS{>{B_8abRmXQJxaGJ zy=T7#m6n+*Ro-Vkp0QxvMJL_UE8*HCS(3?WZKNgz;`&{AWO<%Zc2^9}E9pI`KV>Ko z#wC$eOP>rBvi!7YjQAQ+^BlJMDUvqhcnOm*r)o#X|g&hJ5m z6Jw*PNqxgOm>Be0sL}==z5>@o4U17#e*{1YIP=p-A6HJQK`(XY*0wEN;|_K$nn9Tg zEq3Wx*axik&!$qzjty)27dzB$Hnm^}4=4G}h6_Ij1>g-haVQ<3U2 zNn}~l(>hA{>&7c`pQ>Sh3_-5Rq=?s%hCuKNX2FZp?Pq0Mdm#gDO2VZNWLvZBjl;t- zWM*q6jmi@%4fy%wXbNs9%;opf@-k!@-H|1`N`3rnCiPYU{DPj{Wg)Gm7T#yN-dkK~ zudmIOTjSYeq8h?v&t1$Ru6~ z$l`641eK6TzX%Nf3nQP>RIA;;0cr}4y~e47DEZ(?aHpsLB^FKb9m|@nQh9X{v@L?h z`eW^25w23=3kQ0rxd^X6Uxbf#vo}@gUbqzAHH^%+puKngx;!V<(g!Ow;=Vt4(Ea`6 z$El;=emh|_65GCw#I}vz3=0J&UJ~2>mg_eX+a934f{EXT+q-JD0%cNp%Xbd?imoWs z$ECju0t=OOi00HvHsID?O2h_yKAQUM!5{rkUU-~k|1F7{1}cIEm_#L!Uw(2DKtI3j zvg|(b)!K8|X$MRlH2VYW#FGJqvj3U{{EG!&;r{w>yDfhv&tHEIK>EH@`p+IRw=(^! zU03v?HRxWu{IeId(8u~a1y2MK_%NL;-s|}tZ3iK>@2Ly7)u>GSKO405sLS4O>f5u2 z!AxLo1U7(oZ^19PuikK%i*#-La0Z-4=b{f~fsp*dpA3}{c)s?0q4>Ik6L4is*PCwvl znSsVpyt)p}Zm0iy0eCx!izV-pKj-1&#Er7@)o)dj-zE!=?N98DxhT z-CvjgvhkaLwi;c}-wlZ&(sh|PtGTcLxP44)hiN6mt86ui2#8PZ!XyO+uyds*+Ukgp- zH!AurzsZCquZSk|zd7&J-URAKkAo3Ewb>7!r63nTWp@QscDP@-G_weoApC9}6pPp2 zyFl+e5XjmTTngVz2RYtr4wW%)hx=E_gn68Vfm(%uO3Kt8Me&R}G`5|-${46uMa501 zivK8lAUOpWKz!FO#9y(pv6{bF)35~CW^<_p&{+`X@(YxXt5TBc8ukOPeP3v z{}~Fuxn(Y;$1+=Mh#K>uhUTgviBCHXYHnl_#_nz=K8M5&&qZnlkmk4)SvQy zumLi(FGWgr#NGg82z&TYRBDL@XYZEBFk9~~{w?R)i^})?E*V9rycR0Y$<%(1;?L{Q zNA2`^hRRN*-xmXB55so2${64>&j$EaQ}6TGy!-INH071GnmxdlrPJ$nCISEr!svi9*#pJX-&2ujNF_d^G=M`s-ixpFId$-A1jOLTx-e zTmS2z<)(MRdLQ=6*iXC9?ufl|zjjmM9Bvmw?WD+)!$FH1l(*-_}wY+yAYt>i)LJ zMK#?#&Wcv_lKZSjaUf8g?;0D}*EB-E7l+^6(AKul*I)xHXV-dCo6QjzEJD`<#+=h2|?%ix+Y&gG;*91~7g}1{h?J6ifgB zzo>;>VvfOn?OiD@nt;5AV^R*LUWEl8Kc&?_$d9iKWkO}--jz=a`xDSjg%;0V^ zwsYD+lTGGKswdO<{)QKa^?R!6fq5HpFWYd*L);b1wyQV?G@;#~3;GRmPx z(|EjJTlu_fQs;CLUetRD^!-&E>odaqR{7h9^!4$~5G1P{1w%q!A zu5pWA!h_vi>8b@U*3y32?CE&P&Dr8d;0zHr3=yMYnlK&@5pA9uek*PrA*TuC;NS_v zi=gd@j3KBw1ZmcWg$U5rK!6T5>O~}{3Ien+P;Zwk6_`$$fx5Y!4{~3`b}qU|Uk|7m z7;`n!j{$qG3UWI9>@rkoZLDuo6{E|If3@B<*S9$ldKOOBZFtY;PxPiTQ)M71Rxhcr z$wb>jktWvIAfkO&oO^(XR=oxxf0OO;6M-3bcb08`lB%6R&fKzCJa+vwY* ze!JhD_n|-RuATa5M+4=s0kz@@C{Yr|iBPb*68l*XL&53P*3I+v62DmQyA1_PVKo^B z`?7HFdALY>90|q9HK|tQWIJau@c4*j*x2YAix^d8- z+vFg(avpfBTy(YO9SK%@wW0z01P8S|jrr2kOD#P{Pd$jM2XUN!=qJlA#87`Bt{ymT@az%rCu6l%iha@`s^GEU8$3w=b+_ec+Wc?j zCZx}lezOL`Aq}SGihc41t{5Yqp^AF1^MTXR7IJMU$OXRyfE1`v+I!uMXyW$cj{$?I zf4d7g5{#=c+7LLc7`Rm=m*iO&v^DK`sHHDQ@|U>3KpEeyfZJQ}TOOdd*kd`8HXjbb z{zp9y*d+eVsrMAW{i7N5Z}FpL*U_)OIqi%VoXjp>DBn^kBfp46+plFR`tD3^x8a}; zi%R9Zk7%7OFVpT@T`=92-zw7rSHW)_qKg6+aUO6y92=jM7o`PDNXgnB71zc+qA{oz6Iy692iV} zqtE-Kq6F0rq}IdJ^~ZR+rurP9EegVBYE7kizjd#($ zYlWD6OrWgW*l&BeZ;N$`0C!lZWX_W3L#9f29$XGXb{n9HMll$%kr%Wn?RXH3)Eq0V zpW(kZUvyA;Oqp8Iuv2}p(*jYiLXfC8XxdOiy-k64Y{FSiZoGrPB9f(li@H1 ztb8>n;(V@1ssEwKYU=EeaZBp}GdZDNzSpVUn3hL1qqmV2<&7OaQ5zcu5{DW=aC{%ezcIW5A`~HvbONjq#Ez$ZLX#Hy^*6DX> zjh{j54=-q+wd27sakwmq?N+o2Cq$`VQ_G;2LBuLc`ryAvhO(frLt2 zv-R#Y_r=|J9T(q?i*Nld*EBdNuW_mF@C&87(`$(2ZKvQIY^RJsz7{Szo_eVYIJ@Ol zAN7C_-9Lopxm0A8pwK`wg{pgbjK%&%w0?Q7^$+)a#8Y3U_d!_y4tCn_v^NzB_3|7f z7{Ui|;f&B;1z#=pv+lDy;{$uOrwTZQfnheTV!@w!RrQ}&ET~2STOD-gxVL*uxBZ!q z>a3e|vIkA(UgEz0n4_f!>MC(mw=M2+t8v{p>`*aOmmB)E4PjtRH07yE%%{DKP<5Xb zpQkVn&(*^Y%IEGPTE&2VzM6AA%4?s$F?$F;wU?@Tc%&Y-*LpZ@{#u_?d&wYqbb^b2 zR=MJrh=JCYW84q30~F8uDklRbJF zMf-_Is7MvONC~%}4m>*i7W)(u>6elDuZY7G#}XIs-dA zg&Q*80O|@-QBfTtPb+Oi_drA2wcJJDK5*KvPUYdqj_Km{8hiC^7FsEJtzV{}t#(iJ zd~XQ|3x_ZZJ_un4W4V%uLOyALAkKR3t(fM<_Ag?3<+4IUEP~s#S}EC7ok$vL5^UZ?+!i-p+kg1#FUoR{Qm4{~7*~Xt+Oyt$NXz zz_F1IJhsr=8QsL@!#(Bmd}LQAuAgYW@(i`Fi`MR7UD?+raVQPP%eVzU;xG6vVVV6H z&AW1yUZ3|juAJYeIv$?DclTP8ljpC^avtuj*w;t9K&_eEvdz3G0j9T|N5dD=>)R{O zI#t5%sTN@Zg|)@BPQi$Ac`evgU{|&N7X0#wQ5@hBaOr(JxNokUiqd)Sq~A#`f6+Hx zJ@9W(EnzcNof;&D{8HXhq3#g-%@3m~9my8^Vx0|uPA`))l}B0aXFrVQ#e1wNDH3?m zftE_-m#t^EnH_vl?y+xu5S_|R2?(uJT=Tp&6`hzFQ^zu=jcZB@?qRHJeY9a20p))ViI zb<;bZ@_uZ{y~bxvS~m&*^X7@nzccM?`=QL^z_*dQ$YNg`1~#AtKjJs}8V$DC-TipF zsto#K;H(d@84t7CzwSp?4}QLyd-2U5EnD4R;a%-#)FoS231ze_bJ}(Isz=BQ;NgKH zU$ljqI%l6OVc)qraeCL;UFQUAq1q#b|E)#0qw>#XYHk14-^(=c@TJnFlrBK`k9_1% z$8Q*)LrakbIS`BzK=wzBR9e&mVxRDre4pl8_{TgY5gy_Vn0W*>@bIU6f4|k8Iv=~; zA8&ybDI-6pNwcq9z;IEAdGyhI8unx5nHc#eVN+YqYz;uVCtySFzwTc8#!Kav&hUQf zfbehB-TwxapBh9J9Xm$&Xq9Tu*$~(nNKst*4ONT&HtJh|aNg&0xO|8Xr5bVve+YN* z?)mGpoph9KN~BqMfJ)MEF9O^_9E#61h4QyI@KiqV2ESsN(?~QE+3h zFf$Kp`M}D~O9xqMq$dtb_7xw!17yA37dW6zM4o@1LZj#t5E1wZrCV_7R9a7NFAEp| zu8}m(!zcJLwpG7uQd$ePEBQyeYC(KXrE^+wGh2EokKZGeG*S4G2CJX>shB`bc1U{X zvC!yaZ{VD5QU}?n@vl){KE}s?#}*_TwbqUbY2ll_D;X*`j-6>PBaX-cv1-`B9kb(kq0s~e5+p#9Uo8(Z96Y;in- zw=3Yd1%kZ#Pl6=V0VfV-K_yebfRJ7FoN-ePw+QK(L)}zy3_dUkAqXW!ZP%30iR83t zjkpao1wOH8a}!N%K&h`<%62$DAm!@GfycHaPfVUo9b>#{!UvP)qO<6gtXb+?zkT70 zII}Nj|7rXCHwOiN)GjMLfkJ4co0E7QC0qF3RS1cmg&yF?W8CP$I&7PU07^i$zX!4} z4%$HRdYba)2OD?q*}3ue-*%20_U;Gc-f~js;w=&eweOhv_LWPi2md;k@N+Aty=2ko zy%esr#o|fS$|iFI!SK8mGaHpg4ctK*LgJ@`_%NuId>@w5huW~) zLv8w0Uxt!!8vuq2{|_=={XfX~6KmP_X+SmJcV`KVTg=tnPYGyQe2Ja}>;Eak+**eD zSM8{cTAL2#*JqZY@p?NXUmuPd0rDCH#88U(mFiM?2B;zU7K)=)`MM1-NUdmHivX{C zH>y&T&)6Q_s(*~zE~|PUTSZ&m;IvWHP}ZQzdv^MrXEFFda7%U>6Q5luOKC>HGIr~x8keRCQDDO zt?pz!@$dm#PjL4SKAb!In(jd#d(iY*H2q@3JrGl);j=F|&*26Pd!6>LSO3w%-RYs3iaQj~NV!7)md3mL zXp!HZkH&wK#-q_V9R6gp&1kgwqQkc{f5f+d*Y)behXO$cUN_dj>%tZLJ?CF=#f!xe zM>^mMvfzi|A}7HQgHSM5?~5}FzSRvK?Pj24Jph%q^*sL`oKqe7-XZZIZN-E9i9kU- zR82=HPD4?FhJ}7gO3RGlTR_g%B^N-qQcKQFVO}_;aHGA~eKZexs78B7q`h!y@9=-^ z6*}&4(>)!Adoo(4aqxh3953K%k&OHfR_q-ES6dO5q^xv*p%oF8^SS#WU{37*Qu>w zW2e!ddG<%cr^CRabICC57gEI@Lqm+FHFE6((lRicIA_8je1pDZH(33 zQ7fWwYYI14_hFi45mef?JO%NvaSC&p3;eL*N7iRK=|~f043_S=dB}LV3MHgE7~$?f zTy;*>OK^%oS6Qk3BfjGfe233{P8_?Oi-UZ#d}PH;l`WbP+Xd1T$<>IcfM!VFD^XK7 z=EB$LJK$+J5a3?*b>rMsk?Oj6q7~obulHF`x)y#8b-}=F2$Mj zfSgLUAuVu3ki1;I1wEQmT@O#>1N*F}U=7ttf4E?cH>6BU=a7{khep%LMcYJ&qtSXL zK@BFdOHZ_f;}-SkR7|`-^!pZVt&w)fukDjZt*374Xgr@%eW)|vM@3MtK?N=V+9ZoM z4NPr*gf{lFL88zzZR$fCvC7_P{?X7#o+u7=0BW;ep+<4fGn`IfD__bdd7assWbDxy^J@8I6Owa zi8qE{wOECsy}U%vz@vA@f^PxU^mh5I`>YPQ8C!xJ?Biws`^$rky2vGD(#Y}Aa?JAm z81u0Fs(uUCpgBsHDcxsxHMZw)4}YaM{>6IPD}XzBc}|$p1A_27^J%^De(TA<=C8l( ze2cG}SNJl=y15@B3G#I}ee5oO$+y#Y*GDUWRBrDG>=*yl7jvr`RX|&>&k2K^k15j4 z3;Dq>Rw{CG!8bt6s9q%wf`IzNFWb0zHa~!%GYi&TcE;;nQR5odTKe6%^$u-aWBnVR zB+tx78h^5SX|@MK_vYMyP`p2eIRbUHca_dly3dk6&BkWP^YzjP(WixL(I=lriT_-T zhu@ifDt*9u;*9jE2MzxbJ>|Ud6{h9^m|D%e&(623&sX`_3{u!6+K}<2t z5UpN=Xdkj0q;G)iQIKugbDAl;#KA&)+Ak#W*)$~v7nl7YeugPN_<%L}+=BI2CG@GM z=!MHVGN5d8~FPOP22c@636(&JOfDi&FpL-o-?ejf+o zB=oVPV!xjxowUvp>2^q;tJjM`C#?{_0wfI=m0G+B;t_pvmLLb~b4R_tJa+@z^64@KIe+;{#MN$b%Za6njpx zs9_qREYz4`+PauF)0VB5#N|)2UWbZkb%b|a2QNr@R5YCb){^OOlzB`B@ZdaBgaCgE z?lp86;nJt02$B3$bRe&n?5AT>shl5{j9?r zv|jIh+tGHY9&XzkG1S^BwgFoP35Z~OavHg92}mAwsuHqwTlNVS3~wi=wX%YJ)HfLL z*~8T&rFJU4m6nZ5y3}6j4@H?-Iph+{4MyQT8Nl{@%SPoOcD6ZeC7|6>nVU}*a}5A~ zlV~s9F|fnCG3Wns$c&^!q%Wk>X$k310^N~(04t=vt*?U~0t)extqH$^MAe^Y9c)+r zY)MwVnT-|S=huVnxsnFEr6Q2>wJLpjPuhZG0h&Ee%+({~Z&8r!NCI}=w^nsMsg9;; z1C)#tCCk2`BnFj-O2RzKqaNIodsyf@>WP0YrkC83q^~S~SRqdP$8Et!@M;7+#646D zqK^#>^aNn(=M=QDwLd|xocKA7Ebd$By_4_I8k?Pxo8ph%DfzGD*Tw&A4wOifoY$O8 zpUXfGbm?EJG!|=vs;7h0(ZdUNXL)}%b<82F*p^W`UyY#^9Lr1j%1H|q zd$0&aYn(IF*)pN=?AqW_oYDTlg(yE|J6(#(|0`4LKz4m(_CK#!%OVJcudSTY*F!OO?FwDP$LUf2u!=z|s(xq>=V1 z5+>(m2bxCk27GyOWPXV(3oG=NGQLJDq~s2f9MB=qW0|Rk9eS*V9?H$dh92>Jw6F+2 zAzDRgsJzrn_mkuvNG1hYzxfVjKazCWbOWLeL)5TrZFB^`4N-}adS647Rhdw;)oiwb z9eU#lB#q{)aUd2$&}S!&OwAi4ZFWzi80``SqgQ|h;Rgo28o_AM;SOUf^Lxmi@|yQ= z>EiD>5SvA%a$r-+fK5Zu8?mYEVz^Z?yAliu%gnB9APXdL2bpwQdu(FujZN%+hISE~ z*hP!BRJ&j%9Dh#|K+_~xcV@P>(+DU^U{GUgz9^?AMe}3S|dF z_NPYYYC`m!|Ey@wc|g+zJ{3hJj6B=F-}u|b_aXeg)&Bc~a0{?k3$!1>`h^DlBJ~kj zGz=PioUP5kd^+aAY#QvjTR55a`SDa_jPD^C-}NwhYPR+?fqE}_)a?B{q<%o>j<3RL6D@IE0+Y}7Qm5Q{E zDSbST#26HuJqd%c%(p$;{(CeO`VIimicS^Ru--BKS)vHirJT zVe)Vb8$y!9C>F3c-S=WhGB(Wd|7S>2Ff}lcytN%53s$GkBq*UP;Ob(Nu^2zdO zJuUT{^j}^KR?dkZsHPxxHKLVS&!UwTrU!lHS+t^V;8YHNAzHbQm)-RJ5)wrkA?@Qf~{*!pkpQbi|>x_QFZg|aqiEBHm$yZw%t}`LWAzw6pQqEGg z&~1I6z74%y`@j6w?Lq&){MM~xt|4Vlv{1^g?Xdql2rW8YxG?PLz$32+F@IJD7R46+ zwzsbk^zk}LU*^y_AQq^t7NyV`^6Ir?=p6R%zxYvxg+NJyyABa|J&qMFG7}Y_w7nWj z9C^=#9Z!~Y=*@-5T`_ftKsc`D&=)y0)^ER$Ow7&srj066IxW;|#L^iq!|A++^KE)5 z?iqN=rri=}FoMHl2nCOk-`Lodw|J>m>fqA|dagnh{9QnguJKLo#jN?sbL z*NCUn^&sOj$Y@T*A;gJ_3?P=?)aD}A^vPbFp?%dtpUWe)eB)f#*^?)M_IutdVx=E* zs7#J2lO$<%q?k%U2Nsy7Dh*Suf~ojN?yN{i5XGI%B)Q_Baw$bpLCx3xQur;?eyjc3 zCS%_%ii2FV7dWNV;U2#iqChPwStu$e52AXZJC(WUY)P3}1`_A!HDVyq0*Q;zohD>i zh&)5seKV-GZd3GdDyoIcu|6C-a31hc4>gq@Vh7HU9XM|;82_Be;jvI+rr*FxxxG|5 z^<(cPuQ?sYsDyK*iXj}V__h2nKuvfUw4UOyt9rp!g};H=W@JS|v{!+FDKVBSa8Vczfcb>7-_I1w_+$&gW?UG_H2@K}+mUG*Ld^_U6NypyU zTQ`i;=AcwD6%@QCb7Bh!UNTUT5~xDM4bbo~G`yF@Lk$hN0hGCE6ONKtX2E}}>T67u zF8q(o6n-^)w>!Q=??%)GiKx})eq37jys1vY(?4T+teBoFnT zNyCE6%D#ZgwNxSd9e>zEgn)cW;zRDpZDV99G^ne5g24%z$qgg{EuNIkwU8le;Zqo{ z6%~hreAU@i?|=;>ansK~CvPG!?32e18k9Jei-BcWoSQct=yF{jh=tSg`Y)>5^cQZ4 zquS;J5Aw^|q&!1^_uJ{z%!n~tXCI&*QJIgjadn6&69oMkl*Z?gHcu{of&>5bh%{No+90dpq!_?UqEC z_cmyM(ncjq+Zk!WYZkw6wdYpjqA~IhDr$-1R}dH=7_-g`#%RF!(-0V(iKXcX45sm# z6Y$OwvXqci;4wnzAoM2A)OZRnlKieG!;C_=WgEh8OEPWl1M&LDB7PYR(HG*W4~JXr zG?a_R%0D1Jl7p1m6I&Y*623u2V2E*iCXS}phaJ9v^h#GS8j#Lsxtm@W+u;%#Zic3r z+On1iO-B}nrcv%|cx6j|-27>)zbVhyyoUyonM;Uz|lfPX-Xb|{Bd zV*-Z50xf7Oy#y`hn8Q&LYAlf9xV~@$S)BrRN|X_4&r$iBO&Y#PN6g68m+v#40}!T$ zpYl-2l=r=vqRJt4%L``7Sq@cvP-P@kxv-qU3%Rfvs>nY^Iofg=rPf4fQXHD(WKv0J z@};RsQD`z3nv|D7-QuLV{4Y-ItMy1K{yg{i@5>*$_^y^mcd?tU4!1zs0&O=xwVA=| zQ15LcRBR#oaF~CgOcP&{j8j0y=`7S*hh`2X@q1Fu3TnweMmeImf>LV&&MDTyKo)8( zGKPuEy*OWsJ3SGKM6p&gBe@yH0!Dh|Sw`~8<91*_ZLvv0SZfstQu?N*c&HMLb=iy- ze=?1ASK>w5ExH{Q-L^ruB{F)u`7MlIhBjX6|Fsq=}{H8Mx95|o>7Dpv-|t%hs#*;@AqlHc)pXEW}jqam8NBj4@FE-78ifwnKdH?V%P2J;N?)e|xKKB5!W0gtOTg~AxoS7hdwkg{J*-Ie1^R^b5+>0X<9 zz_X!n0!>i~Igz|mQIn{jqM~+!1y@%!xKk{3g5T&AN1d!3KMZEU2I30oi=z*eTV+l! z1Q@OHMI>gyZ+czZqX(Qp!V1z$^M7;5T34e~nUV7h;@Q0?_B2sBE z0-i&j4XHc4n=nki?~O;hFOYKtM;w@GgQ9AOUB+>xT40wA<{6Em28MY6B*pSOCMv|z zNq&is8Ov`NlS~+X)wRc+rW!$y4?zz;9Tz?fK@WacSZPXv9!q!XhMiNZ+ zVFVcsvj3phqcR^L_jVG33}Ck>k%!Y_=refGNqqUZ<;kr@-%=TDBpfuc+3d!+$*P8n z$G~tKH?zo}zRbV{gcn`bBD@#?h@j_`_v@7X-i_wP(n|ff?P|9DLM3tVZLm9jB@X^2 z?2fsWxE4ZS&km&KdB#;wbXb|sW-9B>^j&gFJw{;8b_=6L@bSmw;#tF zk6Foj6`B=uqH%7?`{X8@*UFt!;X$D7QTH*=f|NbpWp2Z@t$`|+#jl+^p`D@&*rdmc zUpv9Y;nz|Oxj84OY;B7@3;&A6U*|-N5lA;5HoGRYIQNvwL5mrDA`V)VfEJ6Oh3)b} zNjXp7u%_70orIGs$|G#{11I3$?!dp@!Rk2~Zh_PV+8#w;kgYAidil+h?pcy@!1Jx> zMzynlp|?2NzcLH9`pF1}iixeVq2xv=d3X?4L5YrPqLu_hWw|I`l+1s6@lQ+j0m`Jh z;j?RnAj2qCgObZkC0~J(8=z##E7-+~I4^ZJT%Lt%H{zD#s{V*9GQx<)llsvH!icW) z$&aZp=0>h_i!4>j?)FNd{@Na@<}E@^d=%$L8dapvf22?(?epk|sJ8Y4eXsu$qiyGE zAg*tN6(W%=yoQbJm|!;%cil)s@pB)=_$kI0rQ+s;YLZ>*&cCM8>ipss`iEXsZqm*) zecw%Mm_yq@AM1~hLam9ufk)Ds#z=Es+6KDbEbm>sjNCO^i%_Yvv{%PLGbvuuW+S~C zt)>*^E*g@w;QQ{Pp|M6o_0iB+T2tR>DE^fH`1z9=DQ9Vw4OJ4Z*l2@RUpY(LPJ*|R_MRcE zm5u;@!NxuBdlwo)q#CcttN1uTBANr|`s3V-i##j9zo~nLJ zWltTwUOA~LmF-SdCv3%49J6Z!hxjn2_WXHxxV;LIrrPftYPW>E4`@wu*r>X#Lo!7q zr+9J+*DD1Zw1HnJ+Q+unT_18SCrv7j1Eb}QMvckRkKUlZWI25E7F+({zQ~jDijs?V z_oF9Q&6d%V7HD|{tqC;@az6t|gemE#Qm{UO`+K0?_TiS>MWeeowBnSB73|i_k%e@c zrgx8{0tAve&!jkRgsj?O$kV>s$kYCAVV?HrsjgWr)262HOuhsI2IqXHZdS8>^s14r{pa1e1uBqe33bVt1u;d3ql3@Q< z*146WZEvJU8{w;eH^SFlX5RL@1$(g{-bqCwXf-A4#92eiRNuFz6ePjR9|S42P%Avc z5HvgZ9Cc4&20V`X=#hzZrvu;O{?sn=1=$fa!jO%kG}s4w=n;3c2+4XIaW$ONEof3x zN&fE9R{k+p^D=IHzDM=e?80tdRa5-EMS+?Q8QlsP-A2?yX*;#e%r>)vuNWF+LxZ;r z4cbD3x2RoH>+Dvo=fTFfA)QYjE~VaEE8`}+Xp|B*+Q@tB;x^-r)b8I(-dkfQF4LV} zov=-==QglIrD8_;pXk)1o@>udK0*DV(Bvvy5i-l`d4@U;sMC5@XojsNdMf4|J1@)y~_^-&HckXbJKe?AvJbIK@vb{SE zkABccgMqXuM)|Y_YXuhtyKEE%cMsQI3$A^$>Drx!YcJ1HJQ1!POJuV5LF(P)JB7{| z^-=qwNGj6D!W}2T9e*kAxGWG6)UOWrv(UB*52$+T{zA7r#&9_e;26fx%XN72bGPhG z$vl~P^z4c9)X3M)_lwzTBnm?fho7#XjYD%$W^s+lEM_w))ZQec_r>(s`n|<`VrHH=z>Zn)|^u-?+(^!`#o=h~AeD=I8yNo>@9* z#u&pvTqkSl6KtZ5REk$A5xBDUnvNW%JU39zs~;w-ww*rL|BcgjS}0cU4!#W1*YiG= z_G!f|U?u_nm-&B$e86u-1}X+Dw!**;Pze1^B=0|pnqkn2R%*mDwRK+S8bTryjk&rJ?`!{4tnZR1N4@N&p_RpRFk`=S|vO z+QeU9$EiK-M#?YLCD!v-Dq_P(l@Kt*qJ*a?gL=oggP_mQK=IVVn6Mz;mOr65eyzvf z(BdsA#r61mEiPK@e8u%(pk;Nq$kAEV-0(Hf4eQ{kGPy;^xaZTpfNjR*fpi<=I&H|HI+YfM6G=&#YxRt~hK6%AE$wW3iDBW%p}cqMGi7n4*9l(5nJM&lb6<=0n?5E7weRf?r? zFiC`!qi59b-=fNk!Q_<&hd63!)odJ*%BOj9Gt#b}x|mvo%K5LU6y&F>@avxiiYa;! zf1nLb(_g--1<^45wFIrGg_;VP`SppC@jK2aACU9aLemvp3uGPHGcLjhiXfU4!XbkraH5}_hr z;W(|+aejD)uD}7ideJotch+YkFT4JLDuQxxb$Qf9Di+|p%GROrB}_CI=r{X8i1bQMHjhet(Bv$(p3aq$sVcO_ogl5%W^xAK;lqlvj6 z=WaWi@`HDK*RaQ11q`elx3yLz4Yx7(4a2<$}kVuPu)brKC(@x%*B_$wfw>4wY z=_T%!!M}ul>`0(C9G?|96KSEy4f1#}EBPvx_w_W%JbYih>ZckQj`5nNAg&pyy_Kfh zZW7T)dO|z}!1e*Z_!I8WW9M=w$q#?w;#WdN*e%GZyv3K78xdF2CcTE0GLTeLKc{Nvj3orCkq4-fXOT;0pDfrx$ z-vK^1S(|}1I0~W%8KUzbdXOoaTj^d!?dkwqWVyO}#!2M*@5f{3A^E=j-UD!bvMztM z=$f++f3HwG_`yIaJh>+4p2$qTa?Er5Y|@!yQm^L2oSo{O9LRLxk`7)hutopU#;52B zZu~|e#)#KqkF$1`Zen_&=*S)9n!CZn^QS1e+FC?#^{-ejFS?G|Jo`wc3E1<;e1+bx z=vLw{O!r)8YqloBHD1xyMFChlFi_fz@EW@xq;)^#P0l%f{*?54Le6%>%m}^EbC|js zx;z|R?r(HC2VL%?x9g5B)5QGu5X;@5)3({iD+x0Eqj?-F{aqDb;(YE`3ofF(K{4Ql zFVk+r-iY-s+9)!`ck)7tA6*x5=hO%OC=mzF!uJ zq9!`7FS@<#`kMc&+(}}e(^>Nu_)zMX)+6Bh$ihKJz%`-j)^7CbdMb1B$kob8&8aMI z%qEKSZS$=JTtT?MPp0UUTPH3g=bSK2FxJ1rG=ULtVes`UhEAcP)0@xD@S14`gbb_l zKT)`9_pVuNra8+k*Qk6@Kj0t%Hy1v0HY_TwnOh&d^JB%GXq(>DT z!unDV{8#MHTerE`pWI{E2Xkjj`GGM=_(Vlh08@hF-KNrbb-UkAaJ~OxKIq#pi^_T6 ze2c>QeyaZ)YdYU9aK7>~MZ@_IkYi}P`PXo`VT<>n_d?puQ`g0PN-2xs>W}cl?H#fw zi>Le8@SQiY^?zvkP7c;VNF4qUU#BA#ym0F@vNpdGvtB%N50#d2>4)N(?`L$Ok77N( z!q~4FA}O5Uo2pxV_Vo|YdKqbb4E)xMfu2R&Sr7f763$ZtRJJVSPcdEmK>bl7gX)M;c4G z>KMN@^;x)DQe1okxcJB<>T0nMNaAX$RsK;;G8Me|&#pDZ_qR<^-5vz3mkWc|wL&iX z#up9xRJA}`Bw*6l^9W<&UDej(u>3GV+aP5r8tC6COWqx_a6ri0@64I?uJbC*!}e9~ zZ=PTT47ItoYkN|XiWGfDuq(mC1jU_y1doyV8|ZB=V!@}oj2$+#j~PecKZzr%;=p(0 z-Mw8mRi&cVvZw$W>ZLkTUr>%cTHl;vfezZQs7b*)0%hd1Q%Cy&?&6Mf4<3LAb5kNtyp=Q_@dnV*W$E%zcThnwWE6;?+!< z`^fFA_sOptD39tv0p+BA+`=)ayVfmmq_M-ez4UuBG1)Jrnv-3N$3(9t+d);#^8`q* z@6h9Q?B6yn0>F1YTVmS%R8WIXn>UyLeZIB`9tPe23ry=H*d3>U0fv)QJ}_DZJ{zuv z&&u(|I4x0(TvistmlcTzKPcRBy2@OfWZ~jm)x}{Gs{W85N2ixg95u?sl*3${@PpK@ zGIsCc!tbgBv&!KpIm2@y?b`FhkqnE!rbC8Bl>5+7?i!RcBhP3aoB!!&4%fC9=Fsb| zkL18Kp*XyXrC*aK|4o}4H_QW*UY|l>25OO-iLP8W4}K7ZX#=B)oc9C8()7KTwQq6p z`?vJyntonM%`cHa8>|zWaK-N2bc$4icdjMnk7JjPwW3$vplXw)9#_*fTSc!D}cQ!$P0=53Y7T3(H0INWxVU5?%pDg0TlOB zPqi3z*TNLarL%gg7`n*a+0S>*S*QuUit>SN1l%-+n{%ZZ05^fE^^X*jXz9HtxG*XO z#$FE1@zL7|`);9`aa@B-&O+sCQYecS=tz2$!=*TrSLK(m>8-i1qOD=PF(&D^Ey&4n zqhPHpxvjX`ND*G}eOzCW(?OOLf3vvz>iW|G3_1}k8m<%J>T_h_fusby@^DesN!wbRr~-FaQgto z9b95IM+!B=hsE7Ap8WOM$5YUJ7Ybgqk!ncho#x6tZ3d=JR)STkz|U%>&){*|69XL* z?YPZ(7nZ^{c8=yVk{LLRqm6l;4>u&&pQdCdPw??|74YctXZbHN%`y3V$Mx##!=c{KtlHs*UoAKjtUd$SW{ODu+JFK=;q3aH$cvl~366 zI}zjI6$WY#^2lb`A1|*mPQkO-g|}A-UTSu-9P+%u344`LT(p&!$KY0Ds_sZIaB!Za zzbhZ9O=V*Q2bXFPo2uO)982BQ*L}`QY~YZog{vtMS5>uBtxV%)h_5w$2tN(GpJiO>g*+}=T7^=B4${Ikhr)|#cm5$8Dj+ozsPUw_a5+C2uNM|=6khjfiz~mjN?vPS2UY6m;PtP_k4f!$llRI1`i#T-w2_M(l&w<6ScmmZvUO*Hlawgjk*`S zYU^fHO0mES*To9!RcdJ1;YtfwB7Z7G$4g&U6ufWKD?ubi=u-hZP4ehzd``>p=yNS7 z>^DZcqaXpOz5-#j6_JR+LGj#AzUjW=&P~q@9JWc7H?%fJTAPH{n9-VGQf6?ab;f*t-Y^^O<-r!9QTrW z8z(FDE)8KM8}lc3qxakBjcx1mR{*>G3eBf4q_*dApoA*c*UY7I08M3QL#9Lx9qz*Tvq7SCjQG@swJ^>IMr0(fP zLqd5Vk3@P}E3%>>-x^ZWcIq{!39{?jNTrzyId~R3kX`pgdRHR<0sIn=Ch z3W9)DQ;d}$f|g46Dj3G9##1G;VIA(H*D*^=$OF56N=i#4&@Cw~QCUXeYnh|O@=Kw9LXt4KNJ}BYwF&r> z^Z{in_!dMAcIn6z@WEsU1w5BfpxIbIvwgh_fJgraWURId&!+V>+v0O8dOf|mRu3gf zH@8;8N9ql53$dBXFtT@FHV9rfaBqTq`BbT)19f7CxSx7%r(YFS=c*L_%pQZWiBJ`6 zy48m2W&1hW?oD&&?4io=4#VQ&!-sNZWF9Zhu{_8|u@py^lqXNwlFV^Vd~GjXRcNeB zNA21#t@RyXZ&4o)m4=urh3mfk#eyC-neIUpV#9j;niKQCv4uOpt7@ePXKlGkllTY< zs$V|kPrl>1Y1$HzcN0UwONbU>%l=}^nPSV5#%OKe&w-89MxFxgRGXZP_3}jXC+iC= znCzcu`3eoeU6)G3FxlHDQ_bXks3weB3>QSJqdq)ecFE|HKN`>HbLdr@{bI9`dbj+h zw*Ayyu~+Nl3ggZ3U{P7@_3D91MW53pgCaV~= z3Di&!+JuAI6&0t@P3;ihv;?X>Qkb|5U5?5>D|D$cNEd3*rJ_B^vHZw;C9V98OnU7C z%Ci*1LlyWF|7xy}9JHEVvs_4180AIeGT}4sMz7m6pTd(Fvn3Ms#OYJA@YL*cvRQi5 z?h7Kd$c@aS>M?1{g6f_5+809{d^J1JEP~hKTk|9HgFup5N`uk<_UG+4koGIFR}aC4 zbt~nP`)1ljPj+hg>zRjr$rm1ItZauN{}u{!Y(wOEc;zX{I<$v$=7n0ip$40A+ z%-IqxlmU*gkA`6W8c@nRI9Qg|ilqJRy=aVHsq9%$WC5r^ogHX;E1I5|t$iKAW6|`G zNPU`N^^)l1^5;#zf~KJft*NJk57HxSKSvD8vh6~){DdnXN_yoI`(h-)rvCro>^dH=t*`r34~rkfP^{gobcZ7oU;Lb@BQCl*>!=_ zm8*{_pkd+P6ujO=L85J{ms{n!kZX$154Sce@fB_DmGaa*;Pja}oPPPiH-rY{9XD2B z%zr`hwSq%;Tl4w0TmMIEF6MbVPne@nvQ*J|A1+{=NWKrS?=lH9+aUdKZw^!A+C2h6>iyAeEQVSG3Fm?TWqQ zc|3_C^=^85nA1V9f{PIKVC(`HI4KYzUwCq}y*`BG^#<1+yoHZD?rWZT_sfM8IBNSNBcz#*Im^Fj)@Q+y=j9C%};l)yIjaAYm zTk*Y+eA;;l1*4l@lB3iI@G=ZGjI(d-a=3nEz4g3dpDmK&{V*|36kwnEXX>HyyM#Y5 zhY#b(aVj1KQb~{dU$i%ESCI+9Sllh2O zqgbBLlZ}>!Yu#YRe~IHjNxw8L?|lAElg5``YA16W?}f(*GI2uY3qKh!eWO&{6azB1 zI}9&!vED${W-F<&QzS9Lra&IfmNZnf(4jX1Zc0XiGl!-sBt@3STy)sM zV;~07PyR(Chy2rbkw;Z(+Kof@e=Cv7fP>Wj;E%aD<*LBu45Z+&=bC$r7fB4K;j3~v zBx-?7=qrXqwH1ka&a2IhYEJzmYBJK4=egbXn0W1A6thD}lvG(~LyL`@drp_*d&RN)H?jFvGVWSR;FR(I$d9<{zr`tF3^4iV;n*xz3ItP_r#h!i^%V`cd1r+V4`Jf6gL{pQlXq;9;X9wu?hrbUk_5hT@16Cd#XlNg?F1>h?1<#g% za$iv9N$m8M+%_;DrK8@jE>E`;(!ywWQ zM3Br%jT>FtOxY7ZnzIxj<`4R-bs}%JAm+b4@?BD1+Ns$)>H-E0&3-O_4YZGQ&3`HP zvsriBhy*kMI1z=z4fWn$IG^26Y#IvdV!gg;x>-^PuHF+P2k*1H_)hj|&`mhMTt`i^cb5nM z9Ygn`Z2C*z=CqXOdwjuR6(>U^pXYu_skav@TT6snMFS|92UvM3KX6BVKLqW4pI>|5 zkNZdN(%w4?kkN^DghrMUHnizQUq4kF&%5;T7W#&NP-!l$*JAZsdMx3nP!FhO zh1$vyr6nH@T2uK>PxWF;KLJ+tie1W2%=OZbC_QmOTZ!tlBX|H3a{&iFWRiS|?bEOF zKKhg`fEEvy>cJl8wR}o4=u~^&EIsF0;j!tN)QtL1wllJZIr$F@Ea@-96g@@z>Q)~G z6q8Jfaq2Zt+yjbx=#%z(JrKm|`vUm@SwN=0o48n^A<`%t!3CP2N~*M4m%i0v19WMW z3KAns62nw#1R94x;}BZa2(5}yhUJ|;=*~IjJWa=x6gw?EE%maW)NiI~8{=+0t{}dB zxo?iD4d=G{a0}k*uAT;sjrtYdNNXac9RRSUXP*OpA^qTCq`5#+PAR0F?xqGsZ+Krh zL=SjI9>c`8jebV*^r2K>^z(X>Lig1sD;(`l&BtrCMXG-iZ8t$UQN01edqH?F zecBd;5ez&!_pqx9nU+DkOKD=Agq3!(YvUJjbF>SQR?i5Pes!Wyb*Ezy#w?PxkVZI1 z7t*u&O|QADyj5f;pY^mM@Kfe80z?m>0Bd6uL} zefo|K?fb{XlP5yHN||c!9 zqp9c4gdm+qF_B8kV)dO~dKrI+s$&c`k~vc z#(|UCFVg_SSEALs(CS?@pq;e(-NCI^4v`>$8Oyg4il^6P!-QT_IVA312M)Twrx0pY zGBZ6Reg?PtKmj6-c2bE-D`It*m)-|NuFx31MujxYNv}KWQDg6Q?+q{6ybWlAFH)sn zBtannfDn=qS_Azty#b|hie+i9z6d{9l}vq>(cJgw$?d^QvSVM1TGAK5amkKeE}Ce0 z0o~`MRP?YFq~S~N1vj-ta?RTRD7C%47QI0GO?sFrJ?zU-$bR0}$bK%l9-VqWhWK+M z!T18*EEymjH1nfPKsWcXGx1L<4U6Ruj0BMRXL7vw7#lYbpE?wtC+uEwe`~Ufa|7D% z`?l7pfL{yY7Y=^56VHHUi#nF&;P^E-eog(XcpPxdSMY7KY~-_l#F zXW;!#(N7P<(4E&-#_B7OM!&w~bhw^J-3qP?ut@m7;`yeIKVoF&_?{Hb-K3|{91iGs zv=k7y2(~|h?T^&2qoBC`{fwiT28!FsH&xUa)f2C4iE^5hc-Fy1QjJtABl&kjocwr4 zhiU#(wp6IE!TOB%Kb(*@RAN{Of&}#Jm-B6HWLHP52FC zUElh4q|7Q{Tac%xKKPe`r{)HcYRnutn6~%fKJx@5(P{$@$#xqD(~XDg{gsnAkZwFM zk5clo&30hMgFP>MH+m6l*wLHd?S+Ez+)vRDYvWZ~i$<)qXtC0W%)U!74%O5T(eVlV zJ0)>F159o#UX`ZsvpmJZHtkrQvDf;DP(4eH{l>lto_MB~ zMUdAzLy17}fDmNUKbvO808eFpqO%ejFBu8*56Ph1DWB15P{L=eMx; z;+gqk9&v_Vl6%y7K9AZ#Uc0%I+&>BNpA5uJAuX&BlRI9&Daq%>_zm6DT^RW7T4!g~9lQ3k*?Na}C=44PrKdqJLg;Z8H>L_0 zIkeURJ93}j$lV)ZkfH+!j2AnHBXbbhU$zfa8ovbj%Op@opBl8=)d-1@0u~wNFW8~L_3hD`K3c$6T%L5OmkEFTUNDH!B>eu<2cHMG= z8w=J;3*a0tFwu zQu*Q5FAA?C3rO^KE~8Yyteuo-5^3Ohea)|510OuV1B5jwWeKH3p|l&6Y8!KzO3(2^ z3yyU?^f&LdP!*KqOkOCzez)ij8VVS4Jz#@2u+?M5V`RPcn~2kP=QStvEv5zPfzrLy zA2J0Fn`x(FV|_iZg>0?#S1}ktH$bKl!vjbqJsg?_ZN2F_iHS7;a*6)_M%Y2&-@fJw zXBi#sR(o6tL+Br`<6XW6PJKJ|*1mJ{hMShgrhixAJP!X3OVgowYuhN*+y+C_o7bmV zQ|zXrcUs&&{;^7cbaYBR?_;-?Aphbv&L;-Yvr6#_bfWU+EpeFBxhm>|E68Q@FeLk zs=%W}*WOYv=P61!hVgezqu+U5wH1K5o3J+t<7gU zPUPj^m=IKJkJU3VJ~#C|1;D=QSiYcLr3(>%X{df^uR42YIb{l7b*8ROte3hbfJ~ zs(S>heiMZE31Np2{!6?1yq!Pc9co|SMul2`P7mzaQx=@nmzq562iHV@&aIDJ3DHN> z>rxrwrdF?m=c?B5X{mocI_Dgkf5*u**G;J*Nxut|e!^rATHgs95p7U_VJ5dh@rCbm zvV9kn5ur4cK9J!K=wanJ6kO;Q;(J%QfN~4*ABUc^LTJ1Pi?c5}PviqSB{-f0xA{?$ zV3+wr%owDl!)f`(E0bOTBc`sK`*UCMZ{1sp|jm_~A63p8*UXN}~6_zRCV~g~OAVPu+~ryD8qk zydF1((e|$@z^r~#N6^q7USA@P5Ul(fZBXI4@Ji}ND=nzgsz(9F5M|-Fxk$yBOEHEO zB`cS}GfjV)=Pc!ch~K_hg*q}P%HIbp_c1>0D+2VYXz$SjTWB4|0uVi5H&(qco z008@8pAv6R%RQe%F$cfRJDN=o7Qj92n&ZtN{!6cuA>N3Ay_;hEV6~gd(xc` z`A4;sdRoespZwUn2I>8IR~O9d6#`y-dgLd_e2KjCVI+wEk#hHDW@E~ zAEgPxw2QQVvmK%5VPWq|RmgNsPN(Dvs3&S|Og|j_HK!zpTIEP{4tvj*4sy@>nxeg^ zFoI58Qqw7&>v?^4)JVeVG)7>Vj6f@CUXCmeb46t~gCTrAVOJI54A? z9A!kB2k7IJv%y(C1&i#4VUY>qE`pkRo!nNbvQV}fVGC$?i9~S(iz=2O zhyZ@dD9$x%y{(k$_ON2vrMWluAI_y#xe_S)6tLZHw;3o3)biK04uxIxv7EKE!dZ(u zSJk^9H%b@7gZftAsGf!|KUojGf#{18F#!|_a<+9Fpmev115mm_|B5%l1NhKqap^k%U8R52R4M-W{RSR}fnQfn!zdCz z%kTW09BwzQ`Wfd@E>V8)0OY<|g6r$dJNk?feF>=cGlFXWtGTl_E0vz>#ZA%xFJ69^ z!8eAd!5P14gs0)8gj?N}e(oQI=y#qZH!yW*>|XIT#1$H9$EbY*$~T3w!WFkIXOilw z{X2!84deU#)-&iPmYSoyFTI@Nx(LFCbzADKDy#Cog@`txyIU+zf;Pe!)vJa#!)thn zIGZ37+LvBbQ0m}2*tVFj*j`Te2{3yAj2k|-2_+66PvU4VJz%G3`U%cgCVs*B%EZr< zHuhf&aIQ;#7#{@Mc;6TW0AxKuyQL*q6Oik5y14`|V({D64L&r0{*^xPj!!RxEwwO)<27tx zRXVX|5{*IDM#uo`nb6}4>3gNSy&s~x#0Dc~3)%fSQJhdKr?DHa(s9>$yy&cF?m$s8 zd}g@3@L(`vFW&8*8!67eqWkiY+9C_pB48oqO)_Q7gYg{U(m6vOeTD7&*UBIdX43GUwr$ANL;BhTb(cCJMS8H3WwSz~f*x8QO z+R2OjC9k0`t&PV!>41~A%Ntw0)ZSo$z~0)H&AEn1C`qFa&BW8G(xp4Z%O~slw0)_@d9Rh3#6l?oD}4wHBJ-q+8G^%_3duI z>id|cD%4m-9%pSeu(APqk$zBxn^8o^5jiS@JxY(EQP##hML`nf52bBekS`n*=(JKh z_z_iq0Q2&IA@3hzv_6E<$lRiLjZy$`$)~mQ0_JmgnItT#mbmN7#`HWaL%UXnHWWi^ zyS$;lAz&)E>CC;KmULku8>#W3teW7gHgqqJ)}BSuTkicWx2_}`j@A@^cP^Kdy3a^F z;XeX5T?5+wXRSneTa?&UjT>nhJfRn|D#jwMP)W%C_>st9+nF0q4&9N4YT`M@ zA<3Sh(y@9T~C~I9By)+b~A_r~ZdzsSFy<^|&4d4W|*> zcx7lH;vFZaNCy5^Y>)Zb^R#VF8jlj=^vI+JV3Ge0w60XX5+6>PicIn3`_%Q z_w`KL$+Og4{`^!-6n`$su>x?c@h;9a`f|6I1O(se3uR%=1J|{Jl&($ z(<%j&?xN9!&*e8o9Q{f+^)SG;e{NN5CE8T}PPKWsBUKxvE9U}xGSiL|l~Z=I6g(~I zA927#eGQ;(>9YzC6j;t%Udk3&&J_S{eX6a}MA~i#S`ycQG8`cvw)F~ODDiqSlGe`J zMtyH7;FqZ-Xfbj^)Je|oX&j)it?;Xr1Hjwf7G_EH5 za^*XV?P8LKGi}v&F%xX($LcV|ugX;;LH%d|fheGG4nUM+h510wJMOcdMXMGW9XJ*S z_6fp10_;(w(@kU5I18?GFn?sl1qycP-L>9UJ&@y68?5wH25hjDcUrU`S0Rm2rX$1B z`=RdPsA8X1yk+-+ZwrGr4bB=>JbNdOq>d$p|MJke(;>DqVMjE(k%NAXfv-K&Q&olbtot zc?HvDOxJm-J6`vrey_-&#!9a`8-w~J2Gx#Vc8A^SvbYK0GeP)-fDb@cZW@iz!*#|* zD=v`g&>z%#gIGDg&3~xcD~N4(4aFmc+QJ_C%YgD<&X*bsz6pR2H!|SElX<-|Ea%(- zw=*s0Y<^9_6fk}SjGqiOiXd^ zTslyebJ|&5Fd1L>W6+i<0xDkZp6&+~*K|Z%#z|X(>7&2xZW<#kX&7b>gDvd#Fq9wV z-|^>O#kRTSb|9PtBRwzsH(`51F*@b${xfd>pjwJ-Kyl zw)xJ3_}?Htu0)%D8=Rab#4AA?*)6du$6(Zf3mU58OFBxyc37o}PacLTsM0=)6eN^+ z6a+Z;RmhcVRv!5L6wh42~eO+hK5gE=BJtEezvWBawH19^o&lKpV7^bjVCi zn+MpY3H^P|#4o>8qOCP5QwGT%WRa5s3#J&1yxGDi&;v#%3c*MqS8a@0cpPKW3S-hL zLGKKXNYqU`Aj*0o1sSyzb`@ef@&QR(-_0`j{yl?tkom{*=Ci(1*?n+Qe+T+&!h-rh9;slVQ5WQ zg5C$Mp$45*+n<^GvkJ=CH5*E;79d;+PfOapj%Sc2#(+WA_p?+=-bOD49}RHu{|O+S zDI5h-e#1^}4Sr98pB?+B8ww$S?XwB`GGTiY{lp}T>|0;LS8D0> zwBa$+`N3BuB;kNJ=d$yva~9+;9X;9O*?$_ zE34tpTOeRCIinzeRYjBz0mKDv!g2wr%@g$Ibj8Xo^p;3z_2vQnO|P~*M?VQIaHE~L zfV&F-RaswfmlHVORtYDtR-3?2Y4^bnAO|M=ZEj1C!<9;e!?E7w%3EA;mlHU{b|L^? zV3K%&(3H921-b;B-Bc|g_@B)M%8cal?N`|arwz{rm+rSTHk_Z=3y@ZPp6ibPBgfqE zso((>B;Dl!-OvgJ8U1}Gx1dBL>}ou+t|n0nw9dHL$2QnRd)=|j&C6Dhc-jNucBN+@sDV>f{l8h*5D{? zrsiO6T=dt!p5&Zvc+(%a39!^ZwHTVK@&}YjA6RIo)=*sPlRS++i?iDPmPD-ha$)&bZ4N&oyDAv~!XY_b)GNn2e+qomZMI9V^ zf2|{qn_*NY^TJXiM&oZM@O4iK0gQPQgG8AYi!`Kop)b9K@%Kzq@%ZIZU)LC30eWN5 z%`%R}{YZ!Y2ng~-{#$3_&q zPl2Zh%13hGsJ~MXI>F3`CQNYwd)kyd<@Msm8O8%&fzpY zny2tQaw)d&$IvNy7eMm&{6O+w9tM!yDnRmIhQ?4kw32pErfSMC9wo^@_hjchK7ED>#W7Ww~F)oR&FD7k!Da|6$6Q6 zniyv=TV=Re3oyci9ah|Ei(BCiJsLc4g9d@ef>N;qBb-Lo^8P1~n;Uw!1ptAn2h z3jBQ62CAojqd2Vm3$;~+icF+C3q0NfxE%}zpeLx?C(P~g5d;pnod6EwOSRWT;k&9` z&-;aSQW?dR!uN{Rdho0GuJcTgsdJWU|B2znAU47QMbGWEWW}~~XB;;Wtjpxwaw%gt z10>`NCR}7I-fPNMPgO+RFI%&P*0NGP_= zRq>*#MH!5wS7{_-8fo&@C+)O65%4IUi>q@JBzwwYJFTVW`p9D6u>`AN5L+nE+N<+1 zJa9q{i%Qm_i*nDf0jt;Pg7keuBY>T^AuDs6#RG`fXt)lb&&4`2cfsUXbKAZxQl#E68SB@ z7gZMEPjMHJ?~0ddMe z|MG38Ec$lKHyAB{sz_Uu$W!ZDo@KT?j2%)wU|6lD;5A=?qJLgufYu@3hBKC5gL(A( zVxWKNwl6jS^x=(&XJycTvPheq$WMZPe4_Yc9D>0PG2AmNe6w2d&8&BPv+MB9uKRtn z6Y$NpsQMDKvejinz2y1kE4DvOz<5ouOvPhh7-29hnvS`hSEPL?u?P3kK=Av6!{L)- z-%ormI9^D0Z1X!_nxfDRm;&^p&fP*sUUS3W+L?)o$X7r-5X3uzI9xEJH?xbhOkLJHhU>X2PV5)9Bk}eCYwSbMfK|J_1CV0`HNh44E70a z0$NMCwDK_lhFhURc}Gt%-v!Xslg~KhLWjG|H=V&_ZT!|7{?+mP*PM5mZz*adA4E3j zAln~y2hZ}Gax6{{hl`S0T*EbV}w(V zjy$9?5YFgVqb=J1d?i_cn zckau7$t9NOSmE84=a0fV%QFQTYT#jy}@6wx+3DrrM5({7gdo13i+)&`*Q=xyKB8OC;xSq?*(P5%mWe|SV7QgMbx1K7XMXT_HZ*H z_8^RI3_mC{O!wOv*sD4V_bJ-8(D^@2oK)`7ZmQe})Ebc$(>k`!-r=6VeH~DsIR?6X z@>#U+;s$Oj_U_V#|F(CyW!gL3`@h?}w477fW!Wd4YxDO)g+9ui#n=K;b{|^ewOy!! z2sBdL^JJ82(yJUiT$&MzX5f}z4w`timtq-_XlO)LIi})r6$guV^G}s*HMA3XcoH$^ zr?dsx`hqfTakhSpNjuxkjzxD2hrX*^cU!}&T7P2X7oj+6&T&?T@WVD@-HLg%;`(H2 z3;WncmhxTpk=o$#<9As{W4V0m%*XV=e8Exin=jGH?`se7>vAoTXFyr>rZIB4h+9D6 zEi#N*N4~c*k=od~JJf6U1U&<`Y=?`+I4RbJBR~(Omr@2GfiG*DRqaWR)t|J`SG)!h z+O$D?GLED4Cn?H-zmRf9_bL?TJcUBqHz>_cQ63tM%+#KKUi@fFVJhNve_(`lZv*uI ziZ(z^vui1B^%Q(>!ZhEc)%Z*zh`6>=q19m~Lc6cigA}3HDb(In=r!=XDijBKB!nV_ z`by{lz!tB=OOk!tly)YyzUn1fZAFQQQx5B3dwV^_3Sa1&gHO@wE}+{)#%u-Z84Xd) z7UEr6Ob<(1cz+PUjm-D83#yjF*1IX99xt(jfMB$Mru>q?MUyCk0&-6sEY3OZJW2mC zf&xy;Y34X1C?Ej`*3)Xg1eWY$Ul)+=BUD!d-+7YO(4UUJdJ448pR}qE;QBC?J)K@x zW&X8X!95P}kKzEg3Ez(r_QUP(gir14&ZFDcAbi2K~W#7H3!L#CdoePMUX6VbkS2T0bPrl znr2+aUguS5q0Gu4LG}+ek^OJ0(a%eToY3AJJwNn2)EN5`rCax049@BbC@hYpjWg9R z*i2AhgSZ&^u5nM@!0eAcWT# zY3HXJY3G;RPCLIVNn1;wAzUMq!?k;j;DAR6A@AYFHoyvO0_0~DT#&V6^+?Y7GhTmi zz{PTU6l#*zwi94*FOC4%JyyW(*C@$qJB!Tku~t0Pp4ZARL(=<)`yuX$IGpKJ ztTcHxPa61bS!bg{lOF!|jvMy7Iw(m&WlD4;MrQnk5z z8tLw1qsN9u-%fY0{i0w~ZXk-3&PJ+x=cdD3F>ImvqEaD-jRlLto5C!Xk;&6 z1(|lxQy*@nv5@K5%-(NG68r+6Do}^E&QffUTt?QjmY$1}s}y;6X(ke>(x%S5$)Y*n zRVF}K0A@c=gXu(E7v2PYa)JhRw!YolNRFN&3Fzmn*aBd`K9)yFVK|8slcI2+X}()) zL~Fl|7<{UK+TIjwGQD4$j8GL^A|^(7Ex^w|4~|@4SjKXDH30<@5WaAg20QIk8E3_# z9Kf6KBf!CxGzbwQk$v7nRDm!@T+0@Eq_yov787q)X;3V`t^H%-s7m0 z@9ySE+l_96@i{Pd#`WY)Q14C})Kwdy7?B#hfps3NYKh#h^y@&r5*{B=K`d*)WWh|P!2DwpvAIv8jwZ@hd| zjPw5Bfi%GGKLmC7&aJ-`x>qXkj*BotVzXGGAL<+ctsTb$_TMPi4)br7n+^38{AeiF zzmY!(V7`+ATu2|EN+ZS68VG%STmc0)O;B(xHQDp<(nu))Qpxx0BeBzQzZ_UrTd#9~ zAF!Y0r7S;SzuHxL+mC{FPB#1~Uo8AEJ>`a$B0I<)a;Odq{3Y$8wT3$b&mJzgeZ$Xs z7CF`d#TLtQiI$`~Pvuh(9N%Qq3qaGTpU3uFmTxVN7qfsx03rO8?pkqytmqo3+J4VM z7S4B72QL-0{SOvSqtk-6#|dE;5Aa&?4hFYDqz=v+H2Qk30QdU)TOA>7{t<1y z?h8}6OuJ|?TiV7%-fuOL_Z6jvu-MLxO{WR`qX!R?znn$E~LjR1&)8j&Pu5j4-x?G;dYYTBv2vq)R3{2nWEnT_IK<@iW=*Bb(`-~pgy}LAccQiG5gu-6g zlw-p44_^{^{(>m`ZFD}e^yN@SPPx;ae=X1N8KNiR85#n&Reutr(GOqe>9M>DWMM$Q3fTBSWhBK8OU+@1?QjqOe0v#R`eC_+04X2y zZ!t7Q4v-4(H4jC2ZGU8G^WlK-Hxx+UU~>#>yFb=8u5&&9#)=D6PtJCdt;LAkAN`Vm z?o*^5XV&V$4Uc*Z;Qev070*+#3BF$q@clZqHoyem&jR>{`#(YOUn7`sG$oG**fCZgA^`kJIITZnU=f1VxFr7QxPy`G$B&AC$3(?92P(d= zdIEs*VYgB7Lx74OBdB=VzxRiIt^@7^!tOxHi0lzyxX-=TYx8Y@Ca6^(qU5n&EiYD| zB>W`%fm`@VMU({osMx`q!4J&7kc{l*AD;fWZ1s{oNQpj*=Nf7Ehc!G@vh4jb6y7P< zLILuKd&M$vLTul0p)tQr^d1fQ+-lRy<6p7#8Pb~rXN3MZqGEH7eo2{Kwry|jro&qX zj12u05Gm!H=cbV zkxxMB?@BjO>u&x!Tb*ZPTh0a zizE$g;Ml>XUnDs7duSs(I;=&R{i|?^Hi}P&OnCojL###p)p=$j_yOYnN>cWU)|}_1 z0t2yLE{XOxN}~NXE(*#Sx!>zNXLudwqyU%Q3%^)<0eh?vZu-gsP=@O0&R?B(aDg_+ z!h<@=T2a9tr?LT_ZyNc3RRvixh%H!azU@B1Xo%(9^qz06Q9(u`Iw!Gq_(lu}IZ7BgQ z&%DctkSae?zB>SwR%8X&K2CsBH`Ui57tuO7l$Lw-U}^qo!_k^wy47Qha6cm?z?TOf zyvX3c2mDVP{JW}-Nc`Wy2ZTRw=&!$yz|Xkv5A1h;Zz{Tg7p8wV_RD&Udd;LrdNWWhF5|Mx4jZ?hQ5K9%4e*v zkxSoYVH7=6Qw6uQt&sacd#$aaeiVtHRd;?)3AdZx#p(QGxhHc>Bf3o>``>!vB@Q4~ zI|gS%X7nLo!+FMOGY%lXHftz77g-kv@Zau-84YmSZ=kO^4Fi2QZL!cvAifapRYldN6;<;9K&AV9Q06_427&$1j zg+?-kAW4fIyC8J)aIzys`@TKCM-`6Qz@c6W67c%KDEl4wKTPxka4czu0soIO;r~%a zUUu1VIpr+AZB{??(3_rhu&cIzgy%N!lz7+_#2c)bKKX<3t;SDU`sVc3mjo%Phuy%e zi139=5Zr--rQcH<3ir-T7vsD1R!apV0UOfDf=5%HojQJ0h-}r6{0Z87H5AVOzNx#0 zYz(DF*2V}#NOl>}{Z1b3NeM(iM)>L4f3)dw9D@zV7%RUVs67e1|C5Hld=5ze8~%+# zEd}1P?dIQ__12S0?NsiK&R_96#TLCvD^nRhR;6~4Dj;AtjUB>D?EK#3*g$hn5;97k zIZtAX5VUMJ(DOww)MORM`;uQUZ}_(X$>JBw8W^fqB@F|_SUQd?v023EMvz;n3$`T)S(|JELmu8o$n z+EVnR)PeoFN;r^ce}ta0*4~@*R8x`=U+{)qq|Dmb*bVIMEJt-i)BTgico7{yQNG_) zJ^?}}99{L4i&pLpLY;(A9|V+f30%LD*dBWNIV<-J)Y9AP>5@0xjvi9JvjQSt&)f;5 zL55fJEo2>{`CQ#@V5G4dILz1$%<=CArpaz#p1B)%nyezEkwP!r1uS{J8y@-uKBTvS zZ%j`+3N-%H+*;eOpQ>Ne9NIO9l)k1#R^AgxpKvCB0ttvghFB+c&#QOUL#sVNgg3bA zL$pA=7Nf;GIE+_Qn3X34(rWI`t1T;eh?;_o;BR$4H*8jD(J+}YN+8^s)IY>S0{&_p~VO~=vCh1b0f&*(!mNO^`sDJwlSas zv`9w}jWBArK*9y1K0`3-HT#oL5_MftovXyB1@GYDaiQD2{92q8SLU zz=h@7(%$-8{EX!N9-5t=eHArngcF>Ahr#JJBf`S-sz1WwK8dh+Ot{n!^U%Y>rD2%K z<(@F%5-MDtIm#QQEcRrYz&l3J)V_=~PQO`D;{E+k%UUnVZur{3QA@kEA}{uKsg1>! z*$jrZjrDd|Mtup(Sf}dGd$s2cv_&cq@*QLVzeQLE2GAdtu~yZ4V=j6-7_L9raaJO8 z(E)RzeWkTl^>tot9m=^PTEnHXQ!65;KUyPIkD*i~A{?RMlhxeH8Vl;*A!I|SV^EK0 zUG;5H^{yb_)nO!#3e|^iaHX z&{&`dYe6U=Iv9nWG;j#@k6%Z#Tb+Pq@M=F}#Q5L(eu>?%3e?s*g5-}?ptja*@II=wuV=WCx>@vfx!iP(`36~0CtAiGG(ulhyCp|=-)*8mdYscIgt zJw=iBSVWLuKfXE>5hQO%!R&C?m%jz`R_o~g;|jHP(ZhvLIeiTjdICv#=mVOja(!C( zjNKWCe_tM~pQmNo`5_kCg?Ps{w6MnF3~WO$C*%53?R@eEY#XA=oD}`O?zp9TwC8Z; zUP#0s7k~x#6yQ|;JLHG8l_hCEYn{~y>cR+P>JXu&DtdrZZHM10@Vgy#NY;~RiG_P} zjB3lw)Hd^n)YI;z!#Yd2t#1|~pf@auanu&4Z*fzmT%`tvA^Ocp)`I!@O^XVD@h&LX zTUd3d#2p8w?kq430@FTKmP0g89n8HWsCTmd2pE~%`&_pa;KmT{-LCG2?VF@=aWGQb zd<|Usc8m5dK0#@HTy0x79km)fy8v%;86h?m`Iic2=7Q@^kIA*z6KC+fc^-Txfp2r+ zn*qKLM9>4ty3OF555CQXZwB~2(5~)=ZDP94x!XmeG8QD_lCEt2&v#wZl3 z?JTxcDHL|yT7a8FxFtr#ys0SwI@_|A>TzVz;$&MEyRaLUP@sb~%}W|&BFG_Kdx(x0 z{jE<^js8xTi}kS-&N#0Wydu(h9j#hkzS^7`xRhvB2h2-nSrQQu6p^g=tCLJzT!D-2 z>Mq&_WYX;ZYTtRHEZcVXE6WGJq5EBX3}x9Qh5INQx$SxANm_!Tr;p@GNq#G#c`Utj#DH{&pxn2-M9Kgv|Bq`$%ZapOebmAwR`Wu|`Sa zNrcReDBqeRc?CBn?M?+8NAd~^9A|jN9Kdnp5DFkJG=#I;DFJ{!rad z$ha)?u%8X zN-o)Tft=2k^tRz-L2NzrxaD9qe9nW=%%q3yZ`u!0nmX8G3+x!c_eCH^XGVbj zr(!G{cne7ZWV>$NX)nM-L*zFeLJ9tl2gySetH(odmIQ%VRSkDZng zV6kK4^yl3)%lbCD^fb_YlD`nrbtv~_?%z2TIr&FQj$-=(tLd}0j|*q+rn zHNWZM+%kQwa>6_4FftTt&!QeuG_@_W_l@DWG0hTXsP-gn zH-Cf`gs$5U-D-4+qs+4g+P05QS)byJb?BGHWi)2IJ1r)HzKbRM#Thu-v&Z95<#} zY)b+@4&xX zgLpy|r4Q1_8|>=|`{vJ36Jb9ZT$)8wvo!qygMB{OHv#+GH-_T|*q6WYi5{X}(0-t4 zR@=nD+WNz^pZX%vM5g{DKjUjNval9HlhJwd~()P#E_K;`_Nz>b#WBT7WhT{f0wL3_gjhxT=1hQ%q zL|;y@*uD&`#-^&TKHV_XrNtK1Y?Z`^Opl^R2kEG}G5HkFJgmJAd8>fi;G8DIUxuOg zmd9Z5G4uPgF!XCN^f`w$8pN4V^vodrD`V*IlcE1BfI7<1Pe5bBqA3gmQrAk{u-v&Z z95>L)Hv(vDwCu05!ri+WpI@j$w}FCP`>KNXMo=(}!GiB{jnA*{7f8W&Wu?TenCl>S zZOIdcSPZI;`wgwzyBw|i60LjTu(n|kzZ^xg2I=oe>u#cP(6E>$>)q3&B}J>YC1G(- zScXjK75#8%^dFPTi$i{kf5O@~rHkbF{bdBAle4!;baK|PlQYYH*j=#k=+>lcGqeQD zh#PKCId{(RiO1%i&X*Q0 zLTY=bL4FBsYers&t3cTKX7SVz!adhIxl2*lmC+!@+C^IXcnQ{tO@90 zz7Ws}=<+Krx)&=^+p556eqKpN=2l+jrGi?k6y1*%f1%14z!X|91vnZ|anJV77>h|@B z;}syAo-8nb?ioQnll2Uc<^MRoIz?LX*L% zU6}EcmRgW*axz~~DMkC%srxwJr%2k8i>O_95)pG#ewreE-0PmJA4Y)4Jg^!MBX0A} zD}3ffJ5P0MbK<}iJNsbO6{B`zp5GU?8QsfQ!{j#EZo&(ENG!TM5N1BG6#G{@rs$!- zvwjIYYqf;s;}i!)zoDw{%d7Ki;f}hdODlG}pOIEvDg0I3+DRf%qaaYD44r(jP`d${ zx?!QK6ot`fUuD63egY3SgXbCJ0O`%*wt5Q%mvE~AzvRaEzc`cB*flv{+pLHKxzlhU zJ7FxnnT5~Hv$NOjv&2CvkP|hT?z3};hZJO2rI#Jr8HM{k7rF&i0l%UL3inh6XSJuM zLnw6K7EyBFaN7&i1WN9@C;(hQqrbW7`PwK2S_=axt!r0RZZDjJ5q#B+GVc5WHvo0f zYTOo&?aa~|^-<%-NuGtiMxKQ-H_ubJ;iS-?p~P}>wjM@o+@93(+1~H>6nuNs*GoBX z=ARy&f7%d}JPqA6B%_00GMY>$zx#)#HmYb z(V*d?sJVSKwKvqX6?Ox9`5N>x^h}wn6mVuyG*>gvDq0YbwaAGcPxU$8%E{bCZ3E;t zRF73u4{q@SsGjyiti2HjQm1;TGxSbio!;5x+MEBX6N(4=7x3%NS$Aok6k4O!h(@Ib z*y9?xfm6Dfnh3J_1wMN=aA$6C1yVaQlRMo}L}42)U=}-iw0~La*2g!lth`s9cNWOS z^S_G5{jUXbtfPN{Xi>CWMLL!CU_OIWdfc^G;FNQFZg5uC$^;HK)=I~-;1}jL0$hQ0{ZY(W-^a67dCDca+7(O zG`Fu|9CzhF*i^vEIRYztQ25U{~5l=uRb;Mi9mmiX)NXdadraQ9Z_DW9LJ@n)(uSB_y zsF>~l>N{ty=P{_iveC6W?=>eDG`fy$VTWj~K;-57}N z2`-8>G9@Ex(9+VSB@`j$W2eFXF$~~Hy9WX64(@^s+WHo45Twsmnn7*a^W(}j!ivIU-H@}Zns!oILMJ)F<2F|?JIeul974swn=DW0 zgi8rrW<0zz9HAxm3U=##Fwb}!p9qlke$s$Py;Q$=@yBR_w8d78g8&n|jXJn=N?@{W zxB(Ie@x11?lFi(P8lVB-{<~yy2e9$@45~`N#_*%a)QDe?V%cw+k-(RSNZs_~n-eT} z%e*xMVcJ#n3pcuztKg*gKvB+N=jm08a?fUupopfV7LRe0rTC4NZ+PD4=6kZM>urG*HyLM+(=fIE94G()TId6L3EP`}A zT5P*q1d#bPKgj&FoYP;YW3d(v&_d9X(bT#lw?+=D<{Vl{p>U1bQFlQ3DrpCuNa$?E z6Wkj7M_*24*I@Zcu7u7UdO3klSmogz9U&$A1SLK^*Xg{t@(outMy0Qe%IH#RST`yS zN*|U{F%aWzW53^jz`Kpw0xU5rW26Zjf6oApkM7XX4;-(&%0YVo9H&67tvO=h7_n*@ zu^Jh%_3A~8*eM7yhKyw#J71|AG2@Y9+!*B-=u^g(on4KlUN5APE((S$XEZ%sSX1!o zXZu&aQBYHOzSMTPT+7yy;7$kEz*Z&|Qick>5thaGW8BAO(fvd8mhh(ahAtHxy9VGn z=-&WipH+Sv&pi=9_a__Axn`=i#bL4B#j><#uXkewQbK9;%<}JODp1ami@Lwr1Mpop zPE~KUDE+5}Rg}nBIr&^GrE&=wfZJT3f)W)!A4^Yf3`EP_2F$twSCXg$Zce#%MCvoA z-V%*yeYj&M zvOWxb_z+pMu2ix$iys1jX9};-B19F`!~AIVs9xRwZ8t}Ijd%{EOi8ff!S*88H>X@n z;0yS1DdH?Hs3ltideB{CcR zhxd4CkB0qUYK@JHa%T-BCeE*Z7mK=S;KfS6xxqJ1+ql4918zSldb*IuMf|k>q-evq z>#ZyW$yBs}Hh_}h{ClRCw(>f_EYn@I(OKckRuEHD{I2&kA&b;0p!N3+8f90E5#lSlH0Fe7i@27{h6QZElgY8c{hyQw5gokwymWNQ@)^x_F>AbRoE zX5U!ZoC&`$#9j>aTtaUSujt47=}(KEmZNgm1t>=Ujj)OY;|AIvDv*KN3_^I?7dRVF z#M$^119@>$`RV%sz69?$=~ht3cG9cn zo3AJEdEl$`beD{rl8J|Y^*@AP#zU)@`yZk;`UKT>GDClaI%|)JClqVI2|MyS{+Fm& zURMdX$L&1oyisQ<7Xb+QmNB@#Of+LNsWMCW8#{Byd4um&1+d39pHq`M*yF?0#(+J> z0QPw3a)|yA&5g2SGY4!ul?LuHn}%nXx=y%|G2)J%^ZK%u$o&UOw^6vE_XLlTiLA{4QN%Cq_;3$kfUIN8HMG0(Y^U8E_i<<`I`f+ADnP8F ztwhdudzY6SE?Mr~?Z%phpwEDyx1cuVa3L}v<{v@Kn;T*-qlri4rYMCH+>XcXIODc9 zq66eSMN|Y$;A}5t(_-_ViGDnk$93#Z_rCP3f;#xf^ObZ@&;Fm?n-~Ud{EE6_#-!Uw zlrw@vIo0F_XWoTGLC*z=QrB}?7HtA(JlDrYS(B7!rcN}FD5Fgz${rw5!ov1V-6=?v z`qsufUC0O|P;}F~DiYtS0a<)VRy~#uXk*34YY%t@KNm>tITlJ1OSgsprUN%4{5K;#~Lzm=^LD0tU>W-3d|Llh3+jeR$x-y3e57az${}025<&1ki`1F`Y!!PNq&Cn z)&L1T!@4`+JeqS+)}5LSD66isnt+g<)BX71?NxUXtImHT>~w;0!*(r< zN9(=BhnZ@^Q2GIsVXU&#t}!*F5&#!H zB$ML4C z1|Hu6RX=xH>a^&v7@n;wZ>ezA%51>GNd4%zxKn(%R zC|`ku;GZI7+-kFDp|L%axpg?fXC9Bnwlx}CiMwd5+=-ypR@|vVvmuM;oz$sLdX|>0 zFFcI_@a^hpkE^x1E&K*eGrzzK@tC)^(KPStfc!p$2P@g+1X8eijeJ6oNl zo8OhaVa})QesY#?dQZE)&#mpV%3vMPk341PMzSH*NNbA>q8Kt`+sfFoGPbf><2hqH zE7TU3sdtmCn$kuO9W;`6meWn& zLbxb>EF9gQlUPj+{WG;{cPRz_L@k1M@co|fi;w;rL8wi0+fy_}hS&UI${9ho%Ey7_ENr)C9{f-C>#>S_i(GnLwBUs{8ZxEel7T??#2DDP7Bf- zaC~i$Vmt4fNY$zhvEh^%3seq9)OOxT!3hc3YLI)wLkYK2ZyweTY4}V$#p=#TYJl=r zS7N(aIXH?NajS8{dr|pySB8ul=xEwG}x=Bl%{J z@X4XO(oSs2+P}FVc+-%qk;QW)`R38^pC39`5n?-h1l0xoc|jqChi=8f1ZmUJqA}ig z&_x7zp4X0QK_JI1e~%;!-5){?W4QsHQEGyJ?pB;sH7&??oYT}Dqwdfx|Ke=^Q$?JzX0?J_stCH=fFq$0MLl|y=?pASAB z`peLpKY6@A-Z1)kWk!(gI)B3PNX_Ze^SHoF%?T3EY3Gd+=@cX0BX32EUwT)ARblL43@PGFxz!V)KM$pV?cS0fuLu7eSv0tEW{~Y4 z{*r&?wFa`)m0>5(~s0O{Cya_SBpU2Rta|Piw%hz593X`z7=$I3gWl zAs`r!*tzAdK2#qdg+s9et=ww4l3_RVZOZ3>Kj-G`EGu$u%4g6rdJW`x4?YS!S_3oX zrW+|Y$Hf9qN7G-nr{s)4A^*}`gQHffAj#&=a&#^OQN$CtugNgZ>B(;j_nC9z4=~lH8ynT(3%}??~m2NKX*Sd;0lD}8n5NfccsR}`~K9J z*QKmKesi!)-v&q^u7Rf%QXfW1#&8bzdPD;ODoQ_`KHVsc8tkEIBeih}EweIWo_S zv};>kP3fzWL@&MLetpgB#*+R9vd|NZc7YKV^jR1F93t` z%^_@h)3Zj7(HCG+R@!BQ^6@T6Ls1yYXwqKK;6~b=yqjn4=dZFxG_H{ zGg$qzIfFfl`d^+NWb+N<%17;vA9Hd&KT@zH@Eo4zm?jB4KQ|J1W`wt;hI%ulnj0RF z)SZ{j%$=_onrld&Df&35*p08-33ZPA-8kXj7O z&F!9&AFGTtDeK<{ON#)^r?d5^OSPACpan=P&C%b-nw+oQ0&vU7*f|p!JGIuxRPj~` zJzY%q6gQw_z8BPZ?q}g1z`1jifuVn=RqS?FZKX!RTf=gClt1<-l>a@>Wa>&0A;#`I z*YZ91)~`KUti{tk`b^2)8SA87nAkT#)}I2iT6OJa}tjPHHLE-G|(dHYi$!nZFZ>JJuCbCRzBc5))&r&2{+}D43aA?G+?7 zyinqciRTS?ba_H;qhf&h=^;s!XZyV6f> z&pWZ@RPfe>gG0+_2BF@5Pra#n-pmd))Y{#yeH@KIm8bp5p=hg1`v%(y+Iw0TY>IKv zuPLBMN<1sph`}7BuUEF~U6olunB!jDd#_@o<(!hBvH z8gcv19QnLJ&O)?v2;oeoR`a&z!FFnh6WwU=ol`>n%(R+E!FD6qE-cZ$j^`J^cB*s| zY_EXp-J>#ygE;8X(4E67e#$$(wJdmRzno#hc^kbI>rb)C9c26Rkvvo-)xJV*L(pCW z+V7TVf5r0>&_>oy4EkQ9WMT9VIXUo^LIC2Ok(MTjGbN?d=LPiG9T#Z6tqLyCYo-en z)1Lct^OVqkr(T5%)DX3a;Q}>rx4r!6U(S|n%Z{MF)F%XXfAc6LcZAR$KhOQhOu)sg{Iu8c9NV(KpHblVFt@?BJ$e#m8R`P&^oq(1x*F*U{gs;~mC|4%>U zns&532y+W^!~&~NGhkk*1-Mk3Suss7;T8K;=WRCujCh8}VTWEChZ^JDVn^>9x)*kP zkl`ydG<=0r3i!zj|4Z~za^;L5hy9MPpeNn!EUdL_w|vc2rxlO1KzsG+UTVA+8zfGP zT)FB$K$i;YL9RL*TbGmbp8)N!tg4#M`CI3yUWtnh^6f>mR8IBZ&M2rep`#= z`>9$(3_7l1)SJiZUwWhMxGc#!&1*quO`YkD0|3TlTHiYj@&=eDxD+1rZ!lvRn3J(l zFk`U6Jz#^U`)#l%2}T&;B-0B2nIzc(B~_?!_X?+b4O`qqE`z&yEf97&0Q!FCG~Jdq zYH9Hs$^He@_-;EnouBYx?Ee>r@(KI@(oohQ=`;NYGKwiy$u28lrX5#F#i$t98e^Gl zbkU&yzt*fn2>pfdBN{~a@F1)9LLe`JU3(^>_E<6P#kH%jYglbHPU`9u>vPlhwB}K{ zD_f|mmFEVMg`Y7DQ4+57yvq<())}H^@!SlCsCes{+lJ`o|1?BVdDx7BE$U?VJ?(oy z<$54h&&vIU_`N0CbI`?Xskv>HY~W?xnR-pkQa5YcyUo%`F-yZ>mOA~HS!(;=W+`0? zfxt4s{=qVdr4!3k<=4UO@3u_c?P8hgG8E#4ljM>l(qXhhr659^taK=lTcOqWCg|8f zR&g!duv?~*9tiM~6M8xg{nJS0d*w+hr%V5O7%ICxt~6r{i2uK+Z0%7@@^&v>LP4|! z(ABY`s~v`}9vb@B&?-|`2SZmk^@d%0^bgE&^BnnHjSitp^oGj&cuERQ(Z80ksK!Wc zLd77s*-JM{8)(P0uqW+MB38N|iwINuU>}US$Z%@)FVNA|!9R5?O1d&Nh%a(?$+EJ% z6u7c0l4a$D%IW+_3O&N#mTDV8Im1cEuu3<3zD8d5Qd^OBMEk!u`|tRsjwWmXr5MSa z5Qm_gfCZ9G@8E9Bo$lV~z4s1*^n`R;0_m0BO|!xD4(^uZLUWPiO7C@!-aYnvpFOe( z@ArN8k9&Xo60mIV%+Aj4&dkm{(_Pd^u%YWWX<#4N<=i7y#($AkTAK3j9ngruu|?Jh z`^!oehMJ=4NRcKXY>%%Ft7wvB5?Q2!-cFme5%k8H$*9o#gSW>3#VhvFlqcGxp99#y zx^HnvGXuN`_>dlOvRWwg;VU=zkS`9GmT-^Uqm-Xe^4qKjr$3+JYP`+PsHF3Mih+@; zUc-8~pQ1kzdwuV@jGYB!;coCQ90zl)A6V&$O>-MGdxhOvALw;c%p^BK4(fYLDX3hts%|`~^!xSN<5d!X~ns`Pj=X^xPIu zsdHI<|AHdXXv7%G9NvFFhgZCUJrXHO`qm^DGqZF@ zfey|=9W8f5=2;XX-2Vj;1|m}fm>-CMe}1_j#Na`Vskzn`h`|55^>-Y&KV&IMeGIXc z48#=&clb;B4FyDat^#XlcVGxFt;Z0~dz@8?wmu3)|I+=Ize+D$rZ%?zSKwMg`C{Rj zR=~*biv%gA3wW%DrRENeL9;T0Lt{R(Niz_2%ZoPN&0dmoJeLmD^Ydrvg=_S#E&Q5hK>_%Q z5j6`7aI5rHd@*aFLCxBDF=wV7r$2^69SZZ5^V8qK&mIxKMbl`C0)T8_=z@!?kT;BL z|F*e-GnOi7CKN~u*Aj3e7gT&D{rE3GYWya6QttUA6I}*7)5|{N3xWXPb8zCVtTViy z#yrXs*h~6HC@XO+?tq7iNwbQ1aPZ?KIjG)yE~9GzKbBTXnIaqLptHj!{egMcLqE_d zdj{`TbA?;dSDC1cE@&TeEqcd`2~5i)0?!YXm8Cx73*7$^yyt-o0jiP)7|N3h3MKnN z;0eoN4kABVd9Jclz)uy+vvM+^4s#5R6Rp7S$L%&Mf^P~f8(4qPxHt&vl!Iopa#@yI zQ=Tf;3O3>&14aKOxByruG(tjQM-;Dud#m8$Bi9R^$t40+aP`-ChdVg4T%v@0W931%Rv)#m?u}S`+l!OP=2(>XLFYK=>o@x^|`G3HpVn}I&iN+0G7R~VcAd1`}R421OHYKhEKq*ykV#o}?`T^dX8 znB+&1^bS607in+WK_?9Y&96(VX<2CT^AenSm+i|Pc0-?j%$L12Kz}x_=AsdH!yB%9 zS>vo;6(dg~upwNIfZ@tD!22;_#AWa9jajmC~2RcO8!K zc{(ZD9yd02; zWri@_+2|LrMA`(iHfr}F>@C3k=}*LzAIT}%TkV=0lo4T>?yR}VI3C0rGQ!nxpXlQ1n6^B7G zd+rO63x|t+%CXXYZEN^~6mzU$;&S5SuMcIh_T9p%sApK`=E3MZ-}zsz59NSszRnR= zaDDql5JOe)MP;-Fc>XQ^^v_SZ>s(|%Tla(Dko)RT7K!mrKnnkk2OdW#<3S1)e7q<= zUM78yQlsR+X>zcDa;*~Kz{P@HSCYfCV`}CdMp!J9H9H)Eq+7*G%cTr{;aZX)BFrMx zf(^(OOFqkIvYXH3HO=h{&BcuB*P#<;q%3$eH1}F^1&q)PWkxUZ*n=E_V`(R#Xic41 zw*u*RkC{4?#iDw)CZ9a=6^rh!jazh|!lLt0u^|2c@opry=q@S`5U#F=na0K%Jsx@5 z0jfAn;#*ZtDjHE~=u*e9CRKY0W_m_Cqhu)$#ke31SV(mTIJ4`#0U!_M&D^sYE z>!GgK1Mg39hLQFe+gW?qfw_zn_NrVOZM zVc&6U=nlVD-uA>UbRC1nV$V`7R>zA=I9^-=bud&KEBMPZ^QP|@GCjeaV6vT%gE@s zk_*CgY+xiV(?)Dy1pex8leY1!T&43hEZN8WX0|rMnspViOId5In;ORBv%rpu@%1Lt zzKWY*PQ9*&!Dgl*tQubR3fbeOTz{j`i!p*U-l*t;VK> z(d_iU7xgGy)G$$7IM&+CMx1(fzE5EEC^UL}zT-HmKlJ)KUvUb5`JDM)Z2!NOg!Ta)p=KYn;Y#Na4WHPBlX84pB^o-rgHMvLhiwKwh%HFgQmzq zLR#a*v$F(qSuiK}yvdKC_N?tC@6k?(cGgw=t{4(}c`DHBrG?ZWR z9e>|UTFm;3(ib#CxpMDQf#RwURxywM%tyI$mEbKKr6KU z8FOdb9o2#o@rV1{*;XSE2`st%0*xufAd^FtTL)N;_Or}@ll*6#r{h9BRT}*6J24!@ z5#Z>Kuc94asiK0$=}yGFe5QRG+#Q!Tzfys=ITp0Kkz3ajM z9mU(QK^oD$A&qmfk976X0oEvj+YpKH2Fug3OOtC{lMU&EAPX}?hc$aRYa4JdJKJ{P zhK|=-V2n79qp!zz=vPHO61vzc1yW}`X}AlHnp;VpmFS9%?gx^H`dH?aH#D z9jwN69t!KvbD@4eYEyQT`|S*R$2Eh!L+$&JZh^CAGdsnminPGM7O=XyE&>W*dHVIF zR+3M7fC4FLv|p08;|-YkY+-%-3AG~26{UmheJh-gV%7l@*vNEpBR-0s zsS=}%Yemm3AMtS#EVzp=N;^eOF7w&U`aC3|?oEN$3U*^Y%avxhTc}Opr6;cGC?g+) zX1LC^?bsz$The^$Eod^g;+D|tBv%m0WUjJRPyllxX#q#rq(Pto-~Ft#lDo~G+gWcc z*xQ`K+c35oGoK~;eNnu;TfBY|`|y%GiDA@sv9o-T@w@XEsm?6#LvJGbgRl;1)C**; zFr?7dJ_Nu@RhBL1DriMs>)=?LPlGYKEjAKW6w)zbl$L zY$R>YrF*XFJ;^neI(*fb9~V-$Ld}ss>={xzTH{2pfQ_to73lBxpRLeGVekj~T`|;N zq5r@&y*sDx4*F&p5t3zp%tniyKd3;!AoP-@0fDpI-=q^Yhr4kO@D+2eeJ&^{f;T{X zQmy9En)P5C-u7nZy@h%76IcqH zs{mOEOz+A3-{X~BP(hcx^GZKvmuS*0Q!2T(GW`v>Oq%tpxtb?XI}ljU+F?dY8u&Gk z7{j5fC`#EcHbp+$;{|AP=X&|DQhC0}IvDn4@=Wj!N?u?Ba*8|DXM(GTb?r*(VRd7K zi;o^L^+h(!O>-}e+VlCeQRdSIY~niL?9c&c zMF-yJ(t{4T=GN-~WcdLWi|gPoS@JI>fQytFyK8sKkq>cPmA|DxECdN$37G&Lq~--Q zrl1w2@Tr|t;K_@n8cA{9v}vAC5s}OFk5N4TMy%}wZqKAxuBARi)Y>xWDPHETu$W)5 zzlNy*>AYs3k`vyCX0ACv!vN_Vwj$`8z?H7jU-T#6wH+k20l-Vr1nff&QBECE2tpm< zejK(zRZc4}HTNahk^CZSv)#Y&sWu}ZQQghYhlz9aDKSrXm1d`uxgH8D9sTS*=M2o{ zzJeG2tutN)SW7^q2eL|G{a%W3lSi;5K!Z2{pDl3u>=UKN+}vzU-y7t7EB%DesI`)= z_B)9H`HHk|`?z4hvAU*)mJENk#5v0o zs{=N^1#CIBGO%|Qtnz^h{IoaCSht6w-4Ka+#u`CR>tCUy|18ouLv4tHlKzB)q(|pg zWM9w8H`2QhNT}stJu|idn!{!R-wSfd7TtBsbyq;)OYOmcnd@iuePPMG7KnC z(j+x>Fkkk0K#2%S3I!o}cyTD_OCr);^rM<05~R+U{q1 zq)4kLn0t3Vn0vmnG%KaV^-%w^G0&Dcr~5qD)nmNVTLz}#YX)HVUm`iY{Y)%ftQ+%G z;@m+8GPBC||E(*V9iI?1i)nvAXLdSDrNHS>7Vvv@R~?rdX#m9n%jsKdPzfzjfZ8q6 zIw^`TwkmD#-G|x|Lx`F+>ED?Nlk{oPw^Pi8dn;Y{h33RoLV+!;C5PEqoKe(?TtklcRM``tt~2+JgAX8v4oc?LVLF5E9UA9>)48* zQkq`^%=Tx1Y@Z^&WLHY;!6EE~JM9jsZCQd|`Xq^(d+iTKl$C2w`;Afe9_-1Sr|A#J z-ri@*+f(YAJR~cre4+Cp#Px2C_%i;xI0)&@U??`{ZCKmiz*}>Q`(YP#0j4;chc%?( z2KI-&DNL*Env9a{JR`luqlA_*<=|y$@e^xE3G5)d6OyW4u-PTjst~rgJ!~#{NihJg zX$42mW{q}7T&vP1`_EJN8RWxMv-GL4x06jddrH7i&WOsz&WCXx*f$UVD)ze=a0Kt) zNxiZkII72$Pk^+#xq%K_B)=`zV7rf&AI2&6)<5VpiVXV}!Q6fFGID4!@Heq+DwoxQ zlILaM&mN9Mh!hdFko&%fQkx-j2P!z!-ADjG}dE+On^1$h5}vWhU4ZnobWalK4?%5SXN zbC4fX%>;Ps?PPN{=QSdGWcecJR6jUrSjBJoD!viS-U6!w)(lrzRZ;x+$&eX+Bmlnd z{2kZxy9bZZ@C0~@KlxVJkt)E4O@iQT8l{NU*aT z#kLoN-c$9T9N;%bugOD)fby%_t-p;iYdqc`egZYHkBku<@&nUgBC z!d=`|H(03kv7($rQuC|ioqc|`huX9LqtqS!d$V_E=u@Mg?xvycw(nN{^9HRro|7Nx&&xH8Hn6jM?(m`eX zseG4w0dXB#$bS}A zPO`7nA%@QW4l%^M*j;K=#88~{6kUi*He%~0ti`KyO>Xn|pT;n3i6I}+@(%2MN z*2Gf`n5SY+{5`@Ch9n{wo9WHm3%6Y_^r1In(8g^Kk6>WmR+5tzb#IMnrzNA(h|oz9 z&p`0r!NRE(b#XXsU0674g-8f@*xYwghZ`Bx(lryOaR)DQTj5mkv zdI)S?=h}B!3HR%e2YQr)+kDF%uCw%p;VYnuu<`1D|NR~aa=QqYXae`XQWTOPcwYJm zv)RUaKPMONd%3V)9heW&oD|pV-7A-#yQX)fcl%M>CC+jxTLr!P$Ov))nhU4k z0&4&M`@MP>tSskhvW`0Q^7Wg+q6aK~y)3-6}6T|{P*6)m=4jZUl zdirhGj6T#hiQ0eYEMJmCx%)LialeA<-7l$^6wcc{KQrvmbp+{#e`21k>hVyipY9dm zV`TscfNWD=$(B#mne};1vTXo*!zHU#BrBg`h5yq0&+`naACR3H0sF{NCp+l=N`88YU3IC%_IN z&%=K)&s)>`a9?S6H20O>%DtfYN^iyBhju%zCS4UZN8E>SVt$}F633YUnZEV~=LS_* z5jj_&u+iLeI^s}S-f}M;#yuRt|K+M)tO}M86t-IfR~Gq0cvbb4n((UXD>XaRS8A$w zrKV~)@jt2ysMJ)QN9{UAle;)r@wB~l%o)7B_QlfLCjudZSMsqMDmCZrCTSV>82z^~ z{wnvj_KfdnI6I7cJN`@c`y$DG8?`OIM2!(qX@q9p4CO;#lGgKb0FQ0V>m?TBnEymILSUZlnYWT~ zsK?;fFFsei_b_S)@BJA28awefdt;@>GLByO=s>DDi?mWCu~2@4_})-)d+eUwnXiJn+a702;Uz_ZTnCb#^WV1aj-ZjG#*o|wcEavtk`Ixu z(u89*?{|}B&8?~HBTx(%&|sA6U}u{}4P*Y;0$&T%7Q6XF=gaJEK1{9D*o$q7k#-pB z#tJn&oWlMD9(LVPK{2%vs)*qiZfqF>wVBc(e(88`;+#4)aO&aMt5Hg9!9G;zB+uu# z*Z~|DdjK!idkIdPfYVcwM5iEUzz)VLjey2bTqKvag(5kt11-Gib{4!FjcEm^;(Z@+ z&%^#x)vOuwg6b+8sy(O_@CZgXavcm9ENA8P1y!=2bC(#NlJc?gcn)O}KdL-eo)Jy^B9+rE@ ztVB4X74-!&H^d4Bc&Ui>AvtmNRW%4TQW0v=rAPJ4@3!2zz5K2i7ch$fOeWw!c8-k$ zPPp4<$MV|9AGx^yBQ@%+;!QG!_R@AH=Oh|R!$_U}r9W@Hwaw(ecARhE6 zu;)kxyn@F6ALeO&sl?sfnWupTe5BurK-)j0%f`8X2@%dX>hO{COu31etA=&?+ciTt z`z?lkR(*))rX<$=v+aOxb^nvzK7FC=LJ++@hTJ~g0UNc)AFNIKhc;(M5V165zC-k%(0xn!nTX8*=rN%wj-|T@BU$IHQWIIAG zXds~C-D`qPPcYJ6^yUaCPq!#SO;v=t`G0iPvuFLTf>_%^SJ_AMT;8}N*wMHn7?dEt z#+@C_JAz*|?+8|!cRa!2(>d=lOzkt)z;Y_Z0RcnoXMXm$?)9#Cti9krT;0jLH*Dkx22C?G_hCVQ&okm1?TxhD(4Gz+qwYBvzRe6E zFxBkI%ieR{b#FxGaN8p13!}wl45%Zkm`htUG|}8YYh3$7z8lLZp&WHSZ=>;t^Eq$c zMgvI>g?MBM*;rRBAhG#L7Oz-ZT@qSK-xgcABmM$`gBM~vc_b7|1)=h2^*~yLa9oFN zk$E<4YVa(z&k$rvF3=y0ySX#(d~$*7p4hDM74Pvk`+01)SVCT^!XFEN&iVD5%r+mg z4s86_Oyu48E*QUGSKt=UHi=RS8;dxfl{RwFlr(z_QNC3o-BRKd-(??zHcqonDh)e4 zwS>Mdt|-wwSz$ko2FA7F=qJ~nhKO7Q2 zFy`ZL?lxxZDRNDY$r@F@#94D=1)I$fE2~~nlBmmHm;ZCNqe}DhDAGu&& z`$Lf%=pAOy9evR3&3VwG^wQPLvh*E5vY%8oy(FXzqO$VWpr@Pdr&)j?w|^!kk>`|R zX-%lyUEQCi!ztL@W%H2q%i8@xbJW3uhp@&=^!pQTZZn?SZFJp}ls%~&MbEQyU<#ag!gHMZG#tYM*>=K1DSd5BmlZKg!|8G6G!KQC?Vhid9k z_O}qQFj6}sQkmki_ZvBTGfG1EO4@kH!m?TFPBO&hKekvpA1V*UQhq3E`ZemXH8Q7E zyFYl2+HXidzLu#8H+SS+*n_o9$evKX+*#A35m?(Nmdw!QQ;c9z_(%^=K?hVRfwhwp zR6$W9Dj225v{8P{k+}aW%Ecv8F%m|zDKOiby${?ZR4gnFE2VF+hT#?bo#M0y+E72l zDt09uXKTE|)^M!nj*I&FNglVzS2Au!_HggRO&N zX^gG_Y~^vb=rOMJf2xo9BHrBVD`3gL|}H7Qps)~>5@W5rgosL=@K*Ydy6PUa`xPNt)Y+Gn*Q zV}-w!VD=VEl5~^@uQhwT%kF4T_>EV0@r4sQTYoU-QcwxTE(J|1L`!pRz4VF~LT;X!F zM)qyBfdUJoH9XjWqxM?0Hra2Ux;Kv6cjw_CdAY-yb+8n{SIaOQwJcrUi1^%(G!?N^ z86eiSb(KF`|M)HgC+(z{59|3 zgXgHSebkP0Wq6JXn!|K>aPCF5e+$f29lT`Hgjk?-I1QzE{BhzCMNSu4{H%GazFVMo zq3;mH_}zM~@;ZVTdD0R%ZQGbHd?bzbtnVm?kJOm?FVXLfpbpzfTXKn-xTdql)Hayh zmpESo^2~(@n!>kiF@2%@#T)fdHxsHM8`B0$QMu8&A7f`AG|jxWax+u$k`yn)2l(Rx ze_MlV#1^w(MYf1sXpxG}zH6#I7fG|23v-Ed#4?UBXL3QGwY(cy)|@-=G4@#t%FWi@ z=(n^2W@M4b0{&qhl`oa(fjjf^W&Vm0*%85m?DV^?mwHj#IO_PJGZ6olu>~M?hZd2K z&QyColIHYg&ar5M09Qobik;w+C!f6mhh!3mVr_CqNzL^$Qge{qZMj;0)v~)x^8%*( z5m7PRA1J;(_Y``*X0{hPJO!=8Z2vEt&HML!Le1$D{zlh?-RG`~A9q!v6u26i&YI&p zkoO5mq7y0&vBtx6D51jJ&?nqk`ONyb{IOMYS`j9H{`7>)=`b&wb8&hv;|{(1mVcej z0g7Y~u|=Z)0z|Z#4lmm8fj{MiH0$Dh*9&+dO@Q;r1JZ$8S=&l#!TYHU7V%Q8#s&z4 z=W?0?>Co$6M0C*gn>U>|61tSyO+Q(00N!j=(}q=xa1EM}?Ni>-^mmF9S&w1mFUsQE)Hg4=$;Pa1>js zH2)p4cpAD;+1Chq&BKi8$0C5b(njraBEK;bDVo~Ns03r4dsrxTMsG(*t~U!|ZJFmh zeaaAOyO-SWrBiEYGdzc$)NY=0?R!Yz{aK(MXt~!I9vVeKaW6_6AnUEH?_+wCFLDdk zr!(_@PeGaAN^LG*RNl{958xhnt%has(AzRA9Yg5N6W#dw^V?((wt}aX2AA{Uz7tvB z?aWIlLr{Er7v=$P+FQwN&~2wS*DtEdn3`e^ulrg71&eX&aKx@JyP5y{9!I7$uG+pXJ+88B&;iBxp187r}0Ghw-BB)rT zl*EV5xtUpPipwrB@kW@WD}BElIUmz?Sldf?bgE3&4WL2CXT12%ww}IqGIUk51VedeU;tp!+=5GvDR%z>gXSOpI3LB zvuxJETTfNX1F2JOu7EJWqgOMGDdR`Te$f%CXb7};@IVEQkoxF^e3oVK_*?*w&z(Yi zt}A+3hVjsxDmR9LbL#zl#oM=GLWjkA$5+|CD#b&??v2D2f~wX#zJru4)RYGnVoAmQ z{IkfadkioCvEt>w1EJA1=!-8_H(lBaodb){9APhkc|utb3xd~&ZFvRC!jlR5DPgY^ zHci=<0&jB^phQ=7Tj|Zb3)EMThmk*6@0W*dX2TK9op$cBb1Cdp^wG0E+|-;)!AIHD zZpzMgkQl%P!ph`D>|Fp)K(N0-?m<23)I!*QS~sSn7OFz=kh%fu0y$4CoVAJ3pNV*W z0b%VlYU_HGy;Ir#$!MNx>YC+F1`5zp6@A6qHHTqEP_TUyL)?@)kJ6p!i}OrG&7rrN zX+7B6yyox-viPmGL#R3IW(j?&l=B#PO6h7V868cTt+iibTePBC*01?khy(257jG9_ zbfajdh-V?!(;m19+B!<$-96d6Jmc_a#Peg8s#HYj4tFjMe1iPD0vH5m?PYw4V|lu! z^*cVEp$gHnJq#Aph?k0ke7p}~p|n*7ALTL11u2{Mm4YSw88Yx|*gx!nNU_oylWb*$ z(j%aep)%$MT;CZM40prPf9W}IzcdXD4!gl$oL!IgCMVzm=NpC~C$kT)W#zT#FH&t* z{=C)88vax%%=kyvD1DgbDSeopNGm<@0KZgvVbJx@7?=Anb7FdG_L6K=6qck}SC?cJ z9xwgTI=)adr+||i0dhktL`}y=tj*D$FX>GOIZbaYy0#vVqPz@Qr$>5Q2RxtU%#7@W zsF|^X#?e%^FODYouyINm%A3aT|F*h)ozv{o0SPO+wblGFOY-_y96fvc;lum4pEFsv-p=b#Xtb0qSGYdQob`|8xEy3H;ZOIohtrvjCA=5T} zA%J#cAX94?pLY%0$g_w8*f2SOKg{CSis`ysjK>JTO36Q2rJs?#6M6)+=jIYrkh$v{GC{edh>LSJ=dZO9&y9Fsp&40sUf~{Sz^mO;Gjx zgoy*a^aF2xLTzfDaJI2VL3X|1pFhfZt$MY(;7p3u-d8AHKz&fBgf)L_Adg=obx=Xa zS;R}jTfsI&aoaBGih%HQJE<$n7jA|0RrmX-Q^Y|1kjo#xEYRKx?yL45A;?3RkL;)f z=Phm|){H(f$h#B-kmuA41C8NX8F11{ZI*QxhEacxnc!ULoDVTB) z6vi52Q1}0cudSvu+@UkpV7&auCxv)(8g&t-I#)2esJRv{`%@FipMzEVqor{pM+f5) z-fZJ2JVAu!X#^E3B`?i*9@H0Bny-8cUZevG4}XtFmwqJ%`7@4XwCQq@>!da-ZuQ6U5(!zs@oHZhA~^H(*bZ`c zku{Ine*Cy`J1hsaamj=UQA?QGjm9~#z@Fp%{qK#ZKnl2jqP)Dv2^Qd%MkB-kZ?+p5 z;&yjHc(Ps4U;2`2cuthO$Vzj8R?rd}E1`x=@c)Xni1pRS-293(EK2D50WjBt^`{aq z9o?HxxkALH$)_^gbS-|Lx}X*;i_rV8aW{GxR(tij6!1`<#sS|^6P;>?p?HOKSMb1g zpGS26Bb}4p75n5arFY7;Py2V0lZCoT0{)>6T8i60N}rZUMS^)#^uD-^8P4n~uhWvH zQ*8ZG-g=|SY#h`p;=+_@7HO?WA=3kZ{{=JEKOF3eQL|+)E<|>Fl{R>7ay~d z5__KzwzCWU7FOHrx~eZ$=z!1YyL3PfN&1-Iuf3i$&RMbsnu%$bMkC#>qagV3HIL%9lWSW{I>ggpKY( zkzw*EP`;|nTvMSf?jMSoqxPP&&?KFI%^7IT1u!%tb$`xA6U`Se5PMH{LV3+Tnl1k~ zTJ5Wo4tUG^*kXG-rEyP;k#^-viNZ)7#L_{I6FMgK*ALQ>vyijNMDu{#--x}33UFy0 zi;>51`vE^GQ@$*#qyv&!Wbb#OnPKwx*J=4<_Hl`{RqY~wC(w_|j6SmzyqeMVa1iiR zxNlXVz0<$9I$}i!(9)Ex!1Cd1&b_ECpCUe^B0jcTKsn9F9Hip<3i!g!q~ZJk8BSew zFZuC7{P;MwBCuHZ1224?-G#=4$#bsLq6d!_|uAq^CbMoMDP8TNMDAb+{9;sBZG@G&zKY|>` zA@{2kH2HD4v?E_i0G0s8+=em#ERimRDBAUpKus@cANKF2D8?dT9lJ#xbgaG4!Mxn6 z6lzZ$t7gQw#pk4co*_ z>1OGPAhpN*aLzx{-V5nje}OwLynDet>o2@>$`w#le+5i+mc3aYd7!|?DJ6pJue!s$ z2xq66Un77wcQ3gL+%2o7)INiPQD@b`zyLO5VQvvTMcGZ&j}39$E&rMg9Y7UE!%J>7 z#L$nzdEXpXnpRb^VxL z?0jJcIp5RfhQz1`e%Li~u)dEjqVS`qFc|Xd4F+5tX({;|FK-)oBszblGX#HCZU>;u z4cNy|qSaWV&EE1xw#=?JAdNXD?_OqkE+xbE^tL9Uu*R~iWbIYbTl-zroS6g_Nf6N; zwe!UpxD4v4cF7a+w_TwHg67i%q}y{{GJ@x36=XeHI>v zntr-RU(L~>k}ZLK&AO=j#fTW1PD)K+xzQ{hnHhxnk)C~RmEKpH$iiyLRwSNSMqNs1 zHg_!^f|=fq^?azU3i08R9RlOwWrSiHDmIMwOs46~)frc5f#WLepFfdbrONt7ny2%6 z>Ou|z5(TR!N^xr*O7~#Y+*3(^a*XPsN-;1)KiW+WR8N>PgAn`S+>Er48|Nmd?Eh`X zta#0g87`0ulSSAeh=iag0zZ8QD&`AXE83+SWQX~(B1naiR$>3M7>5Wxvq~S}@X1nU zzoE3K=vjXptsOHJSyYDjl9#|mP#NqC>sTY-3>Je%Nl%5d z!K3C2IkDAq`0J|bP*i>GJ8Y6;%J>7y$%D@)xLorR6gGpxIRhKd^buUyxRJC(zy_K4 z$`-)}fdD&mw?^-C$e34ki1g%EIW0QMcN%k3&W1$X-R<3}MJy%aPm7$FFIbBlmgwdp zB@{H~7jpY6)a`mzNmD7#zF6$fhNuF*VsG;6{?=F23fFzN4_FV!b$@KH8P|Q}rAhVI zeb?t&>NZ8}I{1-1|GNE3n2P*20x5TRzVvs2a{ZQ@ubicb&|+J$rp#X0O&410jm+sU zb~>ubCj)<|(_j>*JXOtLLAZze>v4hn?+uJA#GWD?+H1na8?`Tp)4T$kW4dh5Azn$(tbZVnJwWR z^f31krb;NM|CMFs#;fOPNZ57E{=tfWr@vySc-`JSjJ>@<*C`V3CQp5pf547=s+!B3 z#6IcssKq@k;#o*5jrywNu>Sg_;;&zx*V4QFQ6CX7m%ZIPUVkJpGd0C=x$cQbpOStk zIqz@dmZ*aXSu^>I&Qg{P+r*#kw!e|2OG7dA*VenXI|#f!klaKd@EWcXeP?jT-sF9I15MNcM%?pfH$4&_Mo22(UHm)S2_JJ@kz7KZ> z564#~XXfn6cikO*DYj}s#qNulyYqGr&P=G9?_ArRm2#Yo18g}GxM~}z=s)Bs-Zk{9 z%jE&zzs(U8#&fxTw%)MSSde257>Y36f%xiD?e)Mgb=-t7(9_sJu{2$K-4LecG@YjF z(_$<3W##NLyY7y<6kj#3V$a1a&>WNzUp?Phb4|`=Kfzi2(b0jI{w5nhPM!rI$EYLd z^7JlKdEIbjo|=~+nG&YM6ibyU#yd#X@kypDlkCf!rYW6EGjn#EU3W#N$5qV-!Ayl< z0w?%VHZij(?KUAZ+aa}_^O4KJ1=JJ&e;`_kyN<= z_y~v_``cRzY%UTyX)_{1R|EQ?0YbSL~sl!a`@w^5b%u>?@*r?!a*>5b*1c z>baw%Hc%U}G$0tYk6uC?e+#WL*G~>I{fj^Pl=DQi|FUMvT4o2v)vu*vC9@52>VXM- zB^AMDWbe*@C0I<;xO-4$eANPYLb92ec&OT+hpJD?67P4`N31mX@^v%&Orz6%hhwDELo>WV?dya-AUTeaT!ldNPuRTCxQ6&)aIj=HuMI6v5hWMx=KkOMD zrH?d!^dLvM>iws&7F`kn4pwmZNdC6Vt{aD>M3|=L9ZE57%HP`mNMzykV_9uF!((;2 ztA(E@vU&VuXvIs|M3k^C)xFSBSMyCXxpG|Ml2mJI2@OfnY3l6Fr5$45BeP+tr-vk| zM|{vfew;qx=`*}m~ z^&*`&)CMEY4`Y$kDB8+5k*@41^8C5Oivn%#rFzvd$r++q%+q5j+wJYl8EiHJg0u&;B zZjkp`=@T_VTBIJJqn1FEhq!xR-Bz;w3b_?OE(OAjl^((w>7iN~+J8-gqMjm+K!uGr zY9r&n9Q57b?_4!?52RCKe_z$`FZ&FO)+gnEbMK_KvY)TI-x4PDiH8H9nX*4)Q?BdZ ziF=YR&b)YF&&9tpH^=Tz%$%8)*``m%Vsb9gQXzSZvZ@O&PrFtuc|VpX)*a&+;pC2; z+ULr)l5wTqTqRv`C~1QB+%C}+h0EiGj5K-ke=)D(ute>vp4i0_;$LcG;0!v?HLLDNWij3Arn%=*kr>zY2Rr^k1Z*)$= zHZDALv=G~P)8LdL`O{3PsisW@+xi{FHg;xko{Zg`kKMf4v0L&MXGjcN}Qng)g>HXUU*Ks zKV-Ig$TZ)+({X|2?@l|vC4+B>QN{(>5N9`D+?;fHq-lZkv3SrgH5k+@d-mn@(cf=1 z&09-T4!CyF$%5=IR!Kk8MEO>%^lPB}Gn-*|>Y-Dz8u&}^7)w~mA!|x0C2KO{26ArYJ(%K26=k@K4qQ-^bjM1!L;gMR}@ z*rFjg-}cjFc>9pZ5K$Vy{Nw>VJ{+r)YUqSqqmq7-s%u{gNv0RM)CY`>uncHmOhe!* zjdN8~pgo05#o_f_#VhB=iIB1C0W&-~QwjNdz*KhqxskKyz}Za~HzzolO2oP0&kwa? zLl8LYvnEjCEEuvnKvUf=GA3$B9`r&Qq{?-Y2jP0GkZx0jK_wk?l7F>IzoOq2hs?5$ zumSpJ7!uy>_a!%M3Z||%Rap~mt9lI8d!$czcwI|PV7&HtqO&N@_V%ld~D$)IU26UKUHwki@Nmy~{$a zFxRld>v*5r8`Zl1pe%Mqe#@n*BrwwD&gW^3| zV{YWz_GCz(2nD+$GLy;|IOj4Kk*5Tq-#^ou0jHOe)86kHi+snL={&tkDFf3@?4(sV~|FvD2fKu9ut(>gwv8lr+IAx zj~ehkbit!&XoT4gh&@v{hDI`Z-g!RuZ5y}yupY4XupZr6lYBuL8$ZY1lougG;W?WD zNQm%ff$Wy_h;AW6!I|8}2&su$b2Xf`w5su=)KWqvF)X~q9FA(-z1%U8Ke>fxm3D>c zu=3@Yg=4`F#Z~ZyDYUO}Or;X!{>ubj3E(%IxwDP|`?Ir93DA+;D`v;*DVl!4#JZ|k z=vUo__eK?fdMJ&gVdQ-2$?dKed4H%!yb8d04O*RuSMM{WGz{l|N9jwkciQBdtJ<>Q zKy~c0kf_o6m^1H{9g~`vKc{eCYR1OgZShA(z#uq0 z9J!?9*+;9`Kwdz7t#a)T$Rw?{(rtCky4yU%{j9W#XSh#}qRDKbBg6f78qIoV9?Sr$ za>-An!!8c9o-TP%w#BMh8ZP}!bz%a=j8lF!B;SQ>WN6aL|lbPgp(xM^D_z z<(H2uU&l@L_2B0-43_g-FY(iGm}#CV`QXKkm$nW|8*PTk|8qFI$bRmt(=0ttZt9!s z?)`k@&#!q#<~a8LY8K8DsEaH-EnjNQ!g&t-z)1%G@p{d&aKrIQ*2_Eze)jp`kEFkZ z#ytSO7Jpnsrhd9uoYHExv8k7W5yi z9`||Ruwi=5xund`%MUA`3|-RA7wH;9FD56S*$7);c=FKnIT?HRod4&-#!-96URdC~ zeJZlzd$9?tSev$*{9gw*OD|Zv?y?)ZSgO_>q)c_ex}u+rzdNURip(>bJlWV{dl7Qu z12^&9_^r6%<4ccQPn0MttiuZTNt;%41uJS$$GsOEJz5`qW?5;r67}jg4fZl(1;%7Z zFw=EYEMMV*eW{t7vbQFtjmVqle41A=Ol0q`VME%2lMqK4Y zy3$`tc^>K_DBlOG*#Mr{TYh)V`bTbIER#Q~vcGum@BY|rxlihM+aN1_W9`p3+|5SV z-+PdN->80nrw1lUl8|ml;`{s6_RHmG`G8A`kWTzTnjM!7 zM#Oj)=}TOc{H~GykGp1){z$_A+YR z*sdhm`d5h=2FZZ3BZZo|^OPuxru{FRY2=l{%;mE?&NQpf{&YBf z^+t^5scd9tcr+%AM`JE3iG$vCfgs2s`GN|uZM`f%a+1GVG$oE3`MPr1m-7o*lK6%E znt=pLypa-=3mbMHHf&J?r4n4z3vo@q(QCz{Hqxstr+Zd2CAb)axT57?@%i9MW zjVhSV5uIj>6hcdXIH)*6&E~NQ?8DWpUt4<@drSC2@n+hspxJ_?mttn$w>tGy%B#*S%PBSf4+G4eTpP@Nq7~dHDmN+4 z`_T9MabuqlB)ED>dmv<%I-=euGVMw`x9yVahQtHIjPs1Rb2p@K8Fpy2aiR0^3F2aK zv1~OP1c#^@h0_86ElhILF!@brXf+(7@rpwf1czv*-KoC(p^9TYSVQaC2}B+~+(h}f zB9C?T{zrCjT!TCwIOLHX5(jyl=dqr6a5C4p7o22nNp#3#1mrQ6b20#&{Obr^;;+mv zU5@v0slv3Cc0>j&KYh+5y) z()du6Ju~Nd3|lfte?BSi)SWiFX znne4s@DzQ5w? z(~i_x-0>DxJoxfQ)Cfn@&zj@ZS*F_kg zW#8acQYEp<@MF2}`Va&L3-SyQaDOOvzBr9kj@QTjA9Niu1aE$k1@Ax0S3beR)0>?V z^v4nl4k@9*P5n~)7fdcVoLaQ$$~L}z@PzY_+2oGmGwD~FC*O`j8jSRZr~DiH$ll1n zdr-xi`0V1!s3&H}$y*>uyndxC)2a^fZg^_EuZWT-p-C?Vye|^o^h;SWPm&tUV&%cA zpa_&HN;j!UzNwOaK`axAQ5@MGM4XIp7C4}|-?1!HDa8cPyshVD@HT&_bXkI1ls>>3P zGTF+ZAmb{?!0%{9va+&t!!gHK%EIS3P+w0O+JY(OZ@tQ=Sez6t`Yq*|lkUBk?_&MF zXpZ3Rl7Hc;>p5gj4ngMR-n`l&0%_`>7h6$mc|g5V;%(95pm|)O*}7rAJg%$Ew}B=e zaFy9|4NZiGg1YObFlgwc*Cvk_vAgiXX}Qi1sZbTE)SleSkqm_hvAgpAIF!8+=gu0@ z8*wz0l1Rv=MlYF=&5}^!_RbX=SwM5IwlbB_sS@g>v<#H#IE@#5;_eW7AZFjGs?6@q zI)P~yJCKui&why_W*#|<+_t+8g6DZ1juYj85BOcbO zu#B?HNK{&Z)lm;%bUUBiia;if7uA#a6MBGx%t5i*lv7=8 ziuLx6}_Mmr3(-FOQ> zcU@f*VNyO#FdFko$iJNrGAqkydD*^_t(Z^?P3?J*$`LKbjH*gwVxS%S`_1l^%#~@o zbM*JO9{7=#Tpv`>TY75BZi-MD>S&ak0)dmAr!F6=0!9V&nyh~>cl_cZUkqL8N^65y z!BKTi@sB&rZinJ+yVKM66e4f)($Mk+2sN^%DTy_R6GOwy?IBz^$0Tx<`V>$@v~V8Hx@rLs1IC zdjiIq9%bJ#n$6Gh@7gbNY@Ppd8P$lzd6!@X4Gj&B9_H;6eX&$>6WAN~4b((;-%4-j z**5u;bOArCG#TV+aO15s3JuL-^KNHZ(POYEpVa1?e0JZKQR~tTWu)b45RVpN^s8c7 zUOGlk3JQuIiqS8X=_Sp(SPB~!yGH<4;?4U3f9oFD=uPCB6|ii1xkxi;DmzY|IzgMy=ze7vL6OY3>ELh@~U7}%Tkj)G>_(tgDwgJ@gIZE>12xHA-~^_5G-9QA9is_wj}FAqB!AdS3ndSs2QubWD(Zt*GDHnKd_z3I3G`pJ6w*rFPiOZ|m81RtN9GUFyPyIT|$e(@9y_*;%R}oze@j zAK%&w4KjM8e2gNfaHScd(m^&qALLNdScGO4oZP#7)yug~<%`z5OEow0h8hgfiJo53 z8CJd2`d#RDIco^=N+jhIXv~`+-9X^ z;&l;2gOf=H`9q}*Bvlta&nJ~~jHOxPl=DUN62y;*m3f&s#u9wx)q--gXu4Igwya%u zAEuH0kVyIg+bsqzk_AT_#TKkiSh`QS7T)2l6RSj8Wsq;9L>F+DIA!Q@0lk%fTOlL> zTevJ+z9eYm6_jpI6!~chGW_6lV=tVPGxBZug+s{g+|ae_jZjfj*C=S5YS3g4-{JZI zyboElCxgeSeIfxF4ev0%9DN`5B2_o+d}QV9@`D%bxk8|hH&DENM>}3uD7^z4#2~}d z{D55$c$S>8yZ{q_!WVjjm8N0p^*t0j>KfLX&)>g({;$|^aHq#|_mgwc6bc!0mQ z6ErhKn?u_X({^Y;OC0?mhogVIKsp?#(0mUji=4+eHj>4uXcLX(8-ZFHF#X;k5 z@>}}E&BCJN=(-*(NXxH@jM$r09a?*}SQ&?@ID{eG>mSn1;E zuA_F+Inj18>)O?e@c{wD;`@aU%d+XI>RoE(Q^}e$0rlst*xQx91TU^i*~)**8X6%; zR?*R7FjW4fm_8=t)s#xf3RXjUA!xl>*f{5EjkTJSQk6E9YNapG$L~R@-7lE^iQiil zTB|Bn$;;@aSamTQRLf*urQfYQDTn$8+L*)1p z{(DQr;tLnAU%N0YG-UX&@UY<*OBA-7`<5}>D}F(o`HCQVgM>Eps%N{8Ew47h;8DN&WmBOIlICq*cn2`d~?0ReCE+T1~C=z}#SmEW(9u)QYSE zJ>#14*vzT*F5L;Hd7H;UI*{89a_?he!E7nWO%9PiFHx~)XzmYEfd+@1tQL@VV^5qQ zBA7i~V#*WP@-tcoKyOm9wn}Yj+8;HFIUHz*B+q$_jAT zKjjlHwLH95Fj~N*zI>&p{timz%A{Jpnp8{HveHMHR27y6%XmyaH(3{ulACKw;XB_t zBPIq|_BuEE#{pK3{9qM=;S@(Io*%5rWO0g7oSjc&^KGwN#mh8x^;Yp+?6*$!R&gg- z#l2p$ij&x|*R0}UlvHmO*Gf0pvUvhUn(r6#aV0eS4`y@#PMwNRmx{G zbS@1>;8xRP({C^X9o;3d1^>qs3~?B1CEOGg?gwyF&_;q{3d*kN2%Rl`+8Z4u-bnY{z?CXB|Fb zFdh`sN5ennogtME$3l*;jG!I)S2$^ZQ| z<494lQ(T{qLn4ZO;O7^W2z|~_+&p@_TeYIk-t2AG3UcDsLKQ!Q=B@aECBt5-cdLEi zR!1pz6D4p*nrfwHU}!E@k~%7O6TmsZDW=dfWW3IC`0Qo334A;z~yDPLDt z#fouL;d3rL>H&CX;>C@$V|(7 zVf^W)ZUg;;LmP}dnH*2QLi5swHJXx1ufof$RgjMNH zHd-xx?!=bCu$jya8#;l{Zosfn%#APdsc-(Dg{@vQI5fx3qb22iks&#X`l{Jd-jede zQoDb!@`+xtK49uA21vEzUh#g-0NKpXtyd;Ueb4Lv-bNcwjo5{$9;;apAMp*vE@{qG zj})^+^X&Hjcgw`t*P>j6fy|jTuLx8u6ALxxmdUfnuURIr8UDtuH~;c~S`C*SRzvB< zba0y#94>H^p;jYkHm{^c1|~_BB&jvMJOTmsN=v8cunOJ4qe?{?PPiOZFGJ*MCDa%n zIhRVGsFm=~Y%`6$+87j$71Ky-Q^<9^{bM0ZiTK3#_H&bb?M*~>myJ|Y@Mqr7*_+Zh zf!?m6CN%J8HySB_X8jLf=xMO&ej!+?0PVrbeIiy~0|wWv<=5V354?zzf^#&0ANg$zOoMWFI4ALxGRXzRX8% zaTz0Du~83a_<;|k!f4VUz8HitO z^SF7zpA7>}@#-LEKCaGt@$1pcZuCCQ7Xis3w}_-}pQya!QFS~G&!W~n>FIdS**!Qt z$;xxfSmQ$pH>$NfKO^3BvyhsC*Ftb=wn#pCn(a2c3<@v+Bchp4^5q~?J)m~3(D3N`x6jeR0-5h)&_E{+voVV9-5u#Sxna%znE z=I5p-W>6~x+7sl?9dAV{m13zey}H_%6dV+l=n;K3I{>+zcfPa*k_<+DeGh@1!6<)+x2Lf+5oIhXyWQqq^MxJEHH#9e6RZ4qYl zOm9|TtW{ghqZImsz7uIO%eP5yvosZ(LON(& zrp3ZVVoV4Oj7m_nu9e89LK06u@+f3)a7p+w7sTiM6{RbDuIStpoAjQ_Wk_~n?&Iu= zTpn_IVS361u%VRREnRbMd3|TkWAo_ShaxQW=}KQrKQ>*ZSvUtxJJs|?-r7IQ-M&Jp zPk-LN)6u&VX3-q>BkQ0Z5GV3qJ}k9hhw>9m^(=IZ>&x}wzAwggxp|oyD`Mb!qjIVJNXUP+Gp<;u7vFgXE21b;S0#9Y zw{cl2BAEwI3@X_Jk9|A_W5u0Slb6I}GG1;tVnMYH3JO^?sIvJ2Oc5n2qoucQ6u!Vj zqS$zwvZ39BFEek~@i>z`aBRoM!g#=2h8eqZ}L`f9JIW}%Ex98f4ga{n`t;;dV<1KeTVjNACF#Y zCGtqY{m9S@sxV_}gtGhbW%K!HPO|W8Mq7ZPOOLyDwjOqJS+75P4tSe=((2#AjN_KnW6S@SY0-6RjzPh<;i z(oX^GJr=8e_OXYuxNWewZ?U(rxNZ32zWmEg^Ir-1ZdG&D)6? zX>Q)N0!;n|SEh3o>c`hS#L`a(0l;u_YRUWUWweCuIYeeJAMheQ~ra`1<}PP~y|3~S69lRAd@A9XJ7sm4s5 z%VOY>jWpebVn7d-yCtrYyleq?19i&D_pi1kd3iaG=ef$s_bV4h41~dT?)CM@R)?>W z%xc)1!s*=GW?KO@HovSNTv71=9VO9Z5hvn52Km1N)2Rb=R(d2qR8b@9C4x+OIp0^@ zhOFPO9Y9k#XFUtpn_L2Z>}{yIuR`+j3uRj^#tJFWs*_Bme085FGzVKwT+35BqdLyk zEak?j$xAc@U`n`gY?u;&z2+$$Qy23i>_bm8Yhl+3)Do+Td&Y$o?-Z2Qr=d!$XquVE zDAv`dSE*UaBUo3zz`7bR;U;yZPRDOvEms zJY2tq$V0%exbU!H+2B45yJUH>^h+pP*c-S0r-4`8+bRybhPC1j`wI)#O+^QmUxYbu>yli}I zdSJwaDlGJ;V@m%;U$@!`Lajf2h}K*eF|lD`!NZ1OVi!w6VUEa>ilsR8&+Mgs@M(|{ z^Wu>wXC`p_?xn@_2!w*<)6E+z?#+$>;wJLN&rp2i?jt(7lNeRFDp$%s>Px z!3$1_Rq?obKb9!>}xmHbz!^p_HndTD-W;^eIKd+`k=9tG@Phh>Qw;!+=$gcPH_38{4={VZ@><;NvhIY-O!Lec zie-Jgm}k96KhQ1l$K-YUQ?zN{rhaumPgB`EmF&y(u(umtSR3qZWPGa2r$?R&fVEv& zc>ZRJ8@*y3vsJsCC22lM_{Wm z5obJT4>jE=_?>sb`Awm{!upv)9kHiS8Y;qEgTr0^Z)f`rHhgvXneKN4B!Aj$-!CvN z`ZLKMA)J}=3S(APOTo~Wj>@cz1*$0<&=O#z*4dqTlZ-}P#!`_M{RumieoZC z{IF@0cFW4m-)z)V5{nf(Tct?`)`%@9Z{4XWk-I}0Y`!=6wdIE2En96$K61vHCCO9R zErG|vzVSkL*Jbr>=yRVaZRqp!e?=E1ydv2+&XvRCut9hsS^{V<#^O~l@AIKE`Y2y!@w}9(SGi?_U^VztJi(Eef8d)cRQu9_8&e|wGN zrS%Q#=lasOk2%LH+}YAs9Dm(lTWb=Uq4m7T^wcg~m+geVTZGGRQ=0U4IOmv+r786+ zZ(g|>ET@Czq*p9AS6FUR&+?RrS0V??{tlK)R~vVyopz?>U8twdCQYq3wtqEITk}s1 z<~CQkpfbek=m?Dx5x$dx5bO(T2=%+&4^w z!&YvEx55oO|LFL7JDo=WHSEJ3x|2|caK0COxHZRJH#dCmx^d5GY|Rf?3pBu2jCFJV zdNZ{%|5$IX_vDPhTsIX+U3rY}HFJG`fkDNF(^SsU)@|DD3P%X*fvI*X&E*QY?*PSx zYG5j`-g$5pdF)TcK33z0PE3j3rLe_YE+fwYY~j1ta(AADVy!Pn-BrGFEiAN$&@+ zreFuZ1$K7w6GI7gy4+XTac)^`+$Yu& z5VwB4g)i$=k^3`p0PBF0OjFCx)lhz}dN2*nRS$le%q=nUgDj7UqW^3a_~kyqA|;K8 zS_tC^1ARGIxF;Z&|l>yLJcXx?YCw*rZ(n zOvFWq0Zu4vD_a0juUvsPCb<l# z6U8NXi+!TT?;oFv4FIPAlBu|!$9G{r^a@rBB%0($k)&ah6c3>TN4x5nm74d!{ELxX zj6a*e$72hU_t?v5AF z^A?Yv5WN^3aV9!3kKW__0`80@59)jOl&zxIN!Hgb?Fla)XS<^9Z+LOf#*|M}%q9R? zK&HRAHdpC01P4kU05v0;D#i7Cf7q9*OoUP( zfE#5>JwMZ_Zp=$O7t&TbDU_t2yRp}e+}J6He>0H#H;TLQqnUb}ekf|i{f(NdcZzTD zpmM#-p~*k5cpa6O@N|7C&evyXT)*(4*;RV{h}5q{WW776e}a**Q@iWC9bawJzhH|* zHdk>*TCw(O{Q8L*!*)f%9dW~Nm@n=+mEy((xurBIDD{PM9GLw62=E8!o+1SXW@wcHKAnSW{Lv4d`S2O0gE-}2z`|LwPYZ=z1- z?;V~CXRe07o_AS6Z5^-YU?~Bw!U1<)~w}>E;zp=J{vl$CDS?taoo*v)_zkFoouHZaAD0|VP1W4cgiWCe=?NX2=v^%&Wua#2Zf0~rMsZX%eE}Ti@s*Q zyUYa5CU-dvcy|qJ6^6CK+Fi%J;7(@;FV}V8@&OOZdVz;&V*6t0<4||zuEy_j4T@@O z-vY|>CYdhnI1X237eiCod7B#^_yYxe3$+Xpw{L4vWlHh6blcdN+LY218%;rQVkRI5 zo<27}&^?Rj)Tv_x>&QBGFhAAP5jlVdrYY!mYF{5EnnQHQAKC*2)mJ_lOqpacOnmTE%P%e3i`89{BqaL?;`9JUJ;|OmgbYt?sfu2)%b0N>PB0Xqr6YpS7zq~L$ z)sho?%gly?)>{$GspE@i3i(ps889tDClWBTiRJi;XggOa7X)?HNVKlu+dBy)}_zmVbt$y{SaV) z5a6(@Gp+y*`-9H8B=?&W@q&yrdShD-Kc@R52$|*YcThv1k+D z)eS$&y7(Q;!9P;K=O^M7HD~nVeK|nr$=Ul#-@o>`Qa*I6zO#4%nlI$=8lv!Waw-0j z_ZDwgKA=!@ESVPE5beJ}01K1ZtdnXfNT6!^w7(4tj(<%q$9RlP@c?l@Y1a_E))r*n5)aoy4XRLqsxCoZ+=cxud3 zKyuVBl1E9tVCn#W@T`~>7wb2Rb>Yn9@Fn~};pFEh7w>_SUXO<=oUs1_y`}%f@wvA$ zM_t^T{b5dt5#ou@;RR0v%Sm0b()xK}TG?;q!%_1Dw9h#=MVg}0OiO4)#%@3I*)=Pn!LM&VArQ4mz%0`X+|F3S^dhm&c~I7m221v`jmqI z2LQdh?yA(?DzKl$s@;N*qZNF!TqL{La%n;?|NQ~H0UAYE2k_so^%1BU@5X*xdP=tq z2rq_1`c7gl3ld_Yy=U+P$2%pD3x17gQ&Z^A&ob|8?U#ifPZKEYD}4YMoW{GgS2wUn zNxaoq0#L%FRkU8|)BXnU(;o01H{#m??!3PDAaAev-o7ikt*qS*VDqt^keR9G5OtK0 zGpYFxDE=Z=?-sl<2h>uI$Sp8cfQE8{h4F@F2uCX-kS2VwTo-U4Cz}lt;$j14;q;1!2&$AzBU$QrI*$Di3GseC9vp9Z~`GFb* z!|67a=1^=-V`V~o=Qm{|1lU`(9s)83T|e9f+>lNi*}GRhsB&hzq))_*iv83D`)77y zy#E~573#V#i%ab@u~bd{etLZVuJ#dgzQD#}g_{rW+UwB>>i@MqnAPFPp*IR>Q~`Zg z(8^Xu&8_5I_Ec%uUPu1YS+U%daqFfD6#58dzdrNqQpYXP&4m&l*2u zaQp;+--P1@oTaZsjt>;@t#h^djH8o#Rc2{UuJL;2muAvIOvT?=_E;Ym zlNyk2p-6sa(jeJdFDb? zZMgIJhmKuMq4`Am6aD>&P_Iw=fUc5;T^ zv;-gqgv-jl~E?fiF|6iWdnOf9r zb|4H^q|U>;1uI%hN2p#7N{We3QWTuWyqx?!Y*;MvSokMGg(X*cFRRbed z4_D6VHz{fT4)nPHIy3RBi0>j+x=MbMB+AWMBYF{9TUZR0ZX}Q6aMeD>3L{ec_$IPk zu@#qJy;AZNkkxn>>mxCmC9rwo&@ZFD1)|ec_1!;mb1Jm=15Hq{W`U7C{BmP&f2I#r zuN)MyW~8Et%_;8t-Jr{^Fs1MWRrbiVhjyXRUOFV*5!v_d^m&N9w}d`@$-XR+&MGgC zdrWv3rXie#OV(iu6E90p@r4%l)5VwUN{Kx%gdKCIoguYvBJFy%)L+ayeeBBRGZUj@ zMo${hf6UQbJw0aci753_xLxUdopYO4t$l3BXKHXeq>FcMG`J0J;5PDKZasBu9?KSK zl!5(iZ`xkzb8DkzJ*EGEF=?5c z{sK``TToBGSbg{R+?;aly+ETPt*D;V{gw74#9R?Q$H)h)XPvkz_}gXMGi^v@Q{O6qB3HWA)U5%j>vpLj4+sAgWsdmVN+B zzm`ZvA?yctS`i{|Q&_4HGtV3;x^iZ6LOi56aCBN0q=*e!FTxVOgxM9ZiO?@M4ohfI zuX-gyXYj~HxQg8pxft6ApqZI%AGN3UwmAuIpq>yghqc%9Wm}_|al^WHCFh}z#!^Oae4$)>+cSgdnBFU~kN@Rir20bNU%k@De|3N54DzG7>-N%cHw?{Wxr=xMk+tb^ zO*G7|1p5R*+1xgBbr#Le=0f?YY?C4sFypDi8n}qYtRvM`*^{GU;wJfE4RX0O-fLI` z3)bNGD|u3>0KtE*_k-XycQ?bRiWQ|$Y~N62``$e-*|2?WDrv1$Q(Fz9PxGj+iJmGX zf3&+#I(EQ^HZl*^bCZ=UtkI1gxSK_GY zXZjHJcfNeyzeke)TAKeO4c+5vVoZdEDTh9lLODcd=*>V@%t3dha^io72k|df$sq!r z%a@vPj-Z2i(w{=D)~bR&j1=?04NBd?P;@jH!U+JL^4!4FhhpGozTfzL>s$rXkaLxD zQ~S8DNzum0E*@87k^Z6g;H$BQ<0z3AxcZ((9dt#*%cgx4sLozsaSj+&r_?RN?Fg80wIf8`|Ii>~1#;6XcsxOK^A;@|qO=?;6Fj z55Surmsh1CuUxEA3}?qvQ4X*Z!5x_SK(ZL+#+wXuVUH*40{3NPSoYmO>%+vvpgA06 zew7o8V@|`mb>}?~<0yujT|&?JW*2#a6oP7_^G2Vc3hbvgrD<0B!FsqvbB?O$3d$M3 zOgZ}Pv9`yLuKy*~jm=~~sHvp{1FO@s$gW*GMzT(>Y-zK z7A?86wl{D%C9!s%%sudU)U|1P_AMJX#C|CsM}0SQh3Q@%%~rhC9TxiDvVjNOUNl0) z4F}n;;x{QrzB}GlLyb-xS@%+g+)|@+S63y^{(Gb68T114`RMvrY@H%WpqZcWX zZ4ybu4;Ab_d@=`dxPN_D)<}<$V-Jlhny+W?u<><+9Du}+O|;bLh{gTMS=i1QKs0VV z$5*R6gKh$Mr8x0xg%bxG%n5vG>?_*iV3L|NSoDMii7O5@&v4Z5o zr}EI2g1MO3a5jv+70H@{*XYAz3+L%sTW}H}C>`Q+E*nd;DJsVizSzW>`3o^SO|3h9 zS|jqVi#%wjG=*2;0(dO_1p%e4JOQ?T_%X%Jn{!py(jD)_>E#Gg!OfnNl%TlTUH$iE zB62wiTzwL+<3Cln?a+}7?E@v2qWId~^-;RjiH9c_Epc`SORab~#b&ybN0akj<7YFE zr~D`U|B9#ZQuIjr(e5I22Bvyps(;yUPYXv7^JU${^YFMV8H%le>9Pt%QD?%XOtnST_iSO;(}>_O{**!y~5 zhV#K5&_cdkE0yJfT)H-J^rM(to$^3ejntclkWFqqQ$LFIW&=|h+NZ2VCL4)AEfP9$ zrV5Otys)zhM*y{AEkI(Z+;LybAu`dg%T@I$YOY6Q4a zMD;N4(0DLaugScLeV*BL7mVdOLO&ao?WDwh&ez9&6v$zKJJdrC1Ki;kC+MR(sZ%FX zbGueUlIC^H1QbbVBTl$Gw|MR}ubVHlXFFf@Tix&i#(h2=HeWW=`v~KAs_chIqm71CY8YrO5lMez(!fEUlbD|A zJdPF?-8@P@H%zv!)9u0b#Hlsc_tAo2cppG?k3z+x!@3dVk%$>0>a6$R*J>(*Ig$~w0|To z2SzO|muGO`$^hQ0HmI(zAT{pHHn3BYM5ow>Cu)~O1t=?c3=N4i<>%E$mIo?tK0_>n z$~E~3GHRa86|{)A(TsU1=K-gz0#K=Uq(^iI@K-8&SB#Vz1K6_ycDS1VXtTN#0zEXp z8jcbw0xUEXkz_vBe~z$Sq90`o7t3AG`O(`W$o-?8=%^g}OW zmERJ1Tp7<)Jj`r6$e*rkGnMYNtGH|$`KnpaSKWs8(sp7+!qdCmFLBVzN;P7td6x^W z=F>Bc^HqBb=s(e%pT-hvm3 zBx@3p{xTZJv~{Mga@~zz%K!L=BUcV(OINV~j$Bz-x^|t-jWxp|DQ!mqA#IUgs-*3R z6Uz%(JQ`0YSf!gvsKEQc_Ux1SrfeDt^YD$5<<>LS+q`mEbEX23=o4ZbMfJ7X!wm9H zHTNkROM}FUjOj^qqMGg2|z^-k3KM)tiso;f`6&@;Ao&l_>n+HEeoC|YTd z%Cg?}OX=@lXSP|2!)M7V76?lg?ap~`dDs)9S%tkAPgNzCE@$qc;jH6@{TI(&qQ2?i zr}!(&cK9}s4!7+e9f$YsE}|XsIIFbHAcv~u#`IjQzBGUA_@VQ>eUg$-oJ!w=wVH{w zsy=Hi_dd(l%6pW*p?VZg<#={{JX_UQhk;11u3BG1Il|@Awcp#^G><-5BKH$Zq`xR$ zevqKnJbF*sFhKsBjkF8Fx;P{UneJrnGNoscLGltTJZAZq)L2ZQ_&BR{71g|I&Bg)< zrv;X8?x;~o^RRr$XU}Hr#qurV%v`Lh^1j4ev3x^)d}@X%%eRp)U)8!AW%(eRp`d|oM`a)n?fC@c=Zzhk zG#BLeo;sD04Dt&&`3n^l-WL?|!~OhfhAZUvVr_g?mC(`hKflRrvk+_Z-s|ea>34C^ zzX9?8HfUU}wEUyaa%6~;{rGZwd${iK(n#PhGhpLItn{EO9a4!GU}#jwQf*d2hZ1%q@7&rAwu|3Hd&y3x>Mk7l#JV zXKs3Yk3QiI92$@6)sq^J!bv%dnw-6Nmo+)7#9>17atq?J@c=v}r&alt(vr%nH&KAV zi=g(}hl)jKCdb8(o-}aasH0igXO9%QvCU58WXr$*AixZFqnRP1dk^anYUV~Cju)4) z&TQ;z_EuY@&*P*!XI%3`KA>ky)O@rob^f}7pK||jKHE!V!MJ?bm|}ZjD9ST7bL`oc z=7(7aj2ED-S*`9~wUv}zEibkpF3KTH`qER#(Q|mQlpl(n#P&iZuAG`TX584h{RfQQ zd-C+D8!M|wuwqgv$qiCnk?GKmTG+#DKWzR(lHn7j_&akhtOD|o`EW5NL`)oRON(Tc6 zEOQhFY&<+l@7Yg#Am?TaXW^+hlsu;tOKU^rp5TCPfrEt;CyreR4t5vINdpKE!+MY2j14K18)^y z?~@0Mr8xN$<)=6XD^^Nd`^lTxD0|CblvYwZ<4I~9pS913%d2k|=e2CE^t(VZU%)ZN z()mz%C>MNv4-PTJJ#@`dCj^jZkqEe_p;waDS@?<6I4M_qUQY9(qq~vKUPUw z0eK@Amq^7p7mav@euEk(WbVy7lSw@?z~Vv6Y_KT3h11$|bg{HQR1W8|Be1w&{P?j8 zz~b%`Cr<7Li_O+*q-^Uhl#y zGEU;)ea9$o7IWt;0FPy7=$Cbg4Xf~E>a@s3ny;fj_lE$nvbF}-0D61 z;67`9j*Y?TvZ>&@nLf*J%yFNZS)Y|s8(1-q?Bm6%oNH?@T5Wfx#emFHw{>km9F!1{@04XoHL}~ z0VPcxO*l!AJ2DAx|8JF16YE_E$%pWM@PZZ>hj&T;gtYAJ%(QYhwgHCIP2+?MGkEAH=A#zgK`@+WlDDT zl*eqml1ZJ9lXNQlgq9`CtXbAuC8V*!(Y0^mAey08m8VV~j0>?Q1CM!$Q@p(KM2g2f z%zld#X>S@IJ@znCGo43Nm##OXF!4p~plHS7l&vp=fux{T4`)kOvmkCDU9VZY{-zs7 zk7v0eB^uZ-_U7CjtI4*ZQTc@|yoB;wX{BYK^=>h_qkx0I4Q#6oRD!?pQcp-^*2obF zGyQxM51v1#n35~Fp$2RV&rIb-4k!{e3DkyLVUhBBu?CUdsj~hd7y8fTe|&oh$JcPS zXblVH%5vGZ29|A4TFT=i-bQ-E1gmi@czCPq^Rgq>J7v@cMp~2(i}Ai#o;fu>Az`Y& zf5PF+tjxn$j6Xp7R^Gh_eU)c*kC^T~Z$^VO+2w`2)Lb42LuR0gWz&d;#mT_p3|AJ1 zKTTXIU%MWHe4DwjqiP;psG*~B8x@x4Cffp*9_C)z{>+$|0Y@%TVQPitq_ql6al!PR z1g<{hmg~@@#OY9x)bvZ4so?4dt|HlYZ+qk@DiYhL*DY?jE@tboFzv7~wx7#>ch)@4 z{wAZ@QZ|e)PB0h7^(u~bF112mRk`0osUP3({T?Xq+2>nI)l^E2_HDsQ$* zn_(FxW>w`EG|23x^|mdBv#0rNg+qVZAzB;>JQmHTD=IP|zQn11Tzqc$0WLy4M2K&J zUr5m-7yNQ5^6x5=)Vu3OvJ^#~ssXT1B|^#Cb!Be!TVF9?x(W_|J3r=!C+rw%hbVE@ zc|?i((wp(rc6oA68|Jr#=_;rx%$^*I%%vu#!dGi++iiWu`3$pq>g?O>xuQX~fYT_z z_g6Sp*)PDc$~I+{+tjZzEW~>{n@Ghy*Ex#kde}+}t$Pvi0i=Nv@^RPkkk4xoVz&TYecUJ6 zNmI8%3H(qaYV>;O2S39aIYK|wgrPQQA*pB~`RGiw=OSqiQ?Zsj5VXijhnR{~iq+ES zdKmo}Va_+vawQxTVtryIFYB&K&Bh8xKuC9U(x5>ellZ**A`R}=Q9keENQ7{E4^aX_Zx10nz+2C=_t+{C&2j9_%`&ngBdJ!5po7vQfxP(trZfbFYD^ap6gq67 zNtVMrU|d)5Dp(S)1aPu=uwS<9?4S_(Tu^RD#?}f+gOAP-4!}D-(D^~p~HWCK^ zpBA-eE$U+hbwFEiDdk(6B`eO=NN{QN9pAG>#hdDes6yDLY9`vdAh-GM(1l(YyZ>hPjJ zYs4D2AAs%I-u?0;-AlAGb(4F@$=w+fBkX6*>e^|{%SWe?v4@vg>6lUjy4_T6 zdX^#7A;+q+SohAD(*6oan7c8iu?Xwvc^@ zUHb>#j#xb1tP2wyyR_Jpja@1wDLXVA6h3N!D zh0Q*pCfAI${}jUG{o~8*W}n25T*VrZlC1I68`+ z8Y5J-VNwtzfb*o{lj@!dWt&Z>3`*8}TZTI0Anf0*uO9CJB9XEJOaDP_7q2 z3o(-8O~})9IhQ8aC+bS^)&Y*ePKx$a!T!DA7UM)i1r3zs5&(4SABVcj@ekC@7Y!a+ zGdW(xVx*3cB^8;j;0DQaurjpveexU4_WqujHl*K7Ewj(xyU>%~iX*q>dk}H%zKOk4wCtg?JeuZUx;$N2G#PV| zzxGN1F3OG=OU@UuBb+a?v5wbCS=Y0# z8%;ShLZRE=B8@3`*ELL!mkZ2Prgtz~DI;)WzbLzqKeq|#j$O!~;gnt25zT+)Zld%{ zmi)_gX;-!^v3vF=xxD#Gv}CCB=6fK-RLNCmhN8D9l^kO^qeyd^h&_WyJzw&im-Z`y zyD|f}?mTm43=3gnRJ4~uL~3WM1#nb5e9|e>-p+)+%Cb#r4GH#7r?=A&=aJfUA)5we z^Vv)Rd<%lw77Ojzp&W_En$hy7+N;*~h-*M(&RQFRSEwySoi? zx@}JK4~R(Y(|1UQtvo;dmK*(t+KF|o0fL~eomiVBzLv$*Y(5*syHNPIRqg{bw!z1_ zj?^NWqGT44eHZWk;icpjB}%zsWzP6PLt@7vujpicVb+Oi<$=%j*5wz}sNrdXHEMrr z0Dqe}K2coE5_wF~(E-ty<|5sE1b_4+mc`Mr*&qL=6kRjsW>RE^Bc+IDI}(aKb@ll~ z=Rv)Th+LwfLlb6udM50@bSd)yFrB}4B7IHzty^B{Opg?zq`rL--_*O&(b?i67O#Z+ z8`6l-eQ`KX4wU6SuVoR{ZdS60KGs#Ersq`>5lwd_^x%bOJbfy{fV0slwdP_t(t()2 z97_IbO$drV?43mUkX1UQuAL&U7Rd)x_Typb+l*$5Sd!yCgijZloz7a`|PHKy6$^t^x$6*Ru8fVmnZCxOTD_gJMp zYI)fR(E;1aTD=0rZsmY;bsOviT+CPalN?9e%>mg;=Zi2{hLwUboV96PxKP{Cs;Yep zXa!ZKoT?gAtdCb@td~z@PK|dBqF)FaGAsp6KDH)dDd6(Yk zZpDf=lmY{TpM(8t9&BdEI0pYbn#!Yl*3Gf9DBvCY`wfrWzRGF#u_vm_RBbg6*3(Y} zUuY`JR^fLnl7MM9g z^BliVGg(?JP4{9`RhogD+531jcFtS-msLTN7?`xOSKAB;z}#wgpQwu^CB}=G$FLAL z{3yUKz4iEyX9>X%}D2_6f#mCY_ZS^AT80?M}L*mv^<8I5zQ>H6BY zXff7AGi?&PfWFf-8k0zlrEy-kZ3~{;%JU3u^d2mcGj_-!ucB7Ee3NRL3EDzy4YVOyC2=W8IKgjwDZT9u1BBXhR z>Z)OyS7@^uz2^BUwi_O%iixa!Pv!$aHdJcuAeVyk&t1=Vq!xpy?c#l~gM4-|xBK)C z2V|?45WQ9UqRb3vS_3;uq{XZY>f%1Y>|mxuV&AlIyuAwXxR$Z4pM?eBDF&G z+*sA1NuItV6pa2-^n4ww_T>-@Q_&_L82vfu;k+~aLR94yj>k5~cs-vEa=HhRCctMM zY*kjqLnkL&rDUuIJ1d_Se-ffV&W3nN05H{9JO9IGbNOK&r-+f#A!a`|-myw=W0e3` z?^qxjUV!E)dzEQrRrvGa4L3C}aVjhnAk-f@9>I+p3LZg{rzcjT9xAt75vsoe{Nb+% zm4gav?DUJ=Oe~OXgXw$q7d@CJfOTKCrxu-7&)z)eLCs^R_3}MAFfO++(e}lCXO3z) z(NvL7`xFigmYlLvmIDf={|fu=+KED~3w;9~IIuE!aOl>*JOJ2O;h`mX;Oe6QvUgw% zMiiS^cSE3w8+GJjlJ7=ROE!^*qvcSYgvy2qXrs8(LYYdto5%NsX#J_E$LEkVo<^-* z(^!l04v$8kG__&xW_KoU>ZnCyzJ1=J<}vF=wT8NPu$@(!+tdv)tY8zR=D##yI4k8T z9d0D4NP1_k?zk^CmC6M6jwdgB8K*xQ_56^fH1(0|p}xiaAI)->o3dWD*xS$Tlj#L- z5$MXBa;I47i`t8bl1sDlNkosSq1Lq+7&R`>r6RUk=>f$L=rY{=iM#G(Y z3?35}S}^AR{esiQ*9V{O;ihRBewc#Apdh)GpmBD;N0LYr4DtvoML1f*P`n8T!3}$~ z02%$KkyI$Pg)IQw=3~Buj;X>p{gJ2_hb$$jk6jOW77u(d6HNvivENx+>7c-Weu;FK z-)HilRszI?w1T%qh{}DIeJhu~%`btZqRM`=Q64TM^uo9z#nufFSnCw8`!BWI>ZS@y z)J*8pfwe^+JCrHyFTa|4&-Ji>X~eVn&Vf3%hwbF0XY*up%s)Em)4nJ?`#`#%3&e4Z z^|4(LX@o(ZY^AY$D$%dHzo2mMx``*;=Gc~(Uaar@a%>T(4+N}M3Tu7X>po(^8)>vj zUKUB?KTtE5zU`TIvOX0_+6QdcQt!JS_AQNg3aOW|9iry_Md$)^aMu5Jfe|qz?UNdl zl293IgcR@c=3`|)VYDDL#zR3~q(VWUdLG3C9?y1$ z^w=h*=b+@V^`PV!BZ~?EN)DmhW9R|@1RA+i>9n+hfBF$$L#MxV^n1Pq8NZx>ie8j+C88?U(Me3U`?5JqW*9sHA=M{&AK$!uqGWi@CDwnFYo zPEuFitgEX^a|SMXAbTd|&@<#0tWa99l!+J|Tue2{E37pCBc1d^J~^5BUbEJHAvkuL zh)MepGLN)-X^dH37D40r)V;9l+9^84r~btCaNpvAk7qf5GF%K?#sS9L_u_y%aPYO; zsfGC>KsY;73#jUneR&E9r`ui9@Fp$gB7JX=5f4sdI|XTP!3~h#T-wh@-<5s-`{&Ar zuew3m;!8!shdr+kcrxpdv5n@6qS%c{P{c7$;Yh_fvcJ(8eLjQ6*S;g1K(lXe-kb$( zqNSvRtZZ!C?zkqjKkTrvCN2x4xGXJ zvTWp-IZkmMJCGC4F^{5V+0UP`X4xne!`PHcH#tIyoNA@jYMyBAIzWfO1MMrQwnt(` zK)fSX6=`48$z-yNqr5&QVL_9)^}a+gRl zOjI*f6mw$282!=cnnO94ldD|!gk{87XF0Q#9MeLUHn6Xj>a3I@KT;tFr&?qySTkA_ zDsL#J&!`#usuV61EO}`r8lZsUGV74ix_AKzdv(%#B7UH})b1P1cH)OfqhrAq|#HiaxazvJq`lB&bhjOncSGp#LW<=TMI3qyWiS4U>7Z7xJvdfLM z#tiTjp}P(Q&T;}%OQl7@Yyt?xgvuj8;BC}_vT)Y)aMUgPXrUvp-_({#v+K>?H1tZ6hC-)Q~un99`b%gGg7e6iL!&Iki`W1Tp5OB}FUFhnI4 zI-pzfIBse)fV#^oifIuh@Nud14=mC+fkNq5<*Zq3jZ&yLiU`!95mrCRP=1S21vW$AM!RRdv`EKL#JzXkQ2eS|G8#6=YReS+0VLFE(jyEte zK@mhVCX7-9k#l7amM<(l){1>__Ze{Yo(3$WZ-hs#7rN5hgGu`y%GS`t&ubg&d>^~k zMcQe;Y2vgOlv2OqwH&JDF6i$R9pc%9W-p*W4f!*ienkWQw0i9cm;(9`#1$_8(2O`v z_8P4lC8|H#k7%!Q31+K!}YAn8~p*|5UIs6A&14U}HXI$lClZ zALf_&UjuBJM!GM==+8z!JX=NT!}N~p5g1?{ACEp>Z-Dtw2QAE>UCYIMT>Pvf&YwDs zmC98(Q#$6Wl#eDjOtB>1TjjTZt+81e3+@PUt`0U+V_0Ji_X4)}^Hf-4kJAV zK#c*#@$Z6eLcq01hp8q89njU=Y6Jg&u+`lEwbh)Q>3!*KrDH=&NB5KAR>p8JLl2Y(^+wRWe~lm- zZI<7QpmG1FC4^;vWeMF6|359E2d^xl=PT@y$g(u^d(P3vW4qGF!^S??a2?N7b1hM`wqxlr9!bOh|GST$u8_Q_mNWRQ5kp9r zU(2&~n!77VM18-GiJU$9$NYuveElU_Ld_2fF}E+)U!v|gzPLo;k7>+~OO(>t_ae;P z=4`B5LdMejtT{~ysl8f4C-K=$ew`}&08L-aTVK207+P&yN8%F>j4o=PLe-4TS1!7N z_{68-qU(qD()AZzZo@?vU4PMy!j`N$oO=ytcXCKZv<+)hhKp|RzZabsv~ZR5IX3EM zG~sX&JF#X@)hvY5dPBMMTv)T`|6X}7HnXOOqHg2L>k!f9)s<)FSKdHed2?}*ZpNLb zR_;8_%kz#)PwH=8tZPjBt@H>1>i^n%i8RS9e;Pp(JF1wsI}2s+#K2d4asfxxA!-9( zv1O(Eqfw{xa8%`VAb;wvrAMddJ3h`^uf{L>TnjVR=9MB`xN(kG}DN(B6Cc~?p~Ju0jY{)K8pK9hrKtusPR-tB2_o+J zchbC{QX~6U0(0&IL!k8peOmPMgVs`bTZg<$20fn3y{(l95j>E-qPg<5Xq5WBhGMJq zUC87pw)CC31~mOkQ*A$&UZ~w5aKGxh1Pwa&m}!o9J$=cEs1+jP8;IO@5SfF6k!|GO z6iuV4_Im^uCst(BAdbnMPNcmh@Y>nKWTR7KZZD` zmwnB}8B_+7u~hL{U&(J@gZySge%3=zU&+r78aPyfSgZpE7Qb4CGo?%=t&~i>|H7al zp!JDO+5%b#ccaK;0FrL*gWP<}#~|nMt3a=Zs3~1hPf)Gh+CcCD-mK^2u&q4x8DEKh%1TUN6#xfKH5#pls4ca%BJag8otM*Yb>Mcl zZ%^ttN5_He7cZDPTj@72%tX7*53n2utdAYd1~kvX%>#v-_kp*I&M%ys$*-ict3fIY z8g}tm#mKPQ6unTE25?V*GxyrFf`=dhTcZcY|DyC3Ee|PqQmVO61$H-)e9Ut12nr2U zF~cC{&)yE#pNXrvWPF}XZ@DHjRZh>Uk!O(I(XudtJjg>!Uk?_sUAsl7FhDnXa*4et zL`4ys>#_xI4;|y}a&huMKV4aJOF`(Df}|SEqAgolB5e#|Gu2USR+#Qo%!`NGGt|c{ zcZeXvC<+#$tT=U6vF-{W|91)?e+~!aN8T;k4IWnxoG%rP<#)h~(-kFmOEpv{0x7># zCBG|$f{2z?m)PG3VIQia*;G;Uh&i2%e*Q>%j{2JAj-WI0xllgKSwpxtj)^p%_m`vg zI)2<+jr6^#41+JS#FoB1Sy^%$rhk-H_T&!x=RFW!qf-@#8ju|T;5}I-5Z`6RgSx*mY@Ai#5;IBn+9~tH26FQ zhtD&_NQdivo>&$s+~J6pc6TXQdZ-j$ZN{utlt@2@uqkjAXN2iaa?zb=AUXcIV8fK8 z^QxTds+-NlZd#NC|Qr?8q%CpcW3)05!hSQ6mk0ES=MV7{&B z!i!U5VKN2Te&j1w%|-ec*_L;(W-3ng8Hg?}k=BK(#`>Sg|MiL^e1O@|z2hJmG*58-X~G07cZLU3;@ zs#-Tfe=N58P{I} zcX2n*lCMRnBXBqS;%;8d@8-Hq0wv{_nNkW`(FDt9>=z-Z450#()Qaf@_AP5IN`Wj| z4paq3iuk;Y%#QmmUu3ukYuyA#&wpHX{mIu{VmjJz*$w%Jy7T+ab{_X#2N5rU?A>GD z)C5|R!l%9jhw2O*@gA%hkE1JxD&pwy+;G)dMU8DUt~#f>rGn<{d1?~KUf`B{q1K#5 zJ7)0J4GhqsONFU!1aYkH#*9SbtQU8c~PY{E~%Ylw4Uxd9% zK=);Nwh&u2H!V|lIP%VIWfM%urGBPzaH8CN%6fIkUqb8P^;3tK8R(OIX*L>p%CJ8*;2 z1vMVdg({w6@kf;f=R%dmVsQsv$7iUlawRG9uu zY)!iHSu(jO*Hn+H5ofY-O%+9uCwXe=o1b8jv)0%aj9N1%75^f_@x`-ZdlBlJhVVNp zEnmtpw~~A-0<4+>($Gnf+U`awS30#!XKzslZ_+K=XKJIVU>@697`;Uu5nVrHt__Ny zGl;Htgnj-t>$_O5DUf=z^~#+xUv5(S9|0%?HD+vWnuXzeyy(Si%MlY1r3oT+-9WCU zGY`*nBW)yg{cty8F{R9F1M5`!?c>@?;ai|`1~ZQjosYp;kPfotRytnWScTt~2yv*R z)YhPe``;EAkzIIs!|$LoPf17g#OVT3h$6U3A@g)wsLkcm&rWxwHUp^hvSdud!n`-L z&NYate9uM;tJJuxI(sqi<$6L>UlBMp$U($!|3Rgq<|K6ool@2v;IJJ8VDx2MbFP>o zVK^otDX(`Kg;S$mye=8O47o@vMC$n$>9bDVJKd9X@zmp!9XV|{x=5ctSf|1-ZaP!4 zv9?zfC9A#wGWHdC;$-A2+WQE6oK4aI1SikKAy?x|*0?TJ0cWkrC<8bv zr#?`j-o6+KjLWG}PwU4;)U`-+1kjQaQqOw)t#EM4!NJEUWY!$n&iekrIw~COG1m5o zqCK30P7V%SWY`JIjIi6sax~Q$L2MeEPWk9wV5A!Q0BglQWL^2A2pv&zGEdnNwdTk# zf0LW2Is6Nv7yK*M#DNIvZM+Q@htjONJ_7aQiyl{&prd!BnHcCF(wfdZIMbakdbf{u z8{3T3G0%Tkr|Y#%1=cZ)d41$eZRKVhCc~SCd zN4>G;i8L8&-WLhb%0djb;HO(j3q|S-&kbR3h&a zjg{F(#1b8E4#KcC^R7IJ4mSeYU$FwHWTtSn< zJpX2$iobpc)&05~>m0^BK62LVMucMr9TdnV_dH>3x34C&ewjwCA+YVNHFUQn2cd}0 zy^4WH(oD>xr;Wmujbc+|Hi^s3eobf))!(m)>SJe;d2_E0hJBeC)_v50qg*8_2v=^j zS^=pT)~ze4haoNc;-iNSY^wxa8o6U$qB1WLvZNSO1q2z7Ct=4X)m#DL*$s>Ljpko7lTW%N{vvu6#qlK}(|+ zm@%48%8hED2oz|fH!G<~fS9w9S@Be%E^!d!$-d%o2 zH1e^3Lr3`{gCF}Xihfc#va`E>v?~tT*)sCkJN(1M%gZXASJHY>bBJ65)S4pZ!s;UJ z=S*ss;7jyY#<5�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 diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index ca7e5ef815..2ec7e66234 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -8,44 +8,44 @@ //! directly written to a `Write` handle. /// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page. -crate static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css"); +crate static RUSTDOC_CSS: &str = include_str!("static/css/rustdoc.css"); /// The file contents of `settings.css`, responsible for the items on the settings page. -crate static SETTINGS_CSS: &str = include_str!("static/settings.css"); +crate static SETTINGS_CSS: &str = include_str!("static/css/settings.css"); /// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled. -crate static NOSCRIPT_CSS: &str = include_str!("static/noscript.css"); +crate static NOSCRIPT_CSS: &str = include_str!("static/css/noscript.css"); /// The file contents of `normalize.css`, included to even out standard elements between browser /// implementations. -crate static NORMALIZE_CSS: &str = include_str!("static/normalize.css"); +crate static NORMALIZE_CSS: &str = include_str!("static/css/normalize.css"); /// The file contents of `main.js`, which contains the core JavaScript used on documentation pages, /// including search behavior and docblock folding, among others. -crate static MAIN_JS: &str = include_str!("static/main.js"); +crate static MAIN_JS: &str = include_str!("static/js/main.js"); /// The file contents of `search.js`, which contains the search behavior. -crate static SEARCH_JS: &str = include_str!("static/search.js"); +crate static SEARCH_JS: &str = include_str!("static/js/search.js"); /// The file contents of `settings.js`, which contains the JavaScript used to handle the settings /// page. -crate static SETTINGS_JS: &str = include_str!("static/settings.js"); +crate static SETTINGS_JS: &str = include_str!("static/js/settings.js"); /// The file contents of `storage.js`, which contains functionality related to browser Local /// Storage, used to store documentation settings. -crate static STORAGE_JS: &str = include_str!("static/storage.js"); +crate static STORAGE_JS: &str = include_str!("static/js/storage.js"); /// The file contents of `brush.svg`, the icon used for the theme-switch button. -crate static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg"); +crate static BRUSH_SVG: &[u8] = include_bytes!("static/images/brush.svg"); /// The file contents of `wheel.svg`, the icon used for the settings button. -crate static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg"); +crate static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg"); /// The file contents of `clipboard.svg`, the icon used for the "copy path" button. -crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/clipboard.svg"); +crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg"); /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox. -crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg"); +crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg"); /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation /// output. @@ -58,87 +58,114 @@ crate static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt") crate static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt"); /// The contents of `rust-logo.png`, the default icon of the documentation. -crate static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png"); +crate static RUST_LOGO: &[u8] = include_bytes!("static/images/rust-logo.png"); /// The default documentation favicons (SVG and PNG fallbacks) -crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/favicon.svg"); -crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/favicon-16x16.png"); -crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/favicon-32x32.png"); +crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg"); +crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png"); +crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png"); + +crate static PAGE: &str = include_str!("templates/page.html"); /// The built-in themes given to every documentation site. crate mod themes { /// The "light" theme, selected by default when no setting is available. Used as the basis for /// the `--check-theme` functionality. - crate static LIGHT: &str = include_str!("static/themes/light.css"); + crate static LIGHT: &str = include_str!("static/css/themes/light.css"); /// The "dark" theme. - crate static DARK: &str = include_str!("static/themes/dark.css"); + crate static DARK: &str = include_str!("static/css/themes/dark.css"); /// The "ayu" theme. - crate static AYU: &str = include_str!("static/themes/ayu.css"); + crate static AYU: &str = include_str!("static/css/themes/ayu.css"); } /// Files related to the Fira Sans font. crate mod fira_sans { /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font. - crate static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff"); + crate static REGULAR: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff"); /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2. - crate static REGULAR2: &[u8] = include_bytes!("static/FiraSans-Regular.woff2"); + crate static REGULAR2: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff2"); /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font. - crate static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff"); + crate static MEDIUM: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff"); /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2. - crate static MEDIUM2: &[u8] = include_bytes!("static/FiraSans-Medium.woff2"); + crate static MEDIUM2: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff2"); /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font. - crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt"); + crate static LICENSE: &[u8] = include_bytes!("static/fonts/FiraSans-LICENSE.txt"); } /// Files related to the Source Serif 4 font. crate mod source_serif_4 { /// The file `SourceSerif4-Regular.ttf.woff`, the Regular variant of the Source Serif 4 font. - crate static REGULAR: &[u8] = include_bytes!("static/SourceSerif4-Regular.ttf.woff"); + crate static REGULAR: &[u8] = include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff"); + + /// The file `SourceSerif4-Regular.ttf.woff2`, the Regular variant of the Source Serif 4 font in + /// woff2. + crate static REGULAR2: &[u8] = include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff2"); /// The file `SourceSerif4-Bold.ttf.woff`, the Bold variant of the Source Serif 4 font. - crate static BOLD: &[u8] = include_bytes!("static/SourceSerif4-Bold.ttf.woff"); + crate static BOLD: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff"); + + /// The file `SourceSerif4-Bold.ttf.woff2`, the Bold variant of the Source Serif 4 font in + /// woff2. + crate static BOLD2: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff2"); /// The file `SourceSerif4-It.ttf.woff`, the Italic variant of the Source Serif 4 font. - crate static ITALIC: &[u8] = include_bytes!("static/SourceSerif4-It.ttf.woff"); + crate static ITALIC: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff"); + + /// The file `SourceSerif4-It.ttf.woff2`, the Italic variant of the Source Serif 4 font in + /// woff2. + crate static ITALIC2: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff2"); /// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font. - crate static LICENSE: &[u8] = include_bytes!("static/SourceSerif4-LICENSE.md"); + crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceSerif4-LICENSE.md"); } /// Files related to the Source Code Pro font. crate mod source_code_pro { /// The file `SourceCodePro-Regular.ttf.woff`, the Regular variant of the Source Code Pro font. - crate static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.ttf.woff"); + crate static REGULAR: &[u8] = include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff"); + + /// The file `SourceCodePro-Regular.ttf.woff2`, the Regular variant of the Source Code Pro font + /// in woff2. + crate static REGULAR2: &[u8] = include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff2"); /// The file `SourceCodePro-Semibold.ttf.woff`, the Semibold variant of the Source Code Pro /// font. - crate static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.ttf.woff"); + crate static SEMIBOLD: &[u8] = include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff"); + + /// The file `SourceCodePro-Semibold.ttf.woff2`, the Semibold variant of the Source Code Pro + /// font in woff2. + crate static SEMIBOLD2: &[u8] = include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff2"); /// The file `SourceCodePro-It.ttf.woff`, the Italic variant of the Source Code Pro font. - crate static ITALIC: &[u8] = include_bytes!("static/SourceCodePro-It.ttf.woff"); + crate static ITALIC: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff"); + + /// The file `SourceCodePro-It.ttf.woff2`, the Italic variant of the Source Code Pro font in + /// woff2. + crate static ITALIC2: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff2"); /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font. - crate static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt"); + crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt"); } crate mod noto_sans_kr { /// The file `noto-sans-kr-v13-korean-regular.woff`, the Regular variant of the Noto Sans KR /// font. - crate static REGULAR: &[u8] = include_bytes!("static/noto-sans-kr-v13-korean-regular.woff"); + crate static REGULAR: &[u8] = + include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular.woff"); /// The file `noto-sans-kr-v13-korean-regular-LICENSE.txt`, the license text of the Noto Sans KR /// font. crate static LICENSE: &[u8] = - include_bytes!("static/noto-sans-kr-v13-korean-regular-LICENSE.txt"); + include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular-LICENSE.txt"); } /// Files related to the sidebar in rustdoc sources. crate mod sidebar { /// File script to handle sidebar. - crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js"); + crate static SOURCE_SCRIPT: &str = include_str!("static/js/source-script.js"); } diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md new file mode 100644 index 0000000000..fff65e3b5f --- /dev/null +++ b/src/librustdoc/html/templates/STYLE.md @@ -0,0 +1,37 @@ +# Style for Templates + +This directory has templates in the [Tera templating language](teradoc), which is very +similar to [Jinja2](jinjadoc) and [Django](djangodoc) templates, and also to [Askama](askamadoc). + +[teradoc]: https://tera.netlify.app/docs/#templates +[jinjadoc]: https://jinja.palletsprojects.com/en/3.0.x/templates/ +[djangodoc]: https://docs.djangoproject.com/en/3.2/topics/templates/ +[askamadoc]: https://docs.rs/askama/0.10.5/askama/ + +We want our rendered output to have as little unnecessary whitespace as +possible, so that pages load quickly. To achieve that we use Tera's +[whitespace control] features. At the end of most lines, we put an empty comment +tag with the whitespace control characters: `{#- -#}`. This causes all +whitespace between the end of the line and the beginning of the next, including +indentation, to be omitted on render. Sometimes we want to preserve a single +space. In those cases we put the space at the end of the line, followed by +`{# -#}`, which is a directive to remove following whitespace but not preceding. +We also use the whitespace control characters in most instances of tags with +control flow, for example `{%- if foo -%}`. + +[whitespace control]: https://tera.netlify.app/docs/#whitespace-control + +We want our templates to be readable, so we use indentation and newlines +liberally. We indent by four spaces after opening an HTML tag _or_ a Tera +tag. In most cases an HTML tag should be followed by a newline, but if the +tag has simple contents and fits with its close tag on a single line, the +contents don't necessarily need a new line. + +Tera templates support quite sophisticated control flow. To keep our templates +simple and understandable, we use only a subset: `if` and `for`. In particular +we avoid [assignments in the template logic](assignments) and [Tera +macros](macros). This also may make things easier if we switch to a different +Jinja-style template system, like Askama, in the future. + +[assignments]: https://tera.netlify.app/docs/#assignments +[macros]: https://tera.netlify.app/docs/#macros diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html new file mode 100644 index 0000000000..9b1bef5e44 --- /dev/null +++ b/src/librustdoc/html/templates/page.html @@ -0,0 +1,119 @@ + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {{page.title}} {#- -#} + {#- -#} + {#- -#} + {{- style_files | safe -}} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {%- if layout.css_file_extension -%} + {#- -#} + {%- endif -%} + {%- if layout.favicon -%} + {#- -#} + {%- else -%} + {#- -#} + {#- -#} + {#- -#} + {%- endif -%} + {{- layout.external_html.in_header | safe -}} + {#- -#} + {#- -#} + {#- -#} + {#- -#} + {{- layout.external_html.before_content | safe -}} + {#- -#} +
{#- -#} + {#- -#} + {#- -#} +
{#- -#} + {#- -#} +
{{- content | safe -}}
{#- -#} + {#- -#} + {{- layout.external_html.after_content | safe -}} +
{#- -#} +
+ {#- -#} + {%- for script in page.static_extra_scripts -%} + {#- -#} + {% endfor %} + {%- for script in page.extra_scripts -%} + {#- -#} + {% endfor %} + {#- -#} + {#- -#} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 7086dd8c4d..bf8db79416 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -5,9 +5,10 @@ #![allow(rustc::default_hash_types)] use std::convert::From; +use std::fmt; use rustc_ast::ast; -use rustc_hir::def::CtorKind; +use rustc_hir::{def::CtorKind, def_id::DefId}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_span::Pos; @@ -15,7 +16,7 @@ use rustc_span::Pos; use rustdoc_json_types::*; use crate::clean::utils::print_const_expr; -use crate::clean::{self, FakeDefId}; +use crate::clean::{self, ItemId}; use crate::formats::item_type::ItemType; use crate::json::JsonRenderer; use std::collections::HashSet; @@ -30,7 +31,7 @@ impl JsonRenderer<'_> { .into_iter() .flatten() .filter_map(|clean::ItemLink { link, did, .. }| { - did.map(|did| (link.clone(), from_def_id(did.into()))) + did.map(|did| (link.clone(), from_item_id(did.into()))) }) .collect(); let docs = item.attrs.collapsed_doc_value(); @@ -47,7 +48,7 @@ impl JsonRenderer<'_> { _ => from_clean_item(item, self.tcx), }; Some(Item { - id: from_def_id(def_id), + id: from_item_id(def_id), crate_id: def_id.krate().as_u32(), name: name.map(|sym| sym.to_string()), span: self.convert_span(span), @@ -86,7 +87,7 @@ impl JsonRenderer<'_> { Inherited => Visibility::Default, Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate, Restricted(did) => Visibility::Restricted { - parent: from_def_id(did.into()), + parent: from_item_id(did.into()), path: self.tcx.def_path(did).to_string_no_crate_verbose(), }, } @@ -170,12 +171,24 @@ impl FromWithTcx for TypeBindingKind { } } -crate fn from_def_id(did: FakeDefId) -> Id { +crate fn from_item_id(did: ItemId) -> Id { + struct DisplayDefId(DefId); + + impl fmt::Display for DisplayDefId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.0.krate.as_u32(), u32::from(self.0.index)) + } + } + match did { - FakeDefId::Real(did) => Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index))), - // We need to differentiate real and fake ids, because the indices might overlap for fake - // and real DefId's, which would cause two different Id's treated as they were the same. - FakeDefId::Fake(idx, krate) => Id(format!("F{}:{}", krate.as_u32(), u32::from(idx))), + ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))), + ItemId::Blanket { for_, impl_id } => { + Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_))) + } + ItemId::Auto { for_, trait_ } => { + Id(format!("a:{}-{}", DisplayDefId(trait_), DisplayDefId(for_))) + } + ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())), } } @@ -328,9 +341,10 @@ impl FromWithTcx for WherePredicate { fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self { use clean::WherePredicate::*; match predicate { - BoundPredicate { ty, bounds } => WherePredicate::BoundPredicate { + BoundPredicate { ty, bounds, .. } => WherePredicate::BoundPredicate { ty: ty.into_tcx(tcx), bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(), + // FIXME: add `bound_params` to rustdoc-json-params? }, RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate { lifetime: lifetime.0.to_string(), @@ -372,14 +386,35 @@ impl FromWithTcx for Type { fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { use clean::Type::*; match ty { - ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath { + ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath { name: path.whole_name(), - id: from_def_id(did.into()), + id: from_item_id(did.into()), args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), - param_names: param_names - .map(|v| v.into_iter().map(|x| x.into_tcx(tcx)).collect()) - .unwrap_or_default(), + param_names: Vec::new(), }, + DynTrait(mut bounds, lt) => { + let (path, id) = match bounds.remove(0).trait_ { + ResolvedPath { path, did, .. } => (path, did), + _ => unreachable!(), + }; + + Type::ResolvedPath { + name: path.whole_name(), + id: from_item_id(id.into()), + args: path + .segments + .last() + .map(|args| Box::new(args.clone().args.into_tcx(tcx))), + param_names: bounds + .into_iter() + .map(|t| { + clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None) + }) + .chain(lt.into_iter().map(|lt| clean::GenericBound::Outlives(lt))) + .map(|bound| bound.into_tcx(tcx)) + .collect(), + } + } Generic(s) => Type::Generic(s.to_string()), Primitive(p) => Type::Primitive(p.as_sym().to_string()), BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), @@ -546,13 +581,13 @@ impl FromWithTcx for Import { Simple(s) => Import { source: import.source.path.whole_name(), name: s.to_string(), - id: import.source.did.map(FakeDefId::from).map(from_def_id), + id: import.source.did.map(ItemId::from).map(from_item_id), glob: false, }, Glob => Import { source: import.source.path.whole_name(), name: import.source.path.last_name().to_string(), - id: import.source.did.map(FakeDefId::from).map(from_def_id), + id: import.source.did.map(ItemId::from).map(from_item_id), glob: true, }, } @@ -646,5 +681,5 @@ impl FromWithTcx for ItemKind { } fn ids(items: impl IntoIterator) -> Vec { - items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_def_id(i.def_id)).collect() + items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect() } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 0d84bf250c..8bdf1a5981 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -25,7 +25,7 @@ use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::FormatRenderer; use crate::html::render::cache::ExternalLocation; -use crate::json::conversions::{from_def_id, IntoWithTcx}; +use crate::json::conversions::{from_item_id, IntoWithTcx}; #[derive(Clone)] crate struct JsonRenderer<'tcx> { @@ -53,7 +53,7 @@ impl JsonRenderer<'tcx> { .map(|i| { let item = &i.impl_item; self.item(item.clone()).unwrap(); - from_def_id(item.def_id) + from_item_id(item.def_id) }) .collect() }) @@ -71,7 +71,7 @@ impl JsonRenderer<'tcx> { let item = &i.impl_item; if item.def_id.is_local() { self.item(item.clone()).unwrap(); - Some(from_def_id(item.def_id)) + Some(from_item_id(item.def_id)) } else { None } @@ -91,9 +91,9 @@ impl JsonRenderer<'tcx> { let trait_item = &trait_item.trait_; trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap()); Some(( - from_def_id(id.into()), + from_item_id(id.into()), types::Item { - id: from_def_id(id.into()), + id: from_item_id(id.into()), crate_id: id.krate.as_u32(), name: self .cache @@ -164,13 +164,13 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let id = item.def_id; if let Some(mut new_item) = self.convert_item(item) { if let types::ItemEnum::Trait(ref mut t) = new_item.inner { - t.implementors = self.get_trait_implementors(id.expect_real()) + t.implementors = self.get_trait_implementors(id.expect_def_id()) } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner { - s.impls = self.get_impls(id.expect_real()) + s.impls = self.get_impls(id.expect_def_id()) } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner { - e.impls = self.get_impls(id.expect_real()) + e.impls = self.get_impls(id.expect_def_id()) } - let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone()); + let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone()); // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check // to make sure the items are unique. The main place this happens is when an item, is @@ -207,7 +207,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { .chain(self.cache.external_paths.clone().into_iter()) .map(|(k, (path, kind))| { ( - from_def_id(k.into()), + from_item_id(k.into()), types::ItemSummary { crate_id: k.krate.as_u32(), path, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 64a9905b33..fa75577758 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -53,11 +53,11 @@ extern crate rustc_parse; extern crate rustc_passes; extern crate rustc_resolve; extern crate rustc_session; -extern crate rustc_span as rustc_span; +extern crate rustc_span; extern crate rustc_target; extern crate rustc_trait_selection; extern crate rustc_typeck; -extern crate test as testing; +extern crate test; #[cfg(feature = "jemalloc")] extern crate tikv_jemalloc_sys; @@ -269,9 +269,9 @@ fn opts() -> Vec { let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable; let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable; vec![ - stable("h", |o| o.optflag("h", "help", "show this help message")), - stable("V", |o| o.optflag("V", "version", "print rustdoc's version")), - stable("v", |o| o.optflag("v", "verbose", "use verbose output")), + stable("h", |o| o.optflagmulti("h", "help", "show this help message")), + stable("V", |o| o.optflagmulti("V", "version", "print rustdoc's version")), + stable("v", |o| o.optflagmulti("v", "verbose", "use verbose output")), stable("r", |o| { o.optopt("r", "input-format", "the input type of the specified file", "[rust]") }), @@ -309,14 +309,14 @@ fn opts() -> Vec { ) }), stable("plugins", |o| o.optmulti("", "plugins", "removed", "PLUGINS")), - stable("no-default", |o| o.optflag("", "no-defaults", "don't run the default passes")), + stable("no-default", |o| o.optflagmulti("", "no-defaults", "don't run the default passes")), stable("document-private-items", |o| { - o.optflag("", "document-private-items", "document private items") + o.optflagmulti("", "document-private-items", "document private items") }), unstable("document-hidden-items", |o| { - o.optflag("", "document-hidden-items", "document items that have doc(hidden)") + o.optflagmulti("", "document-hidden-items", "document items that have doc(hidden)") }), - stable("test", |o| o.optflag("", "test", "run code examples as tests")), + stable("test", |o| o.optflagmulti("", "test", "run code examples as tests")), stable("test-args", |o| { o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS") }), @@ -386,7 +386,7 @@ fn opts() -> Vec { o.optopt("", "markdown-playground-url", "URL to send code snippets to", "URL") }), stable("markdown-no-toc", |o| { - o.optflag("", "markdown-no-toc", "don't include table of contents") + o.optflagmulti("", "markdown-no-toc", "don't include table of contents") }), stable("e", |o| { o.optopt( @@ -412,13 +412,13 @@ fn opts() -> Vec { ) }), unstable("display-warnings", |o| { - o.optflag("", "display-warnings", "to print code warnings when testing doc") + o.optflagmulti("", "display-warnings", "to print code warnings when testing doc") }), stable("crate-version", |o| { o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") }), unstable("sort-modules-by-appearance", |o| { - o.optflag( + o.optflagmulti( "", "sort-modules-by-appearance", "sort modules by where they appear in the program, rather than alphabetically", @@ -495,7 +495,7 @@ fn opts() -> Vec { o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") }), unstable("disable-minification", |o| { - o.optflag("", "disable-minification", "Disable minification applied on JS files") + o.optflagmulti("", "disable-minification", "Disable minification applied on JS files") }), stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "OPT")), stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "OPT")), @@ -511,10 +511,10 @@ fn opts() -> Vec { "LEVEL", ) }), - unstable("force-warns", |o| { + unstable("force-warn", |o| { o.optopt( "", - "force-warns", + "force-warn", "Lints that will warn even if allowed somewhere else", "LINTS", ) @@ -523,7 +523,7 @@ fn opts() -> Vec { o.optopt("", "index-page", "Markdown file to be used as index page", "PATH") }), unstable("enable-index-page", |o| { - o.optflag("", "enable-index-page", "To enable generation of the index page") + o.optflagmulti("", "enable-index-page", "To enable generation of the index page") }), unstable("static-root-path", |o| { o.optopt( @@ -535,7 +535,7 @@ fn opts() -> Vec { ) }), unstable("disable-per-crate-search", |o| { - o.optflag( + o.optflagmulti( "", "disable-per-crate-search", "disables generating the crate selector on the search box", @@ -550,14 +550,14 @@ fn opts() -> Vec { ) }), unstable("show-coverage", |o| { - o.optflag( + o.optflagmulti( "", "show-coverage", "calculate percentage of public items with documentation", ) }), unstable("enable-per-target-ignores", |o| { - o.optflag( + o.optflagmulti( "", "enable-per-target-ignores", "parse ignore-foo for ignoring doctests on a per-target basis", @@ -582,9 +582,9 @@ fn opts() -> Vec { unstable("test-builder", |o| { o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH") }), - unstable("check", |o| o.optflag("", "check", "Run rustdoc checks")), + unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")), unstable("generate-redirect-map", |o| { - o.optflag( + o.optflagmulti( "", "generate-redirect-map", "Generate JSON file at the top level instead of generating HTML redirection files", @@ -598,9 +598,14 @@ fn opts() -> Vec { "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]", ) }), - unstable("no-run", |o| o.optflag("", "no-run", "Compile doctests without running them")), + unstable("no-run", |o| { + o.optflagmulti("", "no-run", "Compile doctests without running them") + }), unstable("show-type-layout", |o| { - o.optflag("", "show-type-layout", "Include the memory layout of types in the docs") + o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs") + }), + unstable("nocapture", |o| { + o.optflag("", "nocapture", "Don't capture stdout and stderr of tests") }), ] } diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index 376c83b1a6..49d8d7fb7f 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -193,7 +193,7 @@ crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) { ); for lint in &*RUSTDOC_LINTS { let name = lint.name_lower(); - lint_store.register_alias(&name.replace("rustdoc::", ""), &name); + lint_store.register_renamed(&name.replace("rustdoc::", ""), &name); } lint_store .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links"); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 963f2cf71f..80af2a7aaf 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -4,6 +4,7 @@ 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, TestOptions}; @@ -114,14 +115,14 @@ crate fn render>( } /// Runs any tests/code examples in the markdown file `input`. -crate fn test(mut options: Options) -> Result<(), String> { +crate fn test(options: Options) -> Result<(), String> { let input_str = read_to_string(&options.input) .map_err(|err| format!("{}: {}", options.input.display(), err))?; let mut opts = TestOptions::default(); opts.no_crate_inject = true; opts.display_warnings = options.display_warnings; let mut collector = Collector::new( - options.input.display().to_string(), + Symbol::intern(&options.input.display().to_string()), options.clone(), true, opts, @@ -134,11 +135,11 @@ crate fn test(mut options: Options) -> Result<(), String> { find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None); - options.test_args.insert(0, "rustdoctest".to_string()); - testing::test_main( - &options.test_args, + crate::doctest::run_tests( + options.test_args, + options.nocapture, + options.display_warnings, collector.tests, - Some(testing::Options::new().display_output(options.display_warnings)), ); Ok(()) } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 26a22f5b30..92e678e4c0 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -213,13 +213,13 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { let filename = i.span(self.ctx.tcx).filename(self.ctx.sess()); let has_doc_example = tests.found_tests != 0; - // The `expect_real()` should be okay because `local_def_id_to_hir_id` + // The `expect_def_id()` should be okay because `local_def_id_to_hir_id` // would presumably panic if a fake `DefIndex` were passed. let hir_id = self .ctx .tcx .hir() - .local_def_id_to_hir_id(i.def_id.expect_real().expect_local()); + .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local()); let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); // `missing_docs` is allow-by-default, so don't treat this as ignoring the item // unless the user had an explicit `allow` diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 7ccfdf2904..d961340f1f 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { return; } - let local_id = match item.def_id.as_real().and_then(|x| x.as_local()) { + let local_id = match item.def_id.as_def_id().and_then(|x| x.as_local()) { Some(id) => id, // We don't need to check the syntax for other crates so returning // without doing anything should not be a problem. @@ -137,7 +137,7 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { let sp = item.attr_span(self.cx.tcx); let extra = crate::html::markdown::ExtraInfo::new_did( self.cx.tcx, - item.def_id.expect_real(), + item.def_id.expect_def_id(), sp, ); for code_block in markdown::rust_code_blocks(&dox, &extra) { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0008155aa0..21bd3ebd21 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -541,6 +541,44 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }) } + /// Convert a DefId to a Res, where possible. + /// + /// This is used for resolving type aliases. + fn def_id_to_res(&self, ty_id: DefId) -> Option { + use PrimitiveType::*; + Some(match *self.cx.tcx.type_of(ty_id).kind() { + ty::Bool => Res::Primitive(Bool), + ty::Char => Res::Primitive(Char), + ty::Int(ity) => Res::Primitive(ity.into()), + ty::Uint(uty) => Res::Primitive(uty.into()), + ty::Float(fty) => Res::Primitive(fty.into()), + ty::Str => Res::Primitive(Str), + ty::Tuple(ref tys) if tys.is_empty() => Res::Primitive(Unit), + ty::Tuple(_) => Res::Primitive(Tuple), + ty::Array(..) => Res::Primitive(Array), + ty::Slice(_) => Res::Primitive(Slice), + ty::RawPtr(_) => Res::Primitive(RawPointer), + ty::Ref(..) => Res::Primitive(Reference), + ty::FnDef(..) => panic!("type alias to a function definition"), + ty::FnPtr(_) => Res::Primitive(Fn), + ty::Never => Res::Primitive(Never), + ty::Adt(&ty::AdtDef { did, .. }, _) | ty::Foreign(did) => { + Res::Def(self.cx.tcx.def_kind(did), did) + } + ty::Projection(_) + | ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(_) + | ty::Opaque(..) + | ty::Dynamic(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::Error(_) => return None, + }) + } + /// Returns: /// - None if no associated item was found /// - Some((_, _, Some(_))) if an item was found and should go through a side channel @@ -556,12 +594,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { match root_res { Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name), + Res::Def(DefKind::TyAlias, did) => { + // Resolve the link on the type the alias points to. + // FIXME: if the associated item is defined directly on the type alias, + // it will show up on its documentation page, we should link there instead. + let res = self.def_id_to_res(did)?; + self.resolve_associated_item(res, item_name, ns, module_id) + } Res::Def( - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::TyAlias - | DefKind::ForeignTy, + DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::ForeignTy, did, ) => { debug!("looking for associated item named {} for item {:?}", item_name, did); @@ -789,49 +830,48 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { fn fold_item(&mut self, item: Item) -> Option { use rustc_middle::ty::DefIdTree; - let parent_node = if item.is_fake() { - None - } else { - find_nearest_parent_module(self.cx.tcx, item.def_id.expect_real()) - }; - + let parent_node = + item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did)); if parent_node.is_some() { trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id); } // find item's parent to resolve `Self` in item's docs below debug!("looking for the `Self` type"); - let self_id = if item.is_fake() { - None - // Checking if the item is a field in an enum variant - } else if (matches!(self.cx.tcx.def_kind(item.def_id.expect_real()), DefKind::Field) - && matches!( - self.cx.tcx.def_kind(self.cx.tcx.parent(item.def_id.expect_real()).unwrap()), - DefKind::Variant - )) - { - self.cx - .tcx - .parent(item.def_id.expect_real()) - .and_then(|item_id| self.cx.tcx.parent(item_id)) - } else if matches!( - self.cx.tcx.def_kind(item.def_id.expect_real()), - DefKind::AssocConst - | DefKind::AssocFn - | DefKind::AssocTy - | DefKind::Variant - | DefKind::Field - ) { - self.cx.tcx.parent(item.def_id.expect_real()) - // HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`. - // Fixing this breaks `fn render_deref_methods`. - // As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item, - // regardless of what rustdoc wants to call it. - } else if let Some(parent) = self.cx.tcx.parent(item.def_id.expect_real()) { - let parent_kind = self.cx.tcx.def_kind(parent); - Some(if parent_kind == DefKind::Impl { parent } else { item.def_id.expect_real() }) - } else { - Some(item.def_id.expect_real()) + let self_id = match item.def_id.as_def_id() { + None => None, + Some(did) + if (matches!(self.cx.tcx.def_kind(did), DefKind::Field) + && matches!( + self.cx.tcx.def_kind(self.cx.tcx.parent(did).unwrap()), + DefKind::Variant + )) => + { + self.cx.tcx.parent(did).and_then(|item_id| self.cx.tcx.parent(item_id)) + } + Some(did) + if matches!( + self.cx.tcx.def_kind(did), + DefKind::AssocConst + | DefKind::AssocFn + | DefKind::AssocTy + | DefKind::Variant + | DefKind::Field + ) => + { + self.cx.tcx.parent(did) + } + Some(did) => match self.cx.tcx.parent(did) { + // HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`. + // Fixing this breaks `fn render_deref_methods`. + // As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item, + // regardless of what rustdoc wants to call it. + Some(parent) => { + let parent_kind = self.cx.tcx.def_kind(parent); + Some(if parent_kind == DefKind::Impl { parent } else { did }) + } + None => Some(did), + }, }; // FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly @@ -856,7 +896,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let inner_docs = item.inner_docs(self.cx.tcx); if item.is_mod() && inner_docs { - self.mod_ids.push(item.def_id.expect_real()); + self.mod_ids.push(item.def_id.expect_def_id()); } // We want to resolve in the lexical scope of the documentation. @@ -883,7 +923,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { Some(if item.is_mod() { if !inner_docs { - self.mod_ids.push(item.def_id.expect_real()); + self.mod_ids.push(item.def_id.expect_def_id()); } let ret = self.fold_item_recur(item); @@ -948,9 +988,9 @@ fn preprocess_link<'a>( } // Parse and strip the disambiguator from the link, if present. - let (path_str, disambiguator) = match Disambiguator::from_str(&link) { - Ok(Some((d, path))) => (path.trim(), Some(d)), - Ok(None) => (link.trim(), None), + let (disambiguator, path_str, link_text) = match Disambiguator::from_str(&link) { + Ok(Some((d, path, link_text))) => (Some(d), path.trim(), link_text.trim()), + Ok(None) => (None, link.trim(), link.trim()), Err((err_msg, relative_range)) => { // Only report error if we would not have ignored this link. See issue #83859. if !should_ignore_link_with_disambiguators(link) { @@ -968,11 +1008,6 @@ fn preprocess_link<'a>( return None; } - // We stripped `()` and `!` when parsing the disambiguator. - // Add them back to be displayed, but not prefix disambiguators. - let link_text = - disambiguator.map(|d| d.display_for(path_str)).unwrap_or_else(|| path_str.to_owned()); - // Strip generics from the path. let path_str = if path_str.contains(['<', '>'].as_slice()) { match strip_generics_from_path(&path_str) { @@ -1002,7 +1037,7 @@ fn preprocess_link<'a>( path_str, disambiguator, extra_fragment: extra_fragment.map(String::from), - link_text, + link_text: link_text.to_owned(), })) } @@ -1199,10 +1234,10 @@ impl LinkCollector<'_, '_> { // item can be non-local e.g. when using #[doc(primitive = "pointer")] if let Some((src_id, dst_id)) = id .as_local() - // The `expect_real()` should be okay because `local_def_id_to_hir_id` + // The `expect_def_id()` should be okay because `local_def_id_to_hir_id` // would presumably panic if a fake `DefIndex` were passed. .and_then(|dst_id| { - item.def_id.expect_real().as_local().map(|src_id| (src_id, dst_id)) + item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id)) }) { let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id); @@ -1343,7 +1378,7 @@ impl LinkCollector<'_, '_> { let other_ns = if expected_ns == ValueNS { TypeNS } else { ValueNS }; // FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator` // See https://github.com/rust-lang/rust/pull/76955#discussion_r493953382 for a good approach - for &new_ns in &[other_ns, MacroNS] { + for new_ns in [other_ns, MacroNS] { if let Some(res) = self.check_full_res(new_ns, path_str, base_node, extra_fragment) { @@ -1441,7 +1476,7 @@ impl LinkCollector<'_, '_> { Ok(res) => Some((res, extra_fragment.clone())), Err(mut kind) => { // `resolve_macro` only looks in the macro namespace. Try to give a better error if possible. - for &ns in &[TypeNS, ValueNS] { + for ns in [TypeNS, ValueNS] { if let Some(res) = self.check_full_res(ns, path_str, base_node, extra_fragment) { @@ -1510,24 +1545,12 @@ enum Disambiguator { } impl Disambiguator { - /// The text that should be displayed when the path is rendered as HTML. - /// - /// NOTE: `path` is not the original link given by the user, but a name suitable for passing to `resolve`. - fn display_for(&self, path: &str) -> String { - match self { - // FIXME: this will have different output if the user had `m!()` originally. - Self::Kind(DefKind::Macro(MacroKind::Bang)) => format!("{}!", path), - Self::Kind(DefKind::Fn) => format!("{}()", path), - _ => path.to_owned(), - } - } - - /// Given a link, parse and return `(disambiguator, path_str)`. + /// Given a link, parse and return `(disambiguator, path_str, link_text)`. /// /// This returns `Ok(Some(...))` if a disambiguator was found, /// `Ok(None)` if no disambiguator was found, or `Err(...)` /// if there was a problem with the disambiguator. - fn from_str(link: &str) -> Result, (String, Range)> { + fn from_str(link: &str) -> Result, (String, Range)> { use Disambiguator::{Kind, Namespace as NS, Primitive}; if let Some(idx) = link.find('@') { @@ -1548,18 +1571,20 @@ impl Disambiguator { "prim" | "primitive" => Primitive, _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)), }; - Ok(Some((d, &rest[1..]))) + Ok(Some((d, &rest[1..], &rest[1..]))) } else { let suffixes = [ ("!()", DefKind::Macro(MacroKind::Bang)), + ("!{}", DefKind::Macro(MacroKind::Bang)), + ("![]", DefKind::Macro(MacroKind::Bang)), ("()", DefKind::Fn), ("!", DefKind::Macro(MacroKind::Bang)), ]; - for &(suffix, kind) in &suffixes { - if let Some(link) = link.strip_suffix(suffix) { + for (suffix, kind) in suffixes { + if let Some(path_str) = link.strip_suffix(suffix) { // Avoid turning `!` or `()` into an empty string - if !link.is_empty() { - return Ok(Some((Kind(kind), link))); + if !path_str.is_empty() { + return Ok(Some((Kind(kind), path_str, link))); } } } @@ -1585,6 +1610,8 @@ impl Disambiguator { return Suggestion::Macro; } else if kind == DefKind::Fn || kind == DefKind::AssocFn { return Suggestion::Function; + } else if kind == DefKind::Field { + return Suggestion::RemoveDisambiguator; } let prefix = match kind { @@ -1649,6 +1676,8 @@ enum Suggestion { Function, /// `m!` Macro, + /// `foo` without any disambiguator + RemoveDisambiguator, } impl Suggestion { @@ -1657,6 +1686,7 @@ impl Suggestion { Self::Prefix(x) => format!("prefix with `{}@`", x).into(), Self::Function => "add parentheses".into(), Self::Macro => "add an exclamation mark".into(), + Self::RemoveDisambiguator => "remove the disambiguator".into(), } } @@ -1666,6 +1696,7 @@ impl Suggestion { Self::Prefix(prefix) => format!("{}@{}", prefix, path_str), Self::Function => format!("{}()", path_str), Self::Macro => format!("{}!", path_str), + Self::RemoveDisambiguator => path_str.into(), } } } @@ -1795,7 +1826,7 @@ fn resolution_failure( break; }; name = start; - for &ns in &[TypeNS, ValueNS, MacroNS] { + for ns in [TypeNS, ValueNS, MacroNS] { if let Some(res) = collector.check_full_res(ns, &start, module_id.into(), &None) { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 6d7c45f6ee..91c495a2bb 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -29,7 +29,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { let mut new_items = Vec::new(); - for &cnum in cx.tcx.crates().iter() { + for &cnum in cx.tcx.crates(()).iter() { for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() { cx.tcx.sess.prof.generic_activity("build_extern_trait_impl").run(|| { inline::build_impl(cx, None, did, None, &mut new_items); @@ -85,7 +85,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } }); - // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations` + // `tcx.crates(())` doesn't include the local crate, and `tcx.all_trait_implementations` // doesn't work with it anyway, so pull them from the HIR map instead let mut extra_attrs = Vec::new(); for &trait_did in cx.tcx.all_traits(()).iter() { @@ -136,10 +136,15 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? - if !self.cx.tcx.get_attrs(i.def_id.expect_real()).lists(sym::doc).has_word(sym::hidden) + if !self + .cx + .tcx + .get_attrs(i.def_id.expect_def_id()) + .lists(sym::doc) + .has_word(sym::hidden) { self.impls - .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_real())); + .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id())); } } @@ -149,7 +154,7 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { #[derive(Default)] struct ItemCollector { - items: FxHashSet, + items: FxHashSet, } impl ItemCollector { @@ -168,7 +173,7 @@ impl DocFolder for ItemCollector { struct BadImplStripper { prims: FxHashSet, - items: FxHashSet, + items: FxHashSet, } impl BadImplStripper { @@ -185,7 +190,7 @@ impl BadImplStripper { } } - fn keep_impl_with_def_id(&self, did: FakeDefId) -> bool { + fn keep_impl_with_def_id(&self, did: ItemId) -> bool { self.items.contains(&did) } } diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs index ba698474f1..03bc2b52f1 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/doc_test_lints.rs @@ -53,7 +53,7 @@ impl crate::doctest::Tester for Tests { } crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool { - if !cx.cache.access_levels.is_public(item.def_id.expect_real()) + if !cx.cache.access_levels.is_public(item.def_id.expect_def_id()) || matches!( *item.kind, clean::StructFieldItem(_) @@ -71,9 +71,9 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo { return false; } - // The `expect_real()` should be okay because `local_def_id_to_hir_id` + // The `expect_def_id()` should be okay because `local_def_id_to_hir_id` // would presumably panic if a fake `DefIndex` were passed. - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_real().expect_local()); + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local()); if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden) || inherits_doc_hidden(cx.tcx, hir_id) { @@ -107,7 +107,8 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { |lint| lint.build("missing code example in this documentation").emit(), ); } - } else if tests.found_tests > 0 && !cx.cache.access_levels.is_public(item.def_id.expect_real()) + } else if tests.found_tests > 0 + && !cx.cache.access_levels.is_public(item.def_id.expect_def_id()) { cx.tcx.struct_span_lint_hir( crate::lint::PRIVATE_DOC_TESTS, diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 87573e8e03..0aedbda35e 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -2,7 +2,7 @@ use rustc_span::symbol::sym; use std::mem; use crate::clean; -use crate::clean::{FakeDefIdSet, Item, NestedAttributesExt}; +use crate::clean::{Item, ItemIdSet, NestedAttributesExt}; use crate::core::DocContext; use crate::fold::{strip_item, DocFolder}; use crate::passes::{ImplStripper, Pass}; @@ -15,7 +15,7 @@ crate const STRIP_HIDDEN: Pass = Pass { /// Strip items marked `#[doc(hidden)]` crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate { - let mut retained = FakeDefIdSet::default(); + let mut retained = ItemIdSet::default(); // strip all #[doc(hidden)] items let krate = { @@ -29,7 +29,7 @@ crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Cra } struct Stripper<'a> { - retained: &'a mut FakeDefIdSet, + retained: &'a mut ItemIdSet, update_retained: bool, } diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 18abeb607a..dfdba2a4b3 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -1,4 +1,4 @@ -use crate::clean::{self, FakeDefIdSet}; +use crate::clean::{self, ItemIdSet}; use crate::core::DocContext; use crate::fold::DocFolder; use crate::passes::{ImplStripper, ImportStripper, Pass, Stripper}; @@ -14,7 +14,7 @@ crate const STRIP_PRIVATE: Pass = Pass { /// crate, specified by the `xcrate` flag. crate fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { // This stripper collects all *retained* nodes. - let mut retained = FakeDefIdSet::default(); + let mut retained = ItemIdSet::default(); // strip all private items { diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 528518410a..4305268c9a 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -2,11 +2,11 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::privacy::AccessLevels; use std::mem; -use crate::clean::{self, FakeDefIdSet, GetDefId, Item}; +use crate::clean::{self, GetDefId, Item, ItemIdSet}; use crate::fold::{strip_item, DocFolder}; crate struct Stripper<'a> { - crate retained: &'a mut FakeDefIdSet, + crate retained: &'a mut ItemIdSet, crate access_levels: &'a AccessLevels, crate update_retained: bool, } @@ -42,7 +42,7 @@ impl<'a> DocFolder for Stripper<'a> { | clean::TraitAliasItem(..) | clean::ForeignTypeItem => { if i.def_id.is_local() { - if !self.access_levels.is_exported(i.def_id.expect_real()) { + if !self.access_levels.is_exported(i.def_id.expect_def_id()) { debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name); return None; } @@ -116,7 +116,7 @@ impl<'a> DocFolder for Stripper<'a> { /// This stripper discards all impls which reference stripped items crate struct ImplStripper<'a> { - crate retained: &'a FakeDefIdSet, + crate retained: &'a ItemIdSet, } impl<'a> DocFolder for ImplStripper<'a> { diff --git a/src/librustdoc/passes/unindent_comments/tests.rs b/src/librustdoc/passes/unindent_comments/tests.rs index 9c9924841b..82d1afac5e 100644 --- a/src/librustdoc/passes/unindent_comments/tests.rs +++ b/src/librustdoc/passes/unindent_comments/tests.rs @@ -1,7 +1,7 @@ use super::*; +use rustc_span::create_default_session_globals_then; use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::Symbol; -use rustc_span::with_default_session_globals; fn create_doc_fragment(s: &str) -> Vec { vec![DocFragment { @@ -17,7 +17,7 @@ fn create_doc_fragment(s: &str) -> Vec { #[track_caller] fn run_test(input: &str, expected: &str) { - with_default_session_globals(|| { + create_default_session_globals_then(|| { let mut s = create_doc_fragment(input); unindent_fragments(&mut s); assert_eq!(&s.iter().collect::(), expected); diff --git a/src/librustdoc/theme/tests.rs b/src/librustdoc/theme/tests.rs index b924215733..4968ffd5a2 100644 --- a/src/librustdoc/theme/tests.rs +++ b/src/librustdoc/theme/tests.rs @@ -105,7 +105,7 @@ fn check_invalid_css() { #[test] fn test_with_minification() { - let text = include_str!("../html/static/themes/dark.css"); + let text = include_str!("../html/static/css/themes/dark.css"); let minified = minifier::css::minify(&text).expect("CSS minification failed"); let against = load_css_paths(text.as_bytes()); diff --git a/src/stage0.txt b/src/stage0.txt index 2af238ff6a..53a437569b 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,14 +12,14 @@ # stable release's version number. `date` is the date where the release we're # bootstrapping off was released. -date: 2021-06-17 -rustc: 1.53.0 +date: 2021-07-29 +rustc: 1.54.0 # We use a nightly rustfmt to format the source because it solves some # bootstrapping issues with use of new syntax in this repo. If you're looking at # the beta/stable branch, this key should be omitted, as we don't want to depend # on rustfmt from nightly there. -# rustfmt: nightly-2021-03-25 +#rustfmt: nightly-2021-03-25 # When making a stable release the process currently looks like: # diff --git a/src/test/assembly/asm/mips-types.rs b/src/test/assembly/asm/mips-types.rs index 60cfebdd99..9ec7ba83c4 100644 --- a/src/test/assembly/asm/mips-types.rs +++ b/src/test/assembly/asm/mips-types.rs @@ -2,8 +2,9 @@ // revisions: mips32 mips64 // assembly-output: emit-asm //[mips32] compile-flags: --target mips-unknown-linux-gnu +//[mips32] needs-llvm-components: mips //[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 -// needs-llvm-components: mips +//[mips64] needs-llvm-components: mips #![feature(no_core, lang_items, rustc_attrs, repr_simd)] #![crate_type = "rlib"] diff --git a/src/test/assembly/asm/powerpc-types.rs b/src/test/assembly/asm/powerpc-types.rs index 742e4ddaed..1e263649e8 100644 --- a/src/test/assembly/asm/powerpc-types.rs +++ b/src/test/assembly/asm/powerpc-types.rs @@ -2,8 +2,9 @@ // revisions: powerpc powerpc64 // assembly-output: emit-asm //[powerpc] compile-flags: --target powerpc-unknown-linux-gnu +//[powerpc] needs-llvm-components: powerpc //[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu -// needs-llvm-components: powerpc +//[powerpc64] needs-llvm-components: powerpc #![feature(no_core, lang_items, rustc_attrs, repr_simd)] #![crate_type = "rlib"] diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs index 1ba73fcac9..e62a6197b9 100644 --- a/src/test/assembly/asm/riscv-types.rs +++ b/src/test/assembly/asm/riscv-types.rs @@ -2,9 +2,10 @@ // revisions: riscv64 riscv32 // assembly-output: emit-asm //[riscv64] compile-flags: --target riscv64imac-unknown-none-elf +//[riscv64] needs-llvm-components: riscv //[riscv32] compile-flags: --target riscv32imac-unknown-none-elf +//[riscv32] needs-llvm-components: riscv // compile-flags: -C target-feature=+d -// needs-llvm-components: riscv // min-system-llvm-version: 12.0 #![feature(no_core, lang_items, rustc_attrs)] diff --git a/src/test/assembly/asm/x86-modifiers.rs b/src/test/assembly/asm/x86-modifiers.rs index da2dc51d69..c926fd7b3f 100644 --- a/src/test/assembly/asm/x86-modifiers.rs +++ b/src/test/assembly/asm/x86-modifiers.rs @@ -3,7 +3,9 @@ // assembly-output: emit-asm // compile-flags: -O //[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 // compile-flags: -C target-feature=+avx512bw diff --git a/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs index b65b727d22..d25f3a0377 100644 --- a/src/test/assembly/asm/x86-types.rs +++ b/src/test/assembly/asm/x86-types.rs @@ -2,7 +2,9 @@ // 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 // compile-flags: -C target-feature=+avx512bw diff --git a/src/test/assembly/static-relocation-model.rs b/src/test/assembly/static-relocation-model.rs index 2cd74a01c8..b331d45668 100644 --- a/src/test/assembly/static-relocation-model.rs +++ b/src/test/assembly/static-relocation-model.rs @@ -1,10 +1,12 @@ // min-llvm-version: 12.0.0 -// needs-llvm-components: aarch64 x86 powerpc // revisions: x64 A64 ppc64le // assembly-output: emit-asm // [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static +// [x64] needs-llvm-components: x86 // [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static +// [A64] needs-llvm-components: aarch64 // [ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu -Crelocation-model=static +// [ppc64le] needs-llvm-components: powerpc #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/codegen/abi-efiapi.rs b/src/test/codegen/abi-efiapi.rs index 613b0bf50e..b4fda5f8c8 100644 --- a/src/test/codegen/abi-efiapi.rs +++ b/src/test/codegen/abi-efiapi.rs @@ -1,13 +1,16 @@ // Checks if the correct annotation for the efiapi ABI is passed to llvm. // revisions:x86_64 i686 aarch64 arm riscv -// needs-llvm-components: aarch64 arm riscv - //[x86_64] compile-flags: --target x86_64-unknown-uefi +//[x86_64] needs-llvm-components: aarch64 arm riscv //[i686] compile-flags: --target i686-unknown-linux-musl +//[i686] needs-llvm-components: aarch64 arm riscv //[aarch64] compile-flags: --target aarch64-unknown-none +//[aarch64] needs-llvm-components: aarch64 arm riscv //[arm] compile-flags: --target armv7r-none-eabi +//[arm] needs-llvm-components: aarch64 arm riscv //[riscv] compile-flags: --target riscv64gc-unknown-none-elf +//[riscv] needs-llvm-components: aarch64 arm riscv // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/align-fn.rs b/src/test/codegen/align-fn.rs new file mode 100644 index 0000000000..c5886cf280 --- /dev/null +++ b/src/test/codegen/align-fn.rs @@ -0,0 +1,9 @@ +// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 + +#![crate_type = "lib"] +#![feature(fn_align)] + +// CHECK: align 16 +#[no_mangle] +#[repr(align(16))] +pub fn fn_align() {} diff --git a/src/test/codegen/array-equality.rs b/src/test/codegen/array-equality.rs new file mode 100644 index 0000000000..4b60fa4b0b --- /dev/null +++ b/src/test/codegen/array-equality.rs @@ -0,0 +1,57 @@ +// compile-flags: -O +// only-x86_64 + +#![crate_type = "lib"] + +// CHECK-LABEL: @array_eq_value +#[no_mangle] +pub fn array_eq_value(a: [u16; 6], b: [u16; 6]) -> bool { + // CHECK-NEXT: start: + // CHECK-NEXT: %2 = icmp eq i96 %0, %1 + // CHECK-NEXT: ret i1 %2 + a == b +} + +// CHECK-LABEL: @array_eq_ref +#[no_mangle] +pub fn array_eq_ref(a: &[u16; 6], b: &[u16; 6]) -> bool { + // CHECK: start: + // CHECK: load i96, i96* %{{.+}}, align 2 + // CHECK: load i96, i96* %{{.+}}, align 2 + // CHECK: icmp eq i96 + // CHECK-NEXT: ret + a == b +} + +// CHECK-LABEL: @array_eq_value_still_passed_by_pointer +#[no_mangle] +pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool { + // CHECK-NEXT: start: + // CHECK-NEXT: bitcast + // CHECK-NEXT: bitcast + // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(18) %{{.+}}, i8* nonnull dereferenceable(18) %{{.+}}, i64 18) + // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0 + // CHECK-NEXT: ret i1 %[[EQ]] + a == b +} + +// CHECK-LABEL: @array_eq_long +#[no_mangle] +pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool { + // CHECK-NEXT: start: + // CHECK-NEXT: bitcast + // CHECK-NEXT: bitcast + // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(2468) %{{.+}}, i8* nonnull dereferenceable(2468) %{{.+}}, i64 2468) + // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0 + // CHECK-NEXT: ret i1 %[[EQ]] + a == b +} + +// CHECK-LABEL: @array_eq_zero(i128 %0) +#[no_mangle] +pub fn array_eq_zero(x: [u16; 8]) -> bool { + // CHECK-NEXT: start: + // CHECK-NEXT: %[[EQ:.+]] = icmp eq i128 %0, 0 + // CHECK-NEXT: ret i1 %[[EQ]] + x == [0; 8] +} diff --git a/src/test/codegen/asm-clobbers.rs b/src/test/codegen/asm-clobbers.rs new file mode 100644 index 0000000000..9d7c8b5f15 --- /dev/null +++ b/src/test/codegen/asm-clobbers.rs @@ -0,0 +1,19 @@ +// compile-flags: -O +// only-x86_64 + +#![crate_type = "rlib"] +#![feature(asm)] + +// CHECK-LABEL: @x87_clobber +// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)} +#[no_mangle] +pub unsafe fn x87_clobber() { + asm!("foo", out("st") _); +} + +// CHECK-LABEL: @mmx_clobber +// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)} +#[no_mangle] +pub unsafe fn mmx_clobber() { + asm!("bar", out("mm0") _, out("mm1") _); +} diff --git a/src/test/codegen/asm-options.rs b/src/test/codegen/asm-options.rs index 70391661b0..28df0f9b85 100644 --- a/src/test/codegen/asm-options.rs +++ b/src/test/codegen/asm-options.rs @@ -94,3 +94,10 @@ pub unsafe fn dont_remove_nonpure() { asm!("", options(nomem)); asm!("", options(readonly)); } + +// CHECK-LABEL: @raw +// CHECK: call void asm sideeffect inteldialect "{} {}", ""() +#[no_mangle] +pub unsafe fn raw() { + asm!("{} {}", options(nostack, nomem, preserves_flags, raw)); +} diff --git a/src/test/codegen/asm-sanitize-llvm.rs b/src/test/codegen/asm-sanitize-llvm.rs index fe09caa697..135177016b 100644 --- a/src/test/codegen/asm-sanitize-llvm.rs +++ b/src/test/codegen/asm-sanitize-llvm.rs @@ -1,5 +1,6 @@ -// FIXME(nagisa): remove the flags here once all targets support `asm!`. +// FIXME(nagisa): remove the flags below once all targets support `asm!`. // compile-flags: --target x86_64-unknown-linux-gnu +// needs-llvm-components: x86 // Verify we sanitize the special tokens for the LLVM inline-assembly, ensuring people won't // inadvertently rely on the LLVM-specific syntax and features. diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index e410180bff..0c16b9ad3a 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -17,7 +17,7 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0" // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, @@ -43,11 +43,11 @@ async fn async_fn_test() { // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]], -// CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]], +// CHECK-NOT: flags: DIFlagArtificial fn main() { let _dummy = async_fn_test(); diff --git a/src/test/codegen/async-fn-debug.rs b/src/test/codegen/async-fn-debug.rs index 7de115f7e9..39319a3ea7 100644 --- a/src/test/codegen/async-fn-debug.rs +++ b/src/test/codegen/async-fn-debug.rs @@ -17,7 +17,7 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]] +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[ASYNC_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs index 3aab4bea3d..7f945299c2 100644 --- a/src/test/codegen/consts.rs +++ b/src/test/codegen/consts.rs @@ -10,7 +10,7 @@ // CHECK: @STATIC = {{.*}}, align 4 // This checks the constants from inline_enum_const -// CHECK: @alloc8 = {{.*}}, align 2 +// CHECK: @alloc9 = {{.*}}, align 2 // This checks the constants from {low,high}_align_const, they share the same // constant, but the alignment differs, so the higher one should be used diff --git a/src/test/codegen/default-requires-uwtable.rs b/src/test/codegen/default-requires-uwtable.rs index d4c4200c5d..5d77d3f14b 100644 --- a/src/test/codegen/default-requires-uwtable.rs +++ b/src/test/codegen/default-requires-uwtable.rs @@ -1,8 +1,9 @@ // revisions: WINDOWS ANDROID -// needs-llvm-components: x86 arm // compile-flags: -C panic=abort // [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc +// [WINDOWS] needs-llvm-components: x86 // [ANDROID] compile-flags: --target=armv7-linux-androideabi +// [ANDROID] needs-llvm-components: arm #![feature(no_core, lang_items)] #![crate_type = "lib"] diff --git a/src/test/codegen/fn-impl-trait-self.rs b/src/test/codegen/fn-impl-trait-self.rs index f9113d5019..4bd811bed1 100644 --- a/src/test/codegen/fn-impl-trait-self.rs +++ b/src/test/codegen/fn-impl-trait-self.rs @@ -1,7 +1,8 @@ // compile-flags: -g // // CHECK-LABEL: @main -// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> ",{{.*}} +// MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}} +// NONMSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> ",{{.*}} // // CHECK: {{.*}}DISubroutineType{{.*}} // CHECK: {{.*}}DIBasicType(name: "", encoding: DW_ATE_unsigned) diff --git a/src/test/codegen/frame-pointer.rs b/src/test/codegen/frame-pointer.rs new file mode 100644 index 0000000000..367591dcb9 --- /dev/null +++ b/src/test/codegen/frame-pointer.rs @@ -0,0 +1,35 @@ +// compile-flags: --crate-type=rlib +// revisions: aarch64-apple aarch64-linux force x64-apple x64-linux +// [aarch64-apple] needs-llvm-components: aarch64 +// [aarch64-apple] compile-flags: --target=aarch64-apple-darwin +// [aarch64-linux] needs-llvm-components: aarch64 +// [aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu +// [force] needs-llvm-components: x86 +// [force] compile-flags: --target=x86_64-unknown-linux-gnu -Cforce-frame-pointers=yes +// [x64-apple] needs-llvm-components: x86 +// [x64-apple] compile-flags: --target=x86_64-apple-darwin +// [x64-linux] needs-llvm-components: x86 +// [x64-linux] compile-flags: --target=x86_64-unknown-linux-gnu + +#![feature(no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } +#[lang="copy"] +trait Copy { } + + + +// CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] { +#[no_mangle] +pub fn peach(x: u32) -> u32 { + x +} + +// CHECK: attributes [[PEACH_ATTRS]] = { +// x64-linux-NOT: {{.*}}"frame-pointer"{{.*}} +// aarch64-linux-NOT: {{.*}}"frame-pointer"{{.*}} +// x64-apple-SAME: {{.*}}"frame-pointer"="all" +// force-SAME: {{.*}}"frame-pointer"="all" +// aarch64-apple-SAME: {{.*}}"frame-pointer"="non-leaf" +// CHECK-SAME: } diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 7edb07d224..68d138f8df 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -21,7 +21,7 @@ fn generator_test() -> impl Generator { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0" +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0" // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, @@ -47,11 +47,11 @@ fn generator_test() -> impl Generator { // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) -// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]], -// CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]], +// CHECK-NOT: flags: DIFlagArtificial fn main() { let _dummy = generator_test(); diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 8b87a2f064..ea324695c1 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -21,7 +21,7 @@ fn generator_test() -> impl Generator { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]] +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[GEN_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] diff --git a/src/test/codegen/i686-macosx-deployment-target.rs b/src/test/codegen/i686-macosx-deployment-target.rs index dad376d667..17258a264a 100644 --- a/src/test/codegen/i686-macosx-deployment-target.rs +++ b/src/test/codegen/i686-macosx-deployment-target.rs @@ -3,6 +3,7 @@ // See issue #60235. // compile-flags: -O --target=i686-apple-darwin --crate-type=rlib +// needs-llvm-components: x86 // rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/codegen/i686-no-macosx-deployment-target.rs b/src/test/codegen/i686-no-macosx-deployment-target.rs index 1cebc49236..043040a95e 100644 --- a/src/test/codegen/i686-no-macosx-deployment-target.rs +++ b/src/test/codegen/i686-no-macosx-deployment-target.rs @@ -3,6 +3,7 @@ // See issue #60235. // compile-flags: -O --target=i686-apple-darwin --crate-type=rlib +// needs-llvm-components: x86 // unset-rustc-env:MACOSX_DEPLOYMENT_TARGET #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/codegen/pgo-instrumentation.rs b/src/test/codegen/pgo-instrumentation.rs index c085f3c829..05c2d2fc0d 100644 --- a/src/test/codegen/pgo-instrumentation.rs +++ b/src/test/codegen/pgo-instrumentation.rs @@ -1,8 +1,7 @@ // Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR. -// Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms. // needs-profiler-support -// compile-flags: -Cprofile-generate -Ccodegen-units=1 -Cpanic=abort +// compile-flags: -Cprofile-generate -Ccodegen-units=1 // CHECK: @__llvm_profile_raw_version = // CHECK-DAG: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = {{.*}}global diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs index c2d01c7fec..698dfe6b4f 100644 --- a/src/test/codegen/remap_path_prefix/main.rs +++ b/src/test/codegen/remap_path_prefix/main.rs @@ -12,7 +12,7 @@ mod aux_mod; include!("aux_mod.rs"); // Here we check that the expansion of the file!() macro is mapped. -// CHECK: @alloc1 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1 +// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1 pub static FILE_PATH: &'static str = file!(); fn main() { diff --git a/src/test/codegen/slice-ref-equality.rs b/src/test/codegen/slice-ref-equality.rs index acc7879e7b..1f99ac7342 100644 --- a/src/test/codegen/slice-ref-equality.rs +++ b/src/test/codegen/slice-ref-equality.rs @@ -2,15 +2,30 @@ #![crate_type = "lib"] -// #71602: check that slice equality just generates a single bcmp +// #71602 reported a simple array comparison just generating a loop. +// This was originally fixed by ensuring it generates a single bcmp, +// but we now generate it as a load instead. `is_zero_slice` was +// tweaked to still test the case of comparison against a slice, +// and `is_zero_array` tests the new array-specific behaviour. // CHECK-LABEL: @is_zero_slice #[no_mangle] pub fn is_zero_slice(data: &[u8; 4]) -> bool { - // CHECK: start: + // CHECK: : // CHECK-NEXT: %{{.+}} = getelementptr {{.+}} // CHECK-NEXT: %[[BCMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{.+}}) // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[BCMP]], 0 // CHECK-NEXT: ret i1 %[[EQ]] + &data[..] == [0; 4] +} + +// CHECK-LABEL: @is_zero_array +#[no_mangle] +pub fn is_zero_array(data: &[u8; 4]) -> bool { + // CHECK: start: + // CHECK-NEXT: %[[PTR:.+]] = bitcast [4 x i8]* {{.+}} to i32* + // CHECK-NEXT: %[[LOAD:.+]] = load i32, i32* %[[PTR]], align 1 + // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0 + // CHECK-NEXT: ret i1 %[[EQ]] *data == [0; 4] } diff --git a/src/test/codegen/sparc-struct-abi.rs b/src/test/codegen/sparc-struct-abi.rs index 78e5b14a21..f228d7c550 100644 --- a/src/test/codegen/sparc-struct-abi.rs +++ b/src/test/codegen/sparc-struct-abi.rs @@ -1,9 +1,8 @@ -// // Checks that we correctly codegen extern "C" functions returning structs. // See issue #52638. -// only-sparc64 // compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib +// needs-llvm-components: sparc #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/codegen/unwind-abis/stdcall-unwind-abi.rs b/src/test/codegen/unwind-abis/stdcall-unwind-abi.rs index ed804ca278..f1dff27ad6 100644 --- a/src/test/codegen/unwind-abis/stdcall-unwind-abi.rs +++ b/src/test/codegen/unwind-abis/stdcall-unwind-abi.rs @@ -1,15 +1,14 @@ -// compile-flags: -C opt-level=0 -// ignore-arm stdcall isn't supported -// ignore-aarch64 stdcall isn't supported -// ignore-riscv64 stdcall isn't supported +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes +#![no_core] +#![feature(no_core, lang_items, c_unwind)] +#[lang="sized"] +trait Sized { } // Test that `nounwind` atributes are correctly applied to exported `stdcall` and `stdcall-unwind` // extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable // optimizations above to prevent LLVM from inferring the attribute. -#![crate_type = "lib"] -#![feature(c_unwind)] - // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] pub extern "stdcall" fn rust_item_that_cannot_unwind() { diff --git a/src/test/codegen/unwind-abis/thiscall-unwind-abi.rs b/src/test/codegen/unwind-abis/thiscall-unwind-abi.rs index aaa63ae55c..d2cf041b72 100644 --- a/src/test/codegen/unwind-abis/thiscall-unwind-abi.rs +++ b/src/test/codegen/unwind-abis/thiscall-unwind-abi.rs @@ -1,16 +1,14 @@ -// compile-flags: -C opt-level=0 -// ignore-arm thiscall isn't supported -// ignore-aarch64 thiscall isn't supported -// ignore-riscv64 thiscall isn't supported +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes +#![no_core] +#![feature(no_core, lang_items, c_unwind, abi_thiscall)] +#[lang="sized"] +trait Sized { } // Test that `nounwind` atributes are correctly applied to exported `thiscall` and // `thiscall-unwind` extern functions. `thiscall-unwind` functions MUST NOT have this attribute. We // disable optimizations above to prevent LLVM from inferring the attribute. -#![crate_type = "lib"] -#![feature(abi_thiscall)] -#![feature(c_unwind)] - // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] pub extern "thiscall" fn rust_item_that_cannot_unwind() { diff --git a/src/test/codegen/x86_64-macosx-deployment-target.rs b/src/test/codegen/x86_64-macosx-deployment-target.rs index 8e291b7b29..8e673d11d9 100644 --- a/src/test/codegen/x86_64-macosx-deployment-target.rs +++ b/src/test/codegen/x86_64-macosx-deployment-target.rs @@ -3,6 +3,7 @@ // See issue #60235. // compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib +// needs-llvm-components: x86 // rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9 #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/codegen/x86_64-no-macosx-deployment-target.rs b/src/test/codegen/x86_64-no-macosx-deployment-target.rs index c5ac73b54e..25ae6924de 100644 --- a/src/test/codegen/x86_64-no-macosx-deployment-target.rs +++ b/src/test/codegen/x86_64-no-macosx-deployment-target.rs @@ -3,6 +3,7 @@ // See issue #60235. // compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib +// needs-llvm-components: x86 // unset-rustc-env:MACOSX_DEPLOYMENT_TARGET #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 3721b87678..c35c325549 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -6,9 +6,8 @@ // min-lldb-version: 310 -// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only -// for now. -// only-macos +// This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now. +// ignore-linux // compile-flags:-g @@ -44,6 +43,9 @@ // gdb-check:$13 = 2.5 // gdb-command:print f64 // gdb-check:$14 = 3.5 +// gdb-command:print s +// gdbg-check:$15 = {data_ptr = [...] "Hello, World!", length = 13} +// gdbr-check:$15 = "Hello, World!" // === LLDB TESTS ================================================================================== @@ -94,6 +96,41 @@ // lldbg-check:[...]$12 = 3.5 // lldbr-check:(f64) f64 = 3.5 + +// === CDB TESTS =================================================================================== + +// cdb-command:g +// cdb-command:dx b +// cdb-check:b : false [Type: bool] +// cdb-command:dx i +// cdb-check:i : -1 [Type: [...]] +// The variable 'c' doesn't appear for some reason... +// cdb-command:dx i8 +// cdb-check:i8 : 68 [Type: char] +// cdb-command:dx i16 +// cdb-check:i16 : -16 [Type: short] +// cdb-command:dx i32 +// cdb-check:i32 : -32 [Type: int] +// cdb-command:dx i64 +// cdb-check:i64 : -64 [Type: __int64] +// cdb-command:dx u +// cdb-check:u : 0x1 [Type: [...]] +// cdb-command:dx u8 +// cdb-check:u8 : 0x64 [Type: unsigned char] +// cdb-command:dx u16 +// cdb-check:u16 : 0x10 [Type: unsigned short] +// cdb-command:dx u32 +// cdb-check:u32 : 0x20 [Type: unsigned int] +// cdb-command:dx u64 +// cdb-check:u64 : 0x40 [Type: unsigned __int64] +// cdb-command:dx f32 +// cdb-check:f32 : 2.500000 [Type: float] +// cdb-command:dx f64 +// cdb-check:f64 : 3.500000 [Type: double] +// cdb-command:.enable_unicode 1 +// cdb-command:dx s +// cdb-check:s : "Hello, World!" [Type: str] + #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -113,6 +150,7 @@ fn main() { let u64: u64 = 64; let f32: f32 = 2.5; let f64: f64 = 3.5; + let s: &str = "Hello, World!"; _zzz(); // #break } diff --git a/src/test/debuginfo/duration-type.rs b/src/test/debuginfo/duration-type.rs new file mode 100644 index 0000000000..bc0266d644 --- /dev/null +++ b/src/test/debuginfo/duration-type.rs @@ -0,0 +1,22 @@ +// only-cdb +// compile-flags:-g + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx duration +// cdb-check:duration : 5s 12ns [Type: core::time::Duration] +// cdb-check: [] [Type: core::time::Duration] +// cdb-check: seconds : 5 [Type: unsigned __int64] +// cdb-check: nanoseconds : 12 [Type: unsigned int] + +use std::time::Duration; + +fn main() { + let duration = Duration::new(5, 12); + + zzz(); // #break +} + +fn zzz() { } diff --git a/src/test/debuginfo/fixed-sized-array.rs b/src/test/debuginfo/fixed-sized-array.rs new file mode 100644 index 0000000000..d8899224d2 --- /dev/null +++ b/src/test/debuginfo/fixed-sized-array.rs @@ -0,0 +1,39 @@ +// Testing the display of fixed sized arrays in cdb. + +// cdb-only +// min-cdb-version: 10.0.18317.1001 +// compile-flags:-g + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx xs,d +// cdb-check:xs,d [Type: int [5]] +// cdb-check: [0] : 1 [Type: int] +// cdb-check: [1] : 2 [Type: int] +// cdb-check: [2] : 3 [Type: int] +// cdb-check: [3] : 4 [Type: int] +// cdb-check: [4] : 5 [Type: int] + +// cdb-command: dx ys,d +// cdb-check:ys,d [Type: int [3]] +// cdb-check: [0] : 0 [Type: int] +// cdb-check: [1] : 0 [Type: int] +// cdb-check: [2] : 0 [Type: int] + +fn main() { + // Fixed-size array (type signature is superfluous) + let xs: [i32; 5] = [1, 2, 3, 4, 5]; + + // All elements can be initialized to the same value + let ys: [i32; 3] = [0; 3]; + + // Indexing starts at 0 + println!("first element of the array: {}", xs[0]); + println!("second element of the array: {}", xs[1]); + + zzz(); // #break +} + +fn zzz() { () } diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs new file mode 100644 index 0000000000..28ab176ba5 --- /dev/null +++ b/src/test/debuginfo/function-names.rs @@ -0,0 +1,201 @@ +// Function names are formatted differently in old versions of GDB +// min-gdb-version: 9.2 + +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// Top-level function +// gdb-command:info functions -q function_names::main +// gdb-check:[...]static fn function_names::main(); +// gdb-command:info functions -q function_names::generic_func<* +// gdb-check:[...]static fn function_names::generic_func(i32) -> i32; + +// Implementations +// gdb-command:info functions -q function_names::.*::impl_function.* +// gdb-check:[...]static fn function_names::GenericStruct::impl_function(); +// gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function(); +// gdb-check:[...]static fn function_names::TestStruct1::impl_function(); + +// Trait implementations +// gdb-command:info functions -q function_names::.*::trait_function.* +// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); +// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); +// gdb-check:[...]static fn ::trait_function(); +// gdb-check:[...]static fn ::trait_function(); + +// Closure +// gdb-command:info functions -q function_names::.*::{{closure.* +// gdb-check:[...]static fn function_names::GenericStruct::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0}); +// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0}); +// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0}); + +// Generator +// Generators don't seem to appear in GDB's symbol table. + +// Const generic parameter +// gdb-command:info functions -q function_names::const_generic_fn.* +// gdb-check:[...]static fn function_names::const_generic_fn_bool(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int(); +// gdb-check:[...]static fn function_names::const_generic_fn_signed_int(); +// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int(); + +// === CDB TESTS =================================================================================== + +// Top-level function +// cdb-command:x a!function_names::main +// cdb-check:[...] a!function_names::main (void) +// cdb-command:x a!function_names::generic_func<* +// cdb-check:[...] a!function_names::generic_func (int) + +// Implementations +// cdb-command:x a!function_names::*::impl_function* +// cdb-check:[...] a!function_names::Mod1::TestStruct2::impl_function (void) +// cdb-check:[...] a!function_names::TestStruct1::impl_function (void) +// cdb-check:[...] a!function_names::GenericStruct::impl_function (void) + +// Trait implementations +// cdb-command:x a!function_names::*::trait_function* +// cdb-check:[...] a!function_names::impl$3::trait_function (void) +// cdb-check:[...] a!function_names::impl$6::trait_function (void) +// cdb-check:[...] a!function_names::impl$1::trait_function (void) +// cdb-check:[...] a!function_names::impl$5::trait_function3 (void) +// cdb-check:[...] a!function_names::Mod1::impl$1::trait_function (void) + +// Closure +// cdb-command:x a!function_names::*::closure* +// cdb-check:[...] a!function_names::impl$2::impl_function::closure$0 (void) +// cdb-check:[...] a!function_names::main::closure$0 (void) +// cdb-check:[...] a!function_names::generic_func::closure$0 (void) + +// Generator +// cdb-command:x a!function_names::*::generator* +// cdb-check:[...] a!function_names::main::generator$1 (void) + +// Const generic parameter +// cdb-command:x a!function_names::const_generic_fn* +// cdb-check:[...] a!function_names::const_generic_fn_bool (void) +// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) +// cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) +// cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) + +#![allow(unused_variables)] +#![feature(omit_gdb_pretty_printer_section)] +#![omit_gdb_pretty_printer_section] +#![feature(const_generics, generators, generator_trait)] +#![allow(incomplete_features)] // for const_generics + +use Mod1::TestTrait2; +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + // Implementations + TestStruct1::impl_function(); + Mod1::TestStruct2::impl_function(); + GenericStruct::::impl_function(); + + // Trait implementations + TestStruct1::trait_function(); + Mod1::TestStruct2::trait_function(); + GenericStruct::::trait_function(); + GenericStruct::<[i32; 1], f32>::trait_function(); + GenericStruct::::trait_function3(); + + // Generic function + let _ = generic_func(42); + + // Closure + let closure = || { TestStruct1 }; + closure(); + + // Generator + let mut generator = || { yield; return; }; + Pin::new(&mut generator).resume(()); + + // Const generic functions + const_generic_fn_bool::(); + const_generic_fn_non_int::<{()}>(); + const_generic_fn_signed_int::<-7>(); + const_generic_fn_unsigned_int::<14>(); +} + +struct TestStruct1; +trait TestTrait1 { + fn trait_function(); +} + +// Implementation +impl TestStruct1 { + pub fn impl_function() {} +} + +// Implementation for a trait +impl TestTrait1 for TestStruct1 { + fn trait_function() {} +} + +// Implementation and implementation within a mod +mod Mod1 { + pub struct TestStruct2; + pub trait TestTrait2 { + fn trait_function(); + } + + impl TestStruct2 { + pub fn impl_function() {} + } + + impl TestTrait2 for TestStruct2 { + fn trait_function() {} + } +} + +struct GenericStruct(std::marker::PhantomData<(T1, T2)>); + +// Generic implementation +impl GenericStruct { + pub fn impl_function() { + // Closure in a generic implementation + let closure = || { TestStruct1 }; + closure(); + } +} + +// Generic trait implementation +impl TestTrait1 for GenericStruct { + fn trait_function() {} +} + +// Implementation based on associated type +trait TestTrait3 { + type AssocType; + fn trait_function3(); +} +impl TestTrait3 for TestStruct1 { + type AssocType = usize; + fn trait_function3() {} +} +impl TestTrait3 for GenericStruct { + type AssocType = T::AssocType; + fn trait_function3() {} +} + +// Generic trait implementation with const generics +impl TestTrait1 for GenericStruct<[T; N], f32> { + fn trait_function() {} +} + +// Generic function +fn generic_func(value: T) -> T { + // Closure in a generic function + let closure = || { TestStruct1 }; + closure(); + + value +} + +fn const_generic_fn_bool() {} +fn const_generic_fn_non_int() {} +fn const_generic_fn_signed_int() {} +fn const_generic_fn_unsigned_int() {} diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index 1beed1c835..7ac3304aa9 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -11,31 +11,31 @@ // gdb-command:run // gdb-command:print b -// gdb-check:$1 = generator_objects::main::generator-0::Unresumed(0x[...]) +// gdb-check:$1 = generator_objects::main::{generator#0}::Unresumed(0x[...]) // gdb-command:continue // gdb-command:print b -// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, __0: 0x[...]} +// gdb-check:$2 = generator_objects::main::{generator#0}::Suspend0{c: 6, d: 7, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, __0: 0x[...]} +// gdb-check:$3 = generator_objects::main::{generator#0}::Suspend1{c: 7, d: 8, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$4 = generator_objects::main::generator-0::Returned(0x[...]) +// gdb-check:$4 = generator_objects::main::{generator#0}::Returned(0x[...]) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $0 = +// lldbg-check:(generator_objects::main::{generator#0}) $0 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $1 = +// lldbg-check:(generator_objects::main::{generator#0}) $1 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $2 = +// lldbg-check:(generator_objects::main::{generator#0}) $2 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $3 = +// lldbg-check:(generator_objects::main::{generator#0}) $3 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 170a610c62..5fa5ce8009 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -39,6 +39,27 @@ // lldbg-check:[...]$3 = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } // lldbr-check:(generic_struct::AGenericStruct>) float_int_float = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } +// === CDB TESTS =================================================================================== + +// cdb-command:g + +// cdb-command:dx int_int +// cdb-check:int_int [Type: generic_struct::AGenericStruct] +// cdb-check:[...]key : 0 [Type: int] +// cdb-check:[...]value : 1 [Type: int] +// cdb-command:dx int_float +// cdb-check:int_float [Type: generic_struct::AGenericStruct] +// cdb-check:[...]key : 2 [Type: int] +// cdb-check:[...]value : 3.500000 [Type: double] +// cdb-command:dx float_int +// cdb-check:float_int [Type: generic_struct::AGenericStruct] +// cdb-check:[...]key : 4.500000 [Type: double] +// cdb-check:[...]value : 5 [Type: int] +// cdb-command:dx float_int_float +// cdb-check:float_int_float [Type: generic_struct::AGenericStruct >] +// cdb-check:[...]key : 6.500000 [Type: double] +// cdb-check:[...]value [Type: generic_struct::AGenericStruct] + #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index 6b2b12edda..f6d2146fe1 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -11,20 +11,20 @@ // gdb-command:run // gdb-command:print g -// gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1)) +// gdb-check:$1 = issue_57822::main::{closure#1} (issue_57822::main::{closure#0} (1)) // gdb-command:print b -// gdb-check:$2 = issue_57822::main::generator-3::Unresumed(issue_57822::main::generator-2::Unresumed(2)) +// gdb-check:$2 = issue_57822::main::{generator#3}::Unresumed(issue_57822::main::{generator#2}::Unresumed(2)) // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print g -// lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } } +// lldbg-check:(issue_57822::main::{closure#1}) $0 = { 0 = { 0 = 1 } } // lldb-command:print b -// lldbg-check:(issue_57822::main::generator-3) $1 = +// lldbg-check:(issue_57822::main::{generator#3}) $1 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/marker-types.rs b/src/test/debuginfo/marker-types.rs new file mode 100644 index 0000000000..8373d7856b --- /dev/null +++ b/src/test/debuginfo/marker-types.rs @@ -0,0 +1,49 @@ +// only-cdb +// compile-flags:-g + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx nonnull +// cdb-check:nonnull : NonNull(0x[...]: 0xc) [Type: core::ptr::non_null::NonNull] +// cdb-check: [] [Type: core::ptr::non_null::NonNull] +// cdb-check: 0xc [Type: unsigned int] + +// cdb-command: dx manuallydrop +// cdb-check:manuallydrop : 12345 [Type: core::mem::manually_drop::ManuallyDrop] +// cdb-check: [] [Type: core::mem::manually_drop::ManuallyDrop] + +// cdb-command: dx pin +// cdb-check:pin : Pin(0x[...]: "this") [Type: core::pin::Pin >] +// cdb-check: [] [Type: core::pin::Pin >] +// cdb-check: [len] : 0x4 [Type: unsigned [...]] +// cdb-check: [capacity] : 0x4 [Type: unsigned [...]] +// cdb-check: [chars] : "this" + +// cdb-command: dx unique +// cdb-check:unique : Unique(0x[...]: (0x2a, 4321)) [Type: core::ptr::unique::Unique >] +// cdb-check: [] [Type: core::ptr::unique::Unique >] +// cdb-check: [0] : 0x2a [Type: unsigned __int64] +// cdb-check: [1] : 4321 [Type: int] + +#![feature(ptr_internals)] + +use std::mem::ManuallyDrop; +use std::pin::Pin; +use std::ptr::{NonNull, Unique}; + +fn main() { + let nonnull: NonNull<_> = (&12u32).into(); + + let manuallydrop = ManuallyDrop::new(12345i32); + + let mut s = "this".to_string(); + let pin = Pin::new(&mut s); + + let unique: Unique<_> = (&mut (42u64, 4321i32)).into(); + + zzz(); // #break +} + +fn zzz() { } diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 550cc66f38..9463f82c79 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -5,19 +5,22 @@ // cdb-command: g // Note: The natvis used to visualize niche-layout enums don't work correctly in cdb -// so the best we can do is to make sure we are generating the right debuginfo +// so the best we can do is to make sure we are generating the right debuginfo. +// Therefore, we use the `!` [format specifier](https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019#BKMK_Visual_Studio_2012_format_specifiers) +// to disable the natvis for a given expression. We also provide the `-r2` flag +// to expand the expression 2 levels. // cdb-command: dx -r2 a,! -// cdb-check:a,! [Type: enum$>, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$>, 2, 16, Some>::Some] +// cdb-check:a,! [Type: enum$ >, 2, 16, Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 2, 16, Some>::Some] // cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$>, 2, 16, Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$ >, 2, 16, Some>::Discriminant$] // cdb-command: dx -r2 b,! -// cdb-check:b,! [Type: enum$>, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$>, 2, 16, Some>::Some] +// cdb-check:b,! [Type: enum$ >, 2, 16, Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 2, 16, Some>::Some] // cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$>, 2, 16, Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$ >, 2, 16, Some>::Discriminant$] // cdb-command: dx -r2 c,! // cdb-check:c,! [Type: enum$] @@ -38,25 +41,41 @@ // cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$::Discriminant$] // cdb-command: dx -r2 f,! -// cdb-check:f,! [Type: enum$, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$, 1, [...], Some>::Some] +// cdb-check:f,! [Type: enum$ >, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 1, [...], Some>::Some] // cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$, 1, [...], Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$ >, 1, [...], Some>::Discriminant$] // cdb-command: dx -r2 g,! -// cdb-check:g,! [Type: enum$, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$, 1, [...], Some>::Some] +// cdb-check:g,! [Type: enum$ >, 1, [...], Some>] +// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 1, [...], Some>::Some] // cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$, 1, [...], Some>::Discriminant$] +// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$ >, 1, [...], Some>::Discriminant$] + +// cdb-command: dx -r2 h,! +// cdb-check:h,! : Some [Type: enum$ >] +// cdb-check: [+0x000] variant0 [Type: enum$ >::None] +// cdb-check: [+0x000] variant1 [Type: enum$ >::Some] +// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] +// cdb-check: [+0x000] discriminant : Some (0x1) [Type: core::option::Option] // cdb-command: dx h -// cdb-check:h : Some [Type: enum$>] -// cdb-check: [+0x000] variant$ : Some (0x1) [Type: core::option::Option] +// cdb-check:h : Some [Type: enum$ >] +// cdb-check: [] [Type: enum$ >] +// cdb-check: [variant] : Some // cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] +// cdb-command: dx -r2 i,! +// cdb-check:i,! : None [Type: enum$ >] +// cdb-check: [+0x000] variant0 [Type: enum$ >::None] +// cdb-check: [+0x000] variant1 [Type: enum$ >::Some] +// cdb-check: [+0x004] __0 : 0x[...] [Type: unsigned int] +// cdb-check: [+0x000] discriminant : None (0x0) [Type: core::option::Option] + // cdb-command: dx i -// cdb-check:i : None [Type: enum$>] -// cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option] +// cdb-check:i : None [Type: enum$ >] +// cdb-check: [] [Type: enum$ >] +// cdb-check: [variant] : None // cdb-command: dx j // cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] @@ -67,6 +86,11 @@ // cdb-check: [+0x000] __0 [Type: alloc::string::String] // cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$, 1, [...], Some>::Discriminant$] +// cdb-command: dx -r2 l,! +// cdb-check:l,! : $T2 [Type: enum$ >, Ok>] +// cdb-check: [+0x000] Ok [Type: enum$ >, Ok>::Ok] +// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] + pub enum CStyleEnum { Low = 2, High = 16, @@ -78,6 +102,8 @@ pub enum NicheLayoutEnum { Tag2, } +pub enum Empty { } + fn main() { let a = Some(CStyleEnum::Low); let b = Option::::None; @@ -90,6 +116,7 @@ fn main() { let i = Option::::None; let j = CStyleEnum::High; let k = Some("IAMA optional string!".to_string()); + let l = Result::::Ok(42); zzz(); // #break } diff --git a/src/test/debuginfo/mutable-locs.rs b/src/test/debuginfo/mutable-locs.rs new file mode 100644 index 0000000000..688483e43e --- /dev/null +++ b/src/test/debuginfo/mutable-locs.rs @@ -0,0 +1,104 @@ +// Testing the display of Cell, RefCell, and RefMut in cdb. + +// cdb-only +// min-cdb-version: 10.0.18317.1001 +// compile-flags:-g + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command:dx static_c,d +// cdb-check:static_c,d : 10 [Type: core::cell::Cell] +// cdb-check: [] [Type: core::cell::Cell] + +// cdb-command: dx static_c.value,d +// cdb-check:static_c.value,d : 10 [Type: core::cell::UnsafeCell] +// cdb-check: [] [Type: core::cell::UnsafeCell] + +// cdb-command: dx dynamic_c,d +// cdb-check:dynamic_c,d : 15 [Type: core::cell::RefCell] +// cdb-check: [] [Type: core::cell::RefCell] +// cdb-check: [Borrow state] : Unborrowed + +// cdb-command: dx dynamic_c.value,d +// cdb-check:dynamic_c.value,d : 15 [Type: core::cell::UnsafeCell] +// cdb-check: [] [Type: core::cell::UnsafeCell] + +// cdb-command: dx b,d +// cdb-check:b,d : 42 [Type: core::cell::RefMut] +// cdb-check: [] [Type: core::cell::RefMut] +// cdb-check: 42 [Type: int] + +// cdb-command: g + +// cdb-command: dx dynamic_c,d +// cdb-check:dynamic_c,d : 15 [Type: core::cell::RefCell] +// cdb-check: [] [Type: core::cell::RefCell] +// cdb-check: [Borrow state] : Immutably borrowed + +// cdb-command: dx r_borrow,d +// cdb-check:r_borrow,d : 15 [Type: core::cell::Ref] +// cdb-check: [] [Type: core::cell::Ref] +// cdb-check: 15 [Type: int] + +// cdb-command: g + +// cdb-command: dx dynamic_c,d +// cdb-check:dynamic_c,d : 15 [Type: core::cell::RefCell] +// cdb-check: [] [Type: core::cell::RefCell] +// cdb-check: [Borrow state] : Unborrowed + +// cdb-command: g + +// cdb-command: dx dynamic_c,d +// cdb-check:dynamic_c,d : 15 [Type: core::cell::RefCell] +// cdb-check: [] [Type: core::cell::RefCell] +// cdb-check: [Borrow state] : Mutably borrowed + +// cdb-command: dx r_borrow_mut,d +// cdb-check:r_borrow_mut,d : 15 [Type: core::cell::RefMut] +// cdb-check: [] [Type: core::cell::RefMut] +// cdb-check: 15 [Type: int] + +// cdb-command: g + +// cdb-command: dx dynamic_c,d +// cdb-check:dynamic_c,d : 15 [Type: core::cell::RefCell] +// cdb-check: [] [Type: core::cell::RefCell] +// cdb-check: [Borrow state] : Unborrowed + +#![allow(unused_variables)] + +use std::cell::{Cell, RefCell}; + +fn main() { + let static_c = Cell::new(5); + static_c.set(10); + + let dynamic_c = RefCell::new(5); + dynamic_c.replace(15); + + let dynamic_c_0 = RefCell::new(15); + let mut b = dynamic_c_0.borrow_mut(); + *b = 42; + + zzz(); // #break + + // Check that `RefCell`'s borrow state visualizes correctly + { + let r_borrow = dynamic_c.borrow(); + zzz(); // #break + } + + zzz(); // #break + + { + let r_borrow_mut = dynamic_c.borrow_mut(); + zzz(); // #break + } + + zzz(); // #break +} + +fn zzz() {()} diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs new file mode 100644 index 0000000000..40bea30f12 --- /dev/null +++ b/src/test/debuginfo/mutex.rs @@ -0,0 +1,38 @@ +// Testing the display of Mutex and MutexGuard in cdb. + +// cdb-only +// min-cdb-version: 10.0.21287.1005 +// compile-flags:-g + +// === CDB TESTS ================================================================================== +// +// cdb-command:g +// +// cdb-command:dx m,d +// cdb-check:m,d [Type: std::sync::mutex::Mutex] +// cdb-check: [...] inner [Type: std::sys_common::mutex::MovableMutex] +// cdb-check: [...] poison [Type: std::sync::poison::Flag] +// cdb-check: [...] data [Type: core::cell::UnsafeCell] + +// +// cdb-command:dx m.data,d +// cdb-check:m.data,d [Type: core::cell::UnsafeCell] +// cdb-check: [...] value : 0 [Type: int] + +// +// cdb-command:dx lock,d +// cdb-check:lock,d : Ok [Type: enum$, enum$ >, 0, 1, Poisoned> > >] +// cdb-check: [...] variant$ : Ok (0) [Type: core::result::Result] +// cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard] + +use std::sync::Mutex; + +#[allow(unused_variables)] +fn main() +{ + let m = Mutex::new(0); + let lock = m.try_lock(); + zzz(); // #break +} + +fn zzz() {} diff --git a/src/test/debuginfo/numeric-types.rs b/src/test/debuginfo/numeric-types.rs new file mode 100644 index 0000000000..2eae9239b6 --- /dev/null +++ b/src/test/debuginfo/numeric-types.rs @@ -0,0 +1,206 @@ +// only-cdb +// compile-flags:-g + +// Tests the visualizations for `NonZero{I,U}{8,16,32,64,128,size}`, `Wrapping` and +// `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`. + +// === CDB TESTS ================================================================================== +// cdb-command: g + +// cdb-command: dx nz_i8 +// cdb-check:nz_i8 : 11 [Type: core::num::nonzero::NonZeroI8] +// cdb-check: [] [Type: core::num::nonzero::NonZeroI8] + +// cdb-command: dx nz_i16 +// cdb-check:nz_i16 : 22 [Type: core::num::nonzero::NonZeroI16] +// cdb-check: [] [Type: core::num::nonzero::NonZeroI16] + +// cdb-command: dx nz_i32 +// cdb-check:nz_i32 : 33 [Type: core::num::nonzero::NonZeroI32] +// cdb-check: [] [Type: core::num::nonzero::NonZeroI32] + +// cdb-command: dx nz_i64 +// cdb-check:nz_i64 : 44 [Type: core::num::nonzero::NonZeroI64] +// cdb-check: [] [Type: core::num::nonzero::NonZeroI64] + +// 128-bit integers don't seem to work in CDB +// cdb-command: dx nz_i128 +// cdb-check: [] [Type: core::num::nonzero::NonZeroI128] + +// cdb-command: dx nz_isize +// cdb-check:nz_isize : 66 [Type: core::num::nonzero::NonZeroIsize] +// cdb-check: [] [Type: core::num::nonzero::NonZeroIsize] + +// cdb-command: dx nz_u8 +// cdb-check:nz_u8 : 0x4d [Type: core::num::nonzero::NonZeroU8] +// cdb-check: [] [Type: core::num::nonzero::NonZeroU8] + +// cdb-command: dx nz_u16 +// cdb-check:nz_u16 : 0x58 [Type: core::num::nonzero::NonZeroU16] +// cdb-check: [] [Type: core::num::nonzero::NonZeroU16] + +// cdb-command: dx nz_u32 +// cdb-check:nz_u32 : 0x63 [Type: core::num::nonzero::NonZeroU32] +// cdb-check: [] [Type: core::num::nonzero::NonZeroU32] + +// cdb-command: dx nz_u64 +// cdb-check:nz_u64 : 0x64 [Type: core::num::nonzero::NonZeroU64] +// cdb-check: [] [Type: core::num::nonzero::NonZeroU64] + +// 128-bit integers don't seem to work in CDB +// cdb-command: dx nz_u128 +// cdb-check: [] [Type: core::num::nonzero::NonZeroU128] + +// cdb-command: dx nz_usize +// cdb-check:nz_usize : 0x7a [Type: core::num::nonzero::NonZeroUsize] +// cdb-check: [] [Type: core::num::nonzero::NonZeroUsize] + +// cdb-command: dx w_i8 +// cdb-check:w_i8 : 10 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_i16 +// cdb-check:w_i16 : 20 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_i32 +// cdb-check:w_i32 : 30 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_i64 +// cdb-check:w_i64 : 40 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// 128-bit integers don't seem to work in CDB +// cdb-command: dx w_i128 +// cdb-check:w_i128 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_isize +// cdb-check:w_isize : 60 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_u8 +// cdb-check:w_u8 : 0x46 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_u16 +// cdb-check:w_u16 : 0x50 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_u32 +// cdb-check:w_u32 : 0x5a [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_u64 +// cdb-check:w_u64 : 0x64 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// 128-bit integers don't seem to work in CDB +// cdb-command: dx w_u128 +// cdb-check:w_u128 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx w_usize +// cdb-check:w_usize : 0x78 [Type: core::num::wrapping::Wrapping] +// cdb-check: [] [Type: core::num::wrapping::Wrapping] + +// cdb-command: dx a_bool_t +// cdb-check:a_bool_t : true [Type: core::sync::atomic::AtomicBool] +// cdb-check: [] [Type: core::sync::atomic::AtomicBool] + +// cdb-command: dx a_bool_f +// cdb-check:a_bool_f : false [Type: core::sync::atomic::AtomicBool] +// cdb-check: [] [Type: core::sync::atomic::AtomicBool] + +// cdb-command: dx a_i8 +// cdb-check:a_i8 : 2 [Type: core::sync::atomic::AtomicI8] +// cdb-check: [] [Type: core::sync::atomic::AtomicI8] + +// cdb-command: dx a_i16 +// cdb-check:a_i16 : 4 [Type: core::sync::atomic::AtomicI16] +// cdb-check: [] [Type: core::sync::atomic::AtomicI16] + +// cdb-command: dx a_i32 +// cdb-check:a_i32 : 8 [Type: core::sync::atomic::AtomicI32] +// cdb-check: [] [Type: core::sync::atomic::AtomicI32] + +// cdb-command: dx a_i64 +// cdb-check:a_i64 : 16 [Type: core::sync::atomic::AtomicI64] +// cdb-check: [] [Type: core::sync::atomic::AtomicI64] + +// cdb-command: dx a_isize +// cdb-check:a_isize : 32 [Type: core::sync::atomic::AtomicIsize] +// cdb-check: [] [Type: core::sync::atomic::AtomicIsize] + +// cdb-command: dx a_u8 +// cdb-check:a_u8 : 0x40 [Type: core::sync::atomic::AtomicU8] +// cdb-check: [] [Type: core::sync::atomic::AtomicU8] + +// cdb-command: dx a_u16 +// cdb-check:a_u16 : 0x80 [Type: core::sync::atomic::AtomicU16] +// cdb-check: [] [Type: core::sync::atomic::AtomicU16] + +// cdb-command: dx a_u32 +// cdb-check:a_u32 : 0x100 [Type: core::sync::atomic::AtomicU32] +// cdb-check: [] [Type: core::sync::atomic::AtomicU32] + +// cdb-command: dx a_u64 +// cdb-check:a_u64 : 0x200 [Type: core::sync::atomic::AtomicU64] +// cdb-check: [] [Type: core::sync::atomic::AtomicU64] + +// cdb-command: dx a_usize +// cdb-check:a_usize : 0x400 [Type: core::sync::atomic::AtomicUsize] +// cdb-check: [] [Type: core::sync::atomic::AtomicUsize] + +use std::num::*; +use std::sync::atomic::*; + +fn main() { + let nz_i8 = NonZeroI8::new(11).unwrap(); + let nz_i16 = NonZeroI16::new(22).unwrap(); + let nz_i32 = NonZeroI32::new(33).unwrap(); + let nz_i64 = NonZeroI64::new(44).unwrap(); + let nz_i128 = NonZeroI128::new(55).unwrap(); + let nz_isize = NonZeroIsize::new(66).unwrap(); + + let nz_u8 = NonZeroU8::new(77).unwrap(); + let nz_u16 = NonZeroU16::new(88).unwrap(); + let nz_u32 = NonZeroU32::new(99).unwrap(); + let nz_u64 = NonZeroU64::new(100).unwrap(); + let nz_u128 = NonZeroU128::new(111).unwrap(); + let nz_usize = NonZeroUsize::new(122).unwrap(); + + let w_i8 = Wrapping(10i8); + let w_i16 = Wrapping(20i16); + let w_i32 = Wrapping(30i32); + let w_i64 = Wrapping(40i64); + let w_i128 = Wrapping(50i128); + let w_isize = Wrapping(60isize); + + let w_u8 = Wrapping(70u8); + let w_u16 = Wrapping(80u16); + let w_u32 = Wrapping(90u32); + let w_u64 = Wrapping(100u64); + let w_u128 = Wrapping(110u128); + let w_usize = Wrapping(120usize); + + let a_bool_t = AtomicBool::new(true); + let a_bool_f = AtomicBool::new(false); + + let a_i8 = AtomicI8::new(2); + let a_i16 = AtomicI16::new(4); + let a_i32 = AtomicI32::new(8); + let a_i64 = AtomicI64::new(16); + let a_isize = AtomicIsize::new(32); + + let a_u8 = AtomicU8::new(64); + let a_u16 = AtomicU16::new(128); + let a_u32 = AtomicU32::new(256); + let a_u64 = AtomicU64::new(512); + let a_usize = AtomicUsize::new(1024); + + zzz(); // #break +} + +fn zzz() { } diff --git a/src/test/debuginfo/pretty-huge-vec.rs b/src/test/debuginfo/pretty-huge-vec.rs index 67155b4e9f..84f76ba4e6 100644 --- a/src/test/debuginfo/pretty-huge-vec.rs +++ b/src/test/debuginfo/pretty-huge-vec.rs @@ -13,7 +13,7 @@ // gdb-check:$1 = Vec(size=1000000000) = {[...]...} // gdb-command: print slice -// gdb-check:$2 = &[u8] {data_ptr: [...], length: 1000000000} +// gdb-check:$2 = &[u8](size=1000000000) = {[...]...} #![allow(unused_variables)] diff --git a/src/test/debuginfo/pretty-slices.rs b/src/test/debuginfo/pretty-slices.rs new file mode 100644 index 0000000000..6adc8757b7 --- /dev/null +++ b/src/test/debuginfo/pretty-slices.rs @@ -0,0 +1,46 @@ +// ignore-android: FIXME(#10381) +// ignore-windows +// compile-flags:-g + +// gdb-command: run + +// gdb-command: print slice +// gdbg-check: $1 = struct &[i32](size=3) = {0, 1, 2} +// gdbr-check: $1 = &[i32](size=3) = {0, 1, 2} + +// gdb-command: print mut_slice +// gdbg-check: $2 = struct &mut [i32](size=4) = {2, 3, 5, 7} +// gdbr-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7} + +// gdb-command: print str_slice +// gdb-check: $3 = "string slice" + +// gdb-command: print mut_str_slice +// gdb-check: $4 = "mutable string slice" + +// lldb-command: run + +// lldb-command: print slice +// lldb-check: (&[i32]) $0 = size=3 { [0] = 0 [1] = 1 [2] = 2 } + +// lldb-command: print mut_slice +// lldb-check: (&mut [i32]) $1 = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 } + +// lldb-command: print str_slice +// lldb-check: (&str) $2 = "string slice" { data_ptr = [...] length = 12 } + +// lldb-command: print mut_str_slice +// lldb-check: (&mut str) $3 = "mutable string slice" { data_ptr = [...] length = 20 } + +fn b() {} + +fn main() { + let slice: &[i32] = &[0, 1, 2]; + let mut_slice: &mut [i32] = &mut [2, 3, 5, 7]; + + let str_slice: &str = "string slice"; + let mut mut_str_slice_buffer = String::from("mutable string slice"); + let mut_str_slice: &mut str = mut_str_slice_buffer.as_mut_str(); + + b(); // #break +} diff --git a/src/test/debuginfo/pretty-std-collections-hash.rs b/src/test/debuginfo/pretty-std-collections-hash.rs index 7115aec104..40bde86069 100644 --- a/src/test/debuginfo/pretty-std-collections-hash.rs +++ b/src/test/debuginfo/pretty-std-collections-hash.rs @@ -10,7 +10,7 @@ // cdb-command: g // cdb-command: dx hash_set,d -// cdb-check:hash_set,d [...] : { len=15 } [Type: [...]::HashSet] +// cdb-check:hash_set,d [...] : { len=15 } [Type: [...]::HashSet] // cdb-check: [len] : 15 [Type: [...]] // cdb-check: [capacity] : [...] // cdb-check: [[...]] [...] : 0 [Type: u64] @@ -44,7 +44,7 @@ // cdb-check: [[...]] [...] : 14 [Type: u64] // cdb-command: dx hash_map,d -// cdb-check:hash_map,d [...] : { len=15 } [Type: [...]::HashMap] +// cdb-check:hash_map,d [...] : { len=15 } [Type: [...]::HashMap] // cdb-check: [len] : 15 [Type: [...]] // cdb-check: [capacity] : [...] // cdb-check: ["0x0"] : 0 [Type: unsigned __int64] @@ -77,6 +77,8 @@ // cdb-command: dx hash_map,d // cdb-check: ["0xe"] : 14 [Type: unsigned __int64] +// cdb-command: dx x + #![allow(unused_variables)] use std::collections::HashSet; use std::collections::HashMap; @@ -95,6 +97,9 @@ fn main() { hash_map.insert(i as u64, i as u64); } + let x = &(123u64, 456u64); + let string = "awefawefawe".to_string(); + zzz(); // #break } diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 68e73b5f38..a190a29eec 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,10 +1,10 @@ // ignore-freebsd: gdb package too new // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) -// ignore-tidy-linelength // compile-flags:-g // min-gdb-version: 7.7 // min-lldb-version: 310 +// min-cdb-version: 10.0.18317.1001 // === GDB TESTS =================================================================================== @@ -71,11 +71,15 @@ // cdb-command: g // cdb-command: dx slice,d -// cdb-check:slice,d [...] -// NOTE: While slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1 +// cdb-check:slice,d : { len=4 } [Type: slice$] +// cdb-check: [len] : 4 [Type: [...]] +// cdb-check: [0] : 0 [Type: int] +// cdb-check: [1] : 1 [Type: int] +// cdb-check: [2] : 2 [Type: int] +// cdb-check: [3] : 3 [Type: int] // cdb-command: dx vec,d -// cdb-check:vec,d [...] : { len=4 } [Type: [...]::Vec] +// cdb-check:vec,d [...] : { len=4 } [Type: [...]::Vec] // cdb-check: [len] : 4 [Type: [...]] // cdb-check: [capacity] : [...] [Type: [...]] // cdb-check: [0] : 4 [Type: unsigned __int64] @@ -84,8 +88,7 @@ // cdb-check: [3] : 7 [Type: unsigned __int64] // cdb-command: dx str_slice -// cdb-check:str_slice [...] -// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB +// cdb-check:str_slice : "IAMA string slice!" [Type: str] // cdb-command: dx string // cdb-check:string : "IAMA string!" [Type: [...]::String] @@ -108,20 +111,43 @@ // cdb-check: [11] : 33 '!' [Type: char] // cdb-command: dx os_string -// cdb-check:os_string [Type: [...]::OsString] -// NOTE: OsString doesn't have a .natvis entry yet. +// cdb-check:os_string : "IAMA OS string 😃" [Type: std::ffi::os_str::OsString] +// cdb-check: [] [Type: std::ffi::os_str::OsString] +// cdb-check: [chars] : "IAMA OS string 😃" // cdb-command: dx some -// cdb-check:some : Some [Type: enum$>] +// cdb-check:some : Some [Type: enum$ >] +// cdb-check: [] [Type: enum$ >] +// cdb-check: [variant] : Some +// cdb-check: [+0x002] __0 : 8 [Type: short] + // cdb-command: dx none -// cdb-check:none : None [Type: enum$>] +// cdb-check:none : None [Type: enum$ >] +// cdb-check: [] [Type: enum$ >] +// cdb-check: [variant] : None + // cdb-command: dx some_string +// NOTE: cdb fails to interpret debug info of Option enums on i686. // cdb-check:some_string [Type: enum$, 1, [...], Some>] +// cdb-command: dx linkedlist +// cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList] +// cdb-check: [] [Type: alloc::collections::linked_list::LinkedList] +// cdb-check: [0x0] : 128 [Type: int] +// cdb-check: [0x1] : 42 [Type: int] + +// cdb-command: dx vecdeque +// cdb-check:vecdeque : { len=0x2 } [Type: alloc::collections::vec_deque::VecDeque] +// cdb-check: [] [Type: alloc::collections::vec_deque::VecDeque] +// cdb-check: [len] : 0x2 +// cdb-check: [capacity] : 0x8 [Type: unsigned [...]] +// cdb-check: [0x0] : 90 [Type: int] +// cdb-check: [0x1] : 20 [Type: int] + #![allow(unused_variables)] +use std::collections::{LinkedList, VecDeque}; use std::ffi::OsString; - fn main() { // &[] @@ -145,6 +171,16 @@ fn main() { let some_string = Some("IAMA optional string!".to_owned()); + // LinkedList + let mut linkedlist = LinkedList::new(); + linkedlist.push_back(42); + linkedlist.push_front(128); + + // VecDeque + let mut vecdeque = VecDeque::new(); + vecdeque.push_back(20); + vecdeque.push_front(90); + zzz(); // #break } diff --git a/src/test/debuginfo/range-types.rs b/src/test/debuginfo/range-types.rs new file mode 100644 index 0000000000..7362a50a03 --- /dev/null +++ b/src/test/debuginfo/range-types.rs @@ -0,0 +1,49 @@ +// Testing the display of range types in cdb. + +// cdb-only +// min-cdb-version: 10.0.18317.1001 +// compile-flags:-g + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx r1,d +// cdb-check:r1,d : (3..5) [Type: core::ops::range::Range] +// cdb-check: [] [Type: core::ops::range::Range] + +// cdb-command: dx r2,d +// cdb-check:r2,d : (2..) [Type: core::ops::range::RangeFrom] +// cdb-check: [] [Type: core::ops::range::RangeFrom] + +// cdb-command: dx r3,d +// cdb-check:r3,d : (1..=4) [Type: core::ops::range::RangeInclusive] +// cdb-check: [] [Type: core::ops::range::RangeInclusive] + +// cdb-command: dx r4,d +// cdb-check:r4,d : (..10) [Type: core::ops::range::RangeTo] +// cdb-check: [] [Type: core::ops::range::RangeTo] + +// cdb-command: dx r5,d +// cdb-check:r5,d : (..=3) [Type: core::ops::range::RangeToInclusive] +// cdb-check: [] [Type: core::ops::range::RangeToInclusive] + +// cdb-command: dx r6,d +// cdb-check:r6,d [Type: core::ops::range::RangeFull] + +#[allow(unused_variables)] + +use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeToInclusive}; + +fn main() +{ + let r1 = (3..5); + let r2 = (2..); + let r3 = (1..=4); + let r4 = (..10); + let r5 = (..=3); + let r6 = (..); + zzz(); // #break +} + +fn zzz() { () } diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs index 87bc79ea79..55cddf7c6c 100644 --- a/src/test/debuginfo/rc_arc.rs +++ b/src/test/debuginfo/rc_arc.rs @@ -1,7 +1,8 @@ -// ignore-windows pretty-printers are not loaded +// pretty-printers are not loaded // compile-flags:-g // min-gdb-version: 8.1 +// min-cdb-version: 10.0.18317.1001 // === GDB TESTS ================================================================================== @@ -22,6 +23,46 @@ // lldb-command:print a // lldb-check:[...]$1 = strong=2, weak=1 { data = 42 } +// === CDB TESTS ================================================================================== + +// cdb-command:g + +// cdb-command:dx r,d +// cdb-check:r,d : 42 [Type: alloc::rc::Rc] +// cdb-check: [] [Type: alloc::rc::Rc] +// cdb-check: [Reference count] : 2 [Type: core::cell::Cell] +// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] + +// cdb-command:dx r1,d +// cdb-check:r1,d : 42 [Type: alloc::rc::Rc] +// cdb-check: [] [Type: alloc::rc::Rc] +// cdb-check: [Reference count] : 2 [Type: core::cell::Cell] +// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] + +// cdb-command:dx w1,d +// cdb-check:w1,d : 42 [Type: alloc::rc::Weak] +// cdb-check: [] [Type: alloc::rc::Weak] +// cdb-check: [Reference count] : 2 [Type: core::cell::Cell] +// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] + +// cdb-command:dx a,d +// cdb-check:a,d : 42 [Type: alloc::sync::Arc] +// cdb-check: [] [Type: alloc::sync::Arc] +// cdb-check: [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize] +// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] + +// cdb-command:dx a1,d +// cdb-check:a1,d : 42 [Type: alloc::sync::Arc] +// cdb-check: [] [Type: alloc::sync::Arc] +// cdb-check: [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize] +// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] + +// cdb-command:dx w2,d +// cdb-check:w2,d : 42 [Type: alloc::sync::Weak] +// cdb-check: [] [Type: alloc::sync::Weak] +// cdb-check: [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize] +// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize] + use std::rc::Rc; use std::sync::Arc; diff --git a/src/test/debuginfo/result-types.rs b/src/test/debuginfo/result-types.rs new file mode 100644 index 0000000000..c0d905a6ac --- /dev/null +++ b/src/test/debuginfo/result-types.rs @@ -0,0 +1,28 @@ +// cdb-only +// min-cdb-version: 10.0.18317.1001 +// compile-flags:-g + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx x,d +// cdb-check:x,d : Ok [Type: enum$ >] +// cdb-check: [...] __0 : -3 [Type: int] + +// cdb-command: dx y +// cdb-check:y : Err [Type: enum$ >] +// cdb-check: [...] __0 : "Some error message" [Type: str] + +fn main() +{ + let x: Result = Ok(-3); + assert_eq!(x.is_ok(), true); + + let y: Result = Err("Some error message"); + assert_eq!(y.is_ok(), false); + + zzz(); // #break. +} + +fn zzz() { () } diff --git a/src/test/debuginfo/rwlock-read.rs b/src/test/debuginfo/rwlock-read.rs new file mode 100644 index 0000000000..e1c10a4d37 --- /dev/null +++ b/src/test/debuginfo/rwlock-read.rs @@ -0,0 +1,35 @@ +// Testing the display of RwLock and RwLockReadGuard in cdb. + +// cdb-only +// min-cdb-version: 10.0.18317.1001 +// compile-flags:-g + +// === CDB TESTS ================================================================================== +// +// cdb-command:g +// +// cdb-command:dx l +// cdb-check:l [Type: std::sync::rwlock::RwLock] +// cdb-check: [...] poison [Type: std::sync::poison::Flag] +// cdb-check: [...] data : 0 [Type: core::cell::UnsafeCell] +// +// cdb-command:dx r +// cdb-check:r [Type: std::sync::rwlock::RwLockReadGuard] +// cdb-check: [...] lock : [...] [Type: std::sync::rwlock::RwLock *] +// +// cdb-command:dx r.lock->data,d +// cdb-check:r.lock->data,d : 0 [Type: core::cell::UnsafeCell] +// cdb-check: [] [Type: core::cell::UnsafeCell] + +#[allow(unused_variables)] + +use std::sync::RwLock; + +fn main() +{ + let l = RwLock::new(0); + let r = l.read().unwrap(); + zzz(); // #break +} + +fn zzz() {} diff --git a/src/test/debuginfo/rwlock-write.rs b/src/test/debuginfo/rwlock-write.rs new file mode 100644 index 0000000000..8decf54c17 --- /dev/null +++ b/src/test/debuginfo/rwlock-write.rs @@ -0,0 +1,27 @@ +// Testing the display of RwLockWriteGuard. + +// cdb-only +// min-cdb-version: 10.0.18317.1001 +// compile-flags:-g + +// === CDB TESTS ================================================================================== +// +// cdb-command:g +// +// cdb-command:dx w +// cdb-check:w [Type: std::sync::rwlock::RwLockWriteGuard] +// cdb-check: [...] lock : [...] [Type: std::sync::rwlock::RwLock *] +// cdb-check: [...] poison [Type: std::sync::poison::Guard] + +#[allow(unused_variables)] + +use std::sync::RwLock; + +fn main() +{ + let l = RwLock::new(0); + let w = l.write().unwrap(); + zzz(); // #break +} + +fn zzz() {} diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index b7fcfeef09..0807cfedce 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -129,38 +129,38 @@ // cdb-command: g // cdb-command:dx noPadding8,d -// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple] +// cdb-check:noPadding8,d [...]: (-100, 100) [Type: tuple$] // cdb-check:[...][0] : -100 [Type: [...]] // cdb-check:[...][1] : 100 [Type: [...]] // cdb-command:dx noPadding16,d -// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple] +// cdb-check:noPadding16,d [...]: (0, 1, 2) [Type: tuple$] // cdb-check:[...][0] : 0 [Type: [...]] // cdb-check:[...][1] : 1 [Type: [...]] // cdb-check:[...][2] : 2 [Type: [...]] // cdb-command:dx noPadding32,d -// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple] +// cdb-check:noPadding32,d [...]: (3, 4.5[...], 5) [Type: tuple$] // cdb-check:[...][0] : 3 [Type: [...]] // cdb-check:[...][1] : 4.5[...] [Type: [...]] // cdb-check:[...][2] : 5 [Type: [...]] // cdb-command:dx noPadding64,d -// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple] +// cdb-check:noPadding64,d [...]: (6, 7.5[...], 8) [Type: tuple$] // cdb-check:[...][0] : 6 [Type: [...]] // cdb-check:[...][1] : 7.500000 [Type: [...]] // cdb-check:[...][2] : 8 [Type: [...]] // cdb-command:dx internalPadding1,d -// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple] +// cdb-check:internalPadding1,d [...]: (9, 10) [Type: tuple$] // cdb-check:[...][0] : 9 [Type: short] // cdb-check:[...][1] : 10 [Type: int] // cdb-command:dx internalPadding2,d -// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple] +// cdb-check:internalPadding2,d [...]: (11, 12, 13, 14) [Type: tuple$] // cdb-check:[...][0] : 11 [Type: [...]] // cdb-check:[...][1] : 12 [Type: [...]] // cdb-check:[...][2] : 13 [Type: [...]] // cdb-check:[...][3] : 14 [Type: [...]] // cdb-command:dx paddingAtEnd,d -// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple] +// cdb-check:paddingAtEnd,d [...]: (15, 16) [Type: tuple$] // cdb-check:[...][0] : 15 [Type: [...]] // cdb-check:[...][1] : 16 [Type: [...]] diff --git a/src/test/debuginfo/thread.rs b/src/test/debuginfo/thread.rs new file mode 100644 index 0000000000..531c37a342 --- /dev/null +++ b/src/test/debuginfo/thread.rs @@ -0,0 +1,31 @@ +// Testing the the display of JoinHandle and Thread in cdb. + +// cdb-only +// min-cdb-version: 10.0.18317.1001 +// compile-flags:-g + +// === CDB TESTS ================================================================================== +// +// cdb-command:g +// +// cdb-command:dx join_handle,d +// cdb-check:join_handle,d [Type: std::thread::JoinHandle >] +// cdb-check: [...] __0 [Type: std::thread::JoinInner >] +// +// cdb-command:dx t,d +// cdb-check:t,d : [...] [Type: std::thread::Thread *] +// cdb-check: [...] inner : {...} [Type: alloc::sync::Arc] + +use std::thread; + +#[allow(unused_variables)] +fn main() +{ + let join_handle = thread::spawn(|| { + println!("Initialize a thread"); + }); + let t = join_handle.thread(); + zzz(); // #break +} + +fn zzz() {} diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index 0447d8e9dd..578db74e9e 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -65,64 +65,64 @@ // cdb-command: g // cdb-command:dx no_padding1,d -// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple, u32, u32>] -// cdb-check:[...][0] : (0, 1) [Type: tuple] +// cdb-check:no_padding1,d [...]: ((0, 1), 2, 3) [Type: tuple$,u32,u32>] +// cdb-check:[...][0] : (0, 1) [Type: tuple$] // cdb-check:[...][1] : 2 [Type: [...]] // cdb-check:[...][2] : 3 [Type: [...]] // cdb-command:dx no_padding1.__0,d -// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple] +// cdb-check:no_padding1.__0,d [...]: (0, 1) [Type: tuple$] // cdb-check:[...][0] : 0 [Type: [...]] // cdb-check:[...][1] : 1 [Type: [...]] // cdb-command:dx no_padding2,d -// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple, u32>] +// cdb-check:no_padding2,d [...]: (4, (5, 6), 7) [Type: tuple$,u32>] // cdb-check:[...][0] : 4 [Type: [...]] -// cdb-check:[...][1] : (5, 6) [Type: tuple] +// cdb-check:[...][1] : (5, 6) [Type: tuple$] // cdb-check:[...][2] : 7 [Type: [...]] // cdb-command:dx no_padding2.__1,d -// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple] +// cdb-check:no_padding2.__1,d [...]: (5, 6) [Type: tuple$] // cdb-check:[...][0] : 5 [Type: [...]] // cdb-check:[...][1] : 6 [Type: [...]] // cdb-command:dx no_padding3,d -// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple>] +// cdb-check:no_padding3,d [...]: (8, 9, (10, 11)) [Type: tuple$ >] // cdb-check:[...][0] : 8 [Type: [...]] // cdb-check:[...][1] : 9 [Type: [...]] -// cdb-check:[...][2] : (10, 11) [Type: tuple] +// cdb-check:[...][2] : (10, 11) [Type: tuple$] // cdb-command:dx no_padding3.__2,d -// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple] +// cdb-check:no_padding3.__2,d [...]: (10, 11) [Type: tuple$] // cdb-check:[...][0] : 10 [Type: [...]] // cdb-check:[...][1] : 11 [Type: [...]] // cdb-command:dx internal_padding1,d -// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple>] +// cdb-check:internal_padding1,d [...]: (12, (13, 14)) [Type: tuple$ >] // cdb-check:[...][0] : 12 [Type: [...]] -// cdb-check:[...][1] : (13, 14) [Type: tuple] +// cdb-check:[...][1] : (13, 14) [Type: tuple$] // cdb-command:dx internal_padding1.__1,d -// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple] +// cdb-check:internal_padding1.__1,d [...]: (13, 14) [Type: tuple$] // cdb-check:[...][0] : 13 [Type: [...]] // cdb-check:[...][1] : 14 [Type: [...]] // cdb-command:dx internal_padding2,d -// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple>] +// cdb-check:internal_padding2,d [...]: (15, (16, 17)) [Type: tuple$ >] // cdb-check:[...][0] : 15 [Type: [...]] -// cdb-check:[...][1] : (16, 17) [Type: tuple] +// cdb-check:[...][1] : (16, 17) [Type: tuple$] // cdb-command:dx internal_padding2.__1,d -// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple] +// cdb-check:internal_padding2.__1,d [...]: (16, 17) [Type: tuple$] // cdb-check:[...][0] : 16 [Type: [...]] // cdb-check:[...][1] : 17 [Type: [...]] // cdb-command:dx padding_at_end1,d -// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple>] +// cdb-check:padding_at_end1,d [...]: (18, (19, 20)) [Type: tuple$ >] // cdb-check:[...][0] : 18 [Type: [...]] -// cdb-check:[...][1] : (19, 20) [Type: tuple] +// cdb-check:[...][1] : (19, 20) [Type: tuple$] // cdb-command:dx padding_at_end1.__1,d -// cdb-check:padding_at_end1.__1,d [...][Type: tuple] +// cdb-check:padding_at_end1.__1,d [...][Type: tuple$] // cdb-check:[...][0] : 19 [Type: [...]] // cdb-check:[...][1] : 20 [Type: [...]] // cdb-command:dx padding_at_end2,d -// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple, i32>] -// cdb-check:[...][0] : (21, 22) [Type: tuple] +// cdb-check:padding_at_end2,d [...]: ((21, 22), 23) [Type: tuple$,i32>] +// cdb-check:[...][0] : (21, 22) [Type: tuple$] // cdb-check:[...][1] : 23 [Type: [...]] // cdb-command:dx padding_at_end2.__0,d -// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple] +// cdb-check:padding_at_end2.__0,d [...]: (21, 22) [Type: tuple$] // cdb-check:[...][0] : 21 [Type: [...]] // cdb-check:[...][1] : 22 [Type: [...]] diff --git a/src/test/debuginfo/type-names.cdb.js b/src/test/debuginfo/type-names.cdb.js new file mode 100644 index 0000000000..8f8b20bfae --- /dev/null +++ b/src/test/debuginfo/type-names.cdb.js @@ -0,0 +1,17 @@ +// Helper functions for running the type-names.rs test under CDB + +// CDB exposes an "object model" via JavaScript that allows you to inspect debugging info - in this +// case we want to ask the object model for the return and parameter types for a local variable +// that is a function pointer to make sure that we are emitting the function pointer type in such a +// way that CDB understands how to parse it. + +"use strict"; + +function getFunctionDetails(name) +{ + var localVariable = host.currentThread.Stack.Frames[0].LocalVariables[name]; + var functionPointerType = localVariable.targetType.genericArguments[0]; + var functionType = functionPointerType.baseType; + host.diagnostics.debugLog("Return Type: ", functionType.functionReturnType, "\n"); + host.diagnostics.debugLog("Parameter Types: ", functionType.functionParameterTypes, "\n"); +} diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index cc4a4476d1..3497f0afb2 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -1,208 +1,272 @@ // ignore-lldb -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 + +// GDB changed the way that it formatted Foreign types +// min-gdb-version: 9.2 // compile-flags:-g +// === GDB TESTS =================================================================================== + // gdb-command:run // STRUCTS // gdb-command:whatis simple_struct -// gdbg-check:type = struct Struct1 -// gdbr-check:type = type_names::Struct1 +// gdb-check:type = type_names::Struct1 // gdb-command:whatis generic_struct1 -// gdbg-check:type = struct GenericStruct -// gdbr-check:type = type_names::GenericStruct +// gdb-check:type = type_names::GenericStruct // gdb-command:whatis generic_struct2 -// gdbg-check:type = struct GenericStruct usize> -// gdbr-check:type = type_names::GenericStruct usize> +// gdb-check:type = type_names::GenericStruct usize> // gdb-command:whatis mod_struct -// gdbg-check:type = struct Struct2 -// gdbr-check:type = type_names::mod1::Struct2 +// gdb-check:type = type_names::mod1::Struct2 // ENUMS // gdb-command:whatis simple_enum_1 -// gdbg-check:type = union Enum1 -// gdbr-check:type = type_names::Enum1 +// gdb-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_2 -// gdbg-check:type = union Enum1 -// gdbr-check:type = type_names::Enum1 +// gdb-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_3 -// gdbg-check:type = union Enum2 -// gdbr-check:type = type_names::mod1::Enum2 +// gdb-check:type = type_names::mod1::Enum2 // gdb-command:whatis generic_enum_1 -// gdbg-check:type = union Enum3 -// gdbr-check:type = type_names::mod1::mod2::Enum3 +// gdb-check:type = type_names::mod1::mod2::Enum3 // gdb-command:whatis generic_enum_2 -// gdbg-check:type = union Enum3 -// gdbr-check:type = type_names::mod1::mod2::Enum3 +// gdb-check:type = type_names::mod1::mod2::Enum3 // TUPLES // gdb-command:whatis tuple1 -// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) -// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdb-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) // gdb-command:whatis tuple2 -// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) -// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdb-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) // BOX // gdb-command:whatis box1 -// gdbg-check:type = struct (alloc::boxed::Box, i32) -// gdbr-check:type = (alloc::boxed::Box, i32) +// gdb-check:type = (alloc::boxed::Box, i32) // gdb-command:whatis box2 -// gdbg-check:type = struct (alloc::boxed::Box>, i32) -// gdbr-check:type = (alloc::boxed::Box>, i32) +// gdb-check:type = (alloc::boxed::Box, alloc::alloc::Global>, i32) // REFERENCES // gdb-command:whatis ref1 -// gdbg-check:type = struct (&type_names::Struct1, i32) -// gdbr-check:type = (&type_names::Struct1, i32) +// gdb-check:type = (&type_names::Struct1, i32) // gdb-command:whatis ref2 -// gdbg-check:type = struct (&type_names::GenericStruct, i32) -// gdbr-check:type = (&type_names::GenericStruct, i32) +// gdb-check:type = (&type_names::GenericStruct, i32) // gdb-command:whatis mut_ref1 -// gdbg-check:type = struct (&mut type_names::Struct1, i32) -// gdbr-check:type = (&mut type_names::Struct1, i32) +// gdb-check:type = (&mut type_names::Struct1, i32) // gdb-command:whatis mut_ref2 -// gdbg-check:type = struct (&mut type_names::GenericStruct, i32) -// gdbr-check:type = (&mut type_names::GenericStruct, i32) +// gdb-check:type = (&mut type_names::GenericStruct, i32) // RAW POINTERS // gdb-command:whatis mut_ptr1 -// gdbg-check:type = struct (*mut type_names::Struct1, isize) -// gdbr-check:type = (*mut type_names::Struct1, isize) +// gdb-check:type = (*mut type_names::Struct1, isize) // gdb-command:whatis mut_ptr2 -// gdbg-check:type = struct (*mut isize, isize) -// gdbr-check:type = (*mut isize, isize) +// gdb-check:type = (*mut isize, isize) // gdb-command:whatis mut_ptr3 -// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) -// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3, isize) +// gdb-check:type = (*mut type_names::mod1::mod2::Enum3, isize) // gdb-command:whatis const_ptr1 -// gdbg-check:type = struct (*const type_names::Struct1, isize) -// gdbr-check:type = (*const type_names::Struct1, isize) +// gdb-check:type = (*const type_names::Struct1, isize) // gdb-command:whatis const_ptr2 -// gdbg-check:type = struct (*const isize, isize) -// gdbr-check:type = (*const isize, isize) +// gdb-check:type = (*const isize, isize) // gdb-command:whatis const_ptr3 -// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) -// gdbr-check:type = (*const type_names::mod1::mod2::Enum3, isize) +// gdb-check:type = (*const type_names::mod1::mod2::Enum3, isize) // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdbg-check:type = struct ([type_names::Struct1; 3], i16) -// gdbr-check:type = ([type_names::Struct1; 3], i16) +// gdb-check:type = ([type_names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 -// gdbg-check:type = struct ([usize; 3], i16) -// gdbr-check:type = ([usize; 3], i16) +// gdb-check:type = ([usize; 3], i16) // gdb-command:whatis slice1 -// gdbg-check:type = struct &[usize] -// gdbr-check:type = &[usize] +// gdb-check:type = &[usize] // gdb-command:whatis slice2 -// gdbg-check:type = struct &[type_names::mod1::Enum2] -// gdbr-check:type = &[type_names::mod1::Enum2] +// gdb-check:type = &[type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait -// gdbg-check:type = struct Box -// gdbr-check:type = type_names::Box +// gdb-check:type = alloc::boxed::Box // gdb-command:whatis ref_trait -// gdbg-check:type = struct &Trait1 -// gdbr-check:type = type_names::&Trait1 +// gdb-check:type = &dyn type_names::Trait1 // gdb-command:whatis mut_ref_trait -// gdbg-check:type = struct &mut Trait1 -// gdbr-check:type = type_names::&mut Trait1 +// gdb-check:type = &mut dyn type_names::Trait1 // gdb-command:whatis generic_box_trait -// gdbg-check:type = struct Box> -// gdbr-check:type = type_names::Box> +// gdb-check:type = alloc::boxed::Box, alloc::alloc::Global> // gdb-command:whatis generic_ref_trait -// gdbg-check:type = struct &Trait2 -// gdbr-check:type = type_names::&Trait2 +// gdb-check:type = &dyn type_names::Trait2 // gdb-command:whatis generic_mut_ref_trait -// gdbg-check:type = struct &mut Trait2> -// gdbr-check:type = type_names::&mut Trait2> +// gdb-check:type = &mut dyn type_names::Trait2> + +// gdb-command:whatis no_principal_trait +// gdb-check:type = alloc::boxed::Box<(dyn core::marker::Send + core::marker::Sync), alloc::alloc::Global> + +// gdb-command:whatis has_associated_type_trait +// gdb-check:type = &(dyn type_names::Trait3 + core::marker::Send) + // BARE FUNCTIONS // gdb-command:whatis rust_fn -// gdbg-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) -// gdbr-check:type = (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdb-check:type = (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) // gdb-command:whatis extern_c_fn -// gdbg-check:type = struct (extern "C" fn(isize), usize) -// gdbr-check:type = (extern "C" fn(isize), usize) +// gdb-check:type = (extern "C" fn(isize), usize) // gdb-command:whatis unsafe_fn -// gdbg-check:type = struct (unsafe fn(core::result::Result), usize) -// gdbr-check:type = (unsafe fn(core::result::Result), usize) - -// gdb-command:whatis extern_stdcall_fn -// gdbg-check:type = struct (extern "stdcall" fn(), usize) -// gdbr-check:type = (extern "stdcall" fn(), usize) +// gdb-check:type = (unsafe fn(core::result::Result), usize) // gdb-command:whatis rust_fn_with_return_value -// gdbg-check:type = struct (fn(f64) -> usize, usize) -// gdbr-check:type = (fn(f64) -> usize, usize) +// gdb-check:type = (fn(f64) -> usize, usize) // gdb-command:whatis extern_c_fn_with_return_value -// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) -// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize) +// gdb-check:type = (extern "C" fn() -> type_names::Struct1, usize) // gdb-command:whatis unsafe_fn_with_return_value -// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) -// gdbr-check:type = (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) - -// gdb-command:whatis extern_stdcall_fn_with_return_value -// gdbg-check:type = struct (extern "stdcall" fn(alloc::boxed::Box) -> usize, usize) -// gdbr-check:type = (extern "stdcall" fn(alloc::boxed::Box) -> usize, usize) +// gdb-check:type = (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) // gdb-command:whatis generic_function_int -// gdbg-check:type = struct (fn(isize) -> isize, usize) -// gdbr-check:type = (fn(isize) -> isize, usize) +// gdb-check:type = (fn(isize) -> isize, usize) // gdb-command:whatis generic_function_struct3 -// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) -// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdb-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) // gdb-command:whatis variadic_function -// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) -// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdb-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) // CLOSURES // gdb-command:whatis closure1 -// gdbg-check:type = struct (closure, usize) -// gdbr-check:type = (closure, usize) +// gdb-check:type = (type_names::main::{closure#0}, usize) // gdb-command:whatis closure2 -// gdbg-check:type = struct (closure, usize) -// gdbr-check:type = (closure, usize) +// gdb-check:type = (type_names::main::{closure#1}, usize) + +// FOREIGN TYPES +// gdb-command:whatis foreign1 +// gdb-check:type = *mut ForeignType1 + +// gdb-command:whatis foreign2 +// gdb-check:type = *mut ForeignType2 + +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// STRUCTS +// 0-sized structs appear to be optimized away in some cases, so only check the structs that do +// actually appear. +// cdb-command:dv /t *_struct +// cdb-check:struct type_names::GenericStruct,f64> mut_generic_struct = [...] + +// ENUMS +// cdb-command:dv /t *_enum_* +// cdb-check:union enum$ simple_enum_1 = [...] +// cdb-check:union enum$ simple_enum_2 = [...] +// cdb-check:type_names::mod1::Enum2 simple_enum_3 = [...] +// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_1 = [...] +// cdb-check:type_names::mod1::mod2::Enum3 generic_enum_2 = [...] + +// TUPLES +// cdb-command:dv /t tuple* +// cdb-check:struct tuple$ > > tuple1 = [...] +// cdb-check:struct tuple$,enum$,char> tuple2 = [...] + +// BOX +// cdb-command:dv /t box* +// cdb-check:struct tuple$,i32> box1 = [...] +// cdb-check:struct tuple$ >,alloc::alloc::Global>,i32> box2 = [...] + +// REFERENCES +// cdb-command:dv /t *ref* +// cdb-check:struct tuple$,i32> ref1 = [...] +// cdb-check:struct tuple$ >,i32> ref2 = [...] +// cdb-check:struct tuple$,i32> mut_ref1 = [...] +// cdb-check:struct tuple$,f64> >,i32> mut_ref2 = [...] + +// RAW POINTERS +// cdb-command:dv /t *_ptr* +// cdb-check:struct tuple$,isize> mut_ptr1 = [...] +// cdb-check:struct tuple$,isize> mut_ptr2 = [...] +// cdb-check:struct tuple$ > >,isize> mut_ptr3 = [...] +// cdb-check:struct tuple$,isize> const_ptr1 = [...] +// cdb-check:struct tuple$,isize> const_ptr2 = [...] +// cdb-check:struct tuple$ > >,isize> const_ptr3 = [...] + +// VECTORS +// cdb-command:dv /t *vec* +// cdb-check:struct tuple$,i16> fixed_size_vec1 = [...] +// cdb-check:struct tuple$,i16> fixed_size_vec2 = [...] +// cdb-check:struct alloc::vec::Vec vec1 = [...] +// cdb-check:struct alloc::vec::Vec,alloc::alloc::Global> vec2 = [...] +// cdb-command:dv /t slice* +// cdb-check:struct slice$ slice1 = [...] +// cdb-check:struct slice$ > slice2 = [...] + +// TRAITS +// cdb-command:dv /t *_trait +// cdb-check:struct ref_mut$ > > > generic_mut_ref_trait = [...] +// cdb-check:struct ref$ > > generic_ref_trait = [...] +// cdb-check:struct alloc::boxed::Box >,alloc::alloc::Global> generic_box_trait = [...] +// cdb-check:struct alloc::boxed::Box,alloc::alloc::Global> box_trait = [...] +// cdb-check:struct ref$ > ref_trait = [...] +// cdb-check:struct ref_mut$ > mut_ref_trait = [...] +// cdb-check:struct alloc::boxed::Box,alloc::alloc::Global> no_principal_trait = [...] +// cdb-check:struct ref$ >,core::marker::Send> > has_associated_type_trait = struct ref$ >,core::marker::Send> > + +// BARE FUNCTIONS +// cdb-command:dv /t *_fn* +// cdb-check:struct tuple$),usize> unsafe_fn_with_return_value = [...] +// cdb-check:struct tuple$ extern_c_fn_with_return_value = [...] +// cdb-check:struct tuple$ rust_fn_with_return_value = [...] +// cdb-check:struct tuple$ >),usize> unsafe_fn = [...] +// cdb-check:struct tuple$ extern_c_fn = [...] +// cdb-check:struct tuple$ >,enum$ >, 1, [...], Some>),usize> rust_fn = [...] +// cdb-command:dv /t *_function* +// cdb-check:struct tuple$, ...),usize> variadic_function = [...] +// cdb-check:struct tuple$ generic_function_struct3 = [...] +// cdb-check:struct tuple$ generic_function_int = [...] +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn") +// cdb-check:Return Type: void +// cdb-check:Parameter Types: enum$ >,enum$ >, 1, [...], Some> +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("rust_fn_with_return_value") +// cdb-check:Return Type: usize +// cdb-check:Parameter Types: f64 +// cdb-command:dx Debugger.State.Scripts.@"type-names.cdb".Contents.getFunctionDetails("extern_c_fn_with_return_value") +// cdb-check:Return Type: type_names::Struct1 +// cdb-check:Parameter Types: + +// CLOSURES +// cdb-command:dv /t closure* +// cdb-check:struct tuple$ closure2 = [...] +// cdb-check:struct tuple$ closure1 = [...] + +// FOREIGN TYPES +// cdb-command:dv /t foreign* +// cdb-check:struct ForeignType2 * foreign2 = [...] +// cdb-check:struct ForeignType1 * foreign1 = [...] #![feature(box_syntax)] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] +#![feature(extern_types)] use self::Enum1::{Variant1, Variant2}; use std::marker::PhantomData; @@ -216,6 +280,8 @@ enum Enum1 { Variant2(isize), } +extern { type ForeignType1; } + mod mod1 { pub use self::Enum2::{Variant1, Variant2}; pub struct Struct2; @@ -234,6 +300,8 @@ mod mod1 { Variant2(T), } } + + extern { pub type ForeignType2; } } trait Trait1 { @@ -242,14 +310,20 @@ trait Trait1 { trait Trait2 { fn dummy(&self, _: T1, _: T2) {} } +trait Trait3 { + type AssocType; + fn dummy(&self) -> T { panic!() } +} impl Trait1 for isize {} impl Trait2 for isize {} +impl Trait3 for isize { + type AssocType = isize; +} fn rust_fn(_: Option, _: Option<&mod1::Struct2>) {} extern "C" fn extern_c_fn(_: isize) {} unsafe fn unsafe_fn(_: Result) {} -extern "stdcall" fn extern_stdcall_fn() {} fn rust_fn_with_return_value(_: f64) -> usize { 4 @@ -260,9 +334,6 @@ extern "C" fn extern_c_fn_with_return_value() -> Struct1 { unsafe fn unsafe_fn_with_return_value(_: GenericStruct) -> mod1::Struct2 { mod1::Struct2 } -extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box) -> usize { - 0 -} fn generic_function(x: T) -> T { x @@ -333,28 +404,28 @@ fn main() { let slice2 = &*vec2; // Trait Objects - let box_trait = (box 0_isize) as Box; - let ref_trait = &0_isize as &Trait1; + let box_trait = (box 0_isize) as Box; + let ref_trait = &0_isize as &dyn Trait1; let mut mut_int1 = 0_isize; - let mut_ref_trait = (&mut mut_int1) as &mut Trait1; + let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1; + let no_principal_trait = (box 0_isize) as Box<(dyn Send + Sync)>; + let has_associated_type_trait = &0_isize as &(dyn Trait3 + Send); - let generic_box_trait = (box 0_isize) as Box>; - let generic_ref_trait = (&0_isize) as &Trait2; + let generic_box_trait = (box 0_isize) as Box>; + let generic_ref_trait = (&0_isize) as &dyn Trait2; let mut generic_mut_ref_trait_impl = 0_isize; let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) - as &mut Trait2>; + as &mut dyn Trait2>; // Bare Functions let rust_fn = (rust_fn, 0_usize); let extern_c_fn = (extern_c_fn, 0_usize); let unsafe_fn = (unsafe_fn, 0_usize); - let extern_stdcall_fn = (extern_stdcall_fn, 0_usize); let rust_fn_with_return_value = (rust_fn_with_return_value, 0_usize); let extern_c_fn_with_return_value = (extern_c_fn_with_return_value, 0_usize); let unsafe_fn_with_return_value = (unsafe_fn_with_return_value, 0_usize); - let extern_stdcall_fn_with_return_value = (extern_stdcall_fn_with_return_value, 0_usize); let generic_function_int = (generic_function::, 0_usize); let generic_function_struct3 = (generic_function::, 0_usize); @@ -370,6 +441,10 @@ fn main() { let closure1 = (|x: isize| {}, 0_usize); let closure2 = (|x: i8, y: f32| (x as f32) + y, 0_usize); + // Foreign Types + let foreign1 = unsafe{ 0 as *const ForeignType1 }; + let foreign2 = unsafe{ 0 as *const mod1::ForeignType2 }; + zzz(); // #break } diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 695cdc4f41..a2778fc609 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -108,7 +108,7 @@ // cdb-command: dx closure_local // cdb-check:closure_local : 8 [Type: [...]] // cdb-command: dx nested_closure -// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::{{closure}}::closure-0] +// cdb-check:nested_closure [Type: var_captured_in_nested_closure::main::closure$0::closure$0] // cdb-command: g diff --git a/src/test/incremental/issue-86753.rs b/src/test/incremental/issue-86753.rs new file mode 100644 index 0000000000..4d6c4354e2 --- /dev/null +++ b/src/test/incremental/issue-86753.rs @@ -0,0 +1,50 @@ +// edition:2018 +// revisions: rpass1 + + +// Regression test for #86753. The `type_implements_trait` query (since moved to a method) +// was encountering an ICE during incremental testing when hashing its arguments. +#![warn(rust_2021_compatibility)] + +use std::future::Future; +use std::pin::Pin; +use std::task::{Poll, Context}; + +struct LocalSet {} +struct RunUntil<'a, F> { + _local_set: &'a LocalSet, + _future: F, +} +impl<'a, F> RunUntil<'a, F> { + fn project<'pin>(self: Pin<&'pin mut Self>) -> Projection<'pin, 'a, F> { + unimplemented!() + } +} + +struct Projection<'pin, 'a, F> +where + RunUntil<'a, F>: 'pin, +{ + pub local_set: &'pin mut &'a LocalSet, + pub future: Pin<&'pin mut F>, +} + +impl LocalSet { + fn with(&self, _f: impl FnOnce() -> T) -> T { + unimplemented!() + } +} +impl Future for RunUntil<'_, T> { + type Output = T::Output; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let me = self.project(); + me.local_set.with(|| { + let _ = cx.waker(); + let f = me.future; + let _ = f.poll(cx); + Poll::Pending + }) + } +} + +fn main() {} diff --git a/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir index 3c56fce3f0..e22adae815 100644 --- a/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir @@ -16,10 +16,10 @@ fn main() -> () { _1 = const b"foo"; // scope 0 at $DIR/byte_slice.rs:5:13: 5:19 // ty::Const // + ty: &[u8; 3] - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/byte_slice.rs:5:13: 5:19 - // + literal: Const { ty: &[u8; 3], val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &[u8; 3], val: Value(Scalar(alloc1)) } StorageLive(_2); // scope 1 at $DIR/byte_slice.rs:6:9: 6:10 _2 = [const 5_u8, const 120_u8]; // scope 1 at $DIR/byte_slice.rs:6:13: 6:24 _0 = const (); // scope 0 at $DIR/byte_slice.rs:4:11: 7:2 @@ -29,6 +29,6 @@ fn main() -> () { } } -alloc0 (size: 3, align: 1) { +alloc1 (size: 3, align: 1) { 66 6f 6f │ foo } diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index a046539665..8e02dca4fb 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageLive(_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 - _2 = const {alloc0: &&[(Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + _2 = const {alloc1: &&[(Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 // ty::Const // + ty: &&[(std::option::Option, &[&str])] - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/const_allocation.rs:8:5: 8:8 - // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageDead(_2); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 StorageDead(_1); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 @@ -23,43 +23,43 @@ fn main() -> () { } } -alloc0 (static: FOO, size: 8, align: 4) { - ╾─alloc17─╼ 03 00 00 00 │ ╾──╼.... +alloc1 (static: FOO, size: 8, align: 4) { + ╾─alloc18─╼ 03 00 00 00 │ ╾──╼.... } -alloc17 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼.... +alloc18 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc5──╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc4 (size: 0, align: 4) {} +alloc5 (size: 0, align: 4) {} -alloc8 (size: 16, align: 4) { - ╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼.... +alloc9 (size: 16, align: 4) { + ╾─alloc8──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -alloc7 (size: 3, align: 1) { +alloc8 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc9 (size: 3, align: 1) { +alloc10 (size: 3, align: 1) { 62 61 72 │ bar } -alloc13 (size: 24, align: 4) { - 0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─alloc15─╼ 04 00 00 00 │ ╾──╼.... +alloc14 (size: 24, align: 4) { + 0x00 │ ╾─alloc13─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾─alloc16─╼ 04 00 00 00 │ ╾──╼.... } -alloc12 (size: 3, align: 1) { +alloc13 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc14 (size: 3, align: 1) { +alloc15 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc15 (size: 4, align: 1) { +alloc16 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index 2385943920..88cdbda2fa 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageLive(_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 - _2 = const {alloc0: &&[(Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + _2 = const {alloc1: &&[(Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 // ty::Const // + ty: &&[(std::option::Option, &[&str])] - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/const_allocation.rs:8:5: 8:8 - // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageDead(_2); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 StorageDead(_1); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 @@ -23,47 +23,47 @@ fn main() -> () { } } -alloc0 (static: FOO, size: 16, align: 8) { - ╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc1 (static: FOO, size: 16, align: 8) { + ╾───────alloc18───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc17 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼ +alloc18 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc5────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc4 (size: 0, align: 8) {} +alloc5 (size: 0, align: 8) {} -alloc8 (size: 32, align: 8) { - 0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc9 (size: 32, align: 8) { + 0x00 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc7 (size: 3, align: 1) { +alloc8 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc9 (size: 3, align: 1) { +alloc10 (size: 3, align: 1) { 62 61 72 │ bar } -alloc13 (size: 48, align: 8) { - 0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc14 (size: 48, align: 8) { + 0x00 │ ╾───────alloc13───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾───────alloc16───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc12 (size: 3, align: 1) { +alloc13 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc14 (size: 3, align: 1) { +alloc15 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc15 (size: 4, align: 1) { +alloc16 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index 1e4bd4ba91..059b721f5b 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 - _2 = const {alloc0: &&[(Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + _2 = const {alloc1: &&[(Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 // ty::Const // + ty: &&[(std::option::Option, &[&u8])] - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/const_allocation2.rs:5:5: 5:8 - // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 @@ -23,42 +23,42 @@ fn main() -> () { } } -alloc0 (static: FOO, size: 8, align: 4) { - ╾─alloc27─╼ 03 00 00 00 │ ╾──╼.... +alloc1 (static: FOO, size: 8, align: 4) { + ╾─alloc28─╼ 03 00 00 00 │ ╾──╼.... } -alloc27 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc17─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc25─╼ 03 00 00 00 │ ....*...╾──╼.... +alloc28 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc18─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc26─╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc12 (size: 0, align: 4) {} +alloc13 (size: 0, align: 4) {} -alloc17 (size: 8, align: 4) { - ╾─alloc15─╼ ╾─alloc16─╼ │ ╾──╼╾──╼ +alloc18 (size: 8, align: 4) { + ╾─alloc16─╼ ╾─alloc17─╼ │ ╾──╼╾──╼ } -alloc15 (size: 1, align: 1) { +alloc16 (size: 1, align: 1) { 05 │ . } -alloc16 (size: 1, align: 1) { +alloc17 (size: 1, align: 1) { 06 │ . } -alloc25 (size: 12, align: 4) { - ╾─a21+0x3─╼ ╾─alloc22─╼ ╾─a24+0x2─╼ │ ╾──╼╾──╼╾──╼ +alloc26 (size: 12, align: 4) { + ╾─a22+0x3─╼ ╾─alloc23─╼ ╾─a25+0x2─╼ │ ╾──╼╾──╼╾──╼ } -alloc21 (size: 4, align: 1) { +alloc22 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc22 (size: 1, align: 1) { +alloc23 (size: 1, align: 1) { 2a │ * } -alloc24 (size: 4, align: 1) { +alloc25 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index f943beced3..d6a97917d6 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 - _2 = const {alloc0: &&[(Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + _2 = const {alloc1: &&[(Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 // ty::Const // + ty: &&[(std::option::Option, &[&u8])] - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/const_allocation2.rs:5:5: 5:8 - // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 @@ -23,45 +23,45 @@ fn main() -> () { } } -alloc0 (static: FOO, size: 16, align: 8) { - ╾───────alloc27───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc1 (static: FOO, size: 16, align: 8) { + ╾───────alloc28───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc27 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc12───────╼ │ ....░░░░╾──────╼ +alloc28 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc13───────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc17───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc25───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc18───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc26───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc12 (size: 0, align: 8) {} +alloc13 (size: 0, align: 8) {} -alloc17 (size: 16, align: 8) { - ╾───────alloc15───────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼ +alloc18 (size: 16, align: 8) { + ╾───────alloc16───────╼ ╾───────alloc17───────╼ │ ╾──────╼╾──────╼ } -alloc15 (size: 1, align: 1) { +alloc16 (size: 1, align: 1) { 05 │ . } -alloc16 (size: 1, align: 1) { +alloc17 (size: 1, align: 1) { 06 │ . } -alloc25 (size: 24, align: 8) { - 0x00 │ ╾─────alloc21+0x3─────╼ ╾───────alloc22───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc24+0x2─────╼ │ ╾──────╼ +alloc26 (size: 24, align: 8) { + 0x00 │ ╾─────alloc22+0x3─────╼ ╾───────alloc23───────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────alloc25+0x2─────╼ │ ╾──────╼ } -alloc21 (size: 4, align: 1) { +alloc22 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc22 (size: 1, align: 1) { +alloc23 (size: 1, align: 1) { 2a │ * } -alloc24 (size: 4, align: 1) { +alloc25 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index 5c95afb586..32000340dc 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 - _2 = const {alloc0: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + _2 = const {alloc1: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 // ty::Const // + ty: &&Packed - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/const_allocation3.rs:5:5: 5:8 - // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 @@ -23,31 +23,31 @@ fn main() -> () { } } -alloc0 (static: FOO, size: 4, align: 4) { - ╾─alloc10─╼ │ ╾──╼ +alloc1 (static: FOO, size: 4, align: 4) { + ╾─alloc11─╼ │ ╾──╼ } -alloc10 (size: 168, align: 1) { +alloc11 (size: 168, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc5──╼ │ ............╾──╼ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc6──╼ │ ............╾──╼ 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc7──╼ 00 00 │ ..........╾──╼.. - 0x90 │ ╾─a8+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc8──╼ 00 00 │ ..........╾──╼.. + 0x90 │ ╾─a9+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } -alloc5 (size: 4, align: 4) { +alloc6 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc7 (fn: main) +alloc8 (fn: main) -alloc8 (size: 100, align: 1) { +alloc9 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index 3d1858de22..cac882333a 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 - _2 = const {alloc0: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + _2 = const {alloc1: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 // ty::Const // + ty: &&Packed - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/const_allocation3.rs:5:5: 5:8 - // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 @@ -23,13 +23,13 @@ fn main() -> () { } } -alloc0 (static: FOO, size: 8, align: 8) { - ╾───────alloc10───────╼ │ ╾──────╼ +alloc1 (static: FOO, size: 8, align: 8) { + ╾───────alloc11───────╼ │ ╾──────╼ } -alloc10 (size: 180, align: 1) { +alloc11 (size: 180, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc5── │ ............╾─── + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc6── │ ............╾─── 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -37,18 +37,18 @@ alloc10 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ─────alloc7─────╼ 00 00 ╾─────alloc8+0x63─────╼ │ ─────╼..╾──────╼ + 0x90 │ ─────alloc8─────╼ 00 00 ╾─────alloc9+0x63─────╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } -alloc5 (size: 4, align: 4) { +alloc6 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc7 (fn: main) +alloc8 (fn: main) -alloc8 (size: 100, align: 1) { +alloc9 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 2497c553e6..a64c960b9f 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -7,13 +7,13 @@ promoted[0] in BAR: &[&i32; 1] = { let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 bb0: { - _3 = const {alloc0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 + _3 = const {alloc1: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 // ty::Const // + ty: &i32 - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } _2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 @@ -21,6 +21,6 @@ promoted[0] in BAR: &[&i32; 1] = { } } -alloc0 (static: Y, size: 4, align: 4) { +alloc1 (static: Y, size: 4, align: 4) { 2a 00 00 00 │ *... } 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 2566d745ec..6f4bd65b85 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 @@ -16,21 +16,21 @@ - StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 - StorageLive(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 -- _5 = const {alloc0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 +- _5 = const {alloc1: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 + _6 = const BAR::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 // ty::Const - // + ty: &i32 -- // + val: Value(Scalar(alloc0)) +- // + val: Value(Scalar(alloc1)) + // + ty: &[&i32; 1] + // + val: Unevaluated(BAR, [], Some(promoted[0])) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 -- // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) } +- // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } - _4 = &(*_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35 @@ -53,7 +53,7 @@ } - } - -- alloc0 (static: Y, size: 4, align: 4) { +- alloc1 (static: Y, size: 4, align: 4) { - 2a 00 00 00 │ *... } diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 17107ec431..8b3c5d332f 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -7,13 +7,13 @@ promoted[0] in FOO: &[&i32; 1] = { let mut _3: *const i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 bb0: { - _3 = const {alloc2: *const i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 + _3 = const {alloc3: *const i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 // ty::Const // + ty: *const i32 - // + val: Value(Scalar(alloc2)) + // + val: Value(Scalar(alloc3)) // mir::Constant // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 - // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) } + // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } _2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 @@ -21,4 +21,4 @@ promoted[0] in FOO: &[&i32; 1] = { } } -alloc2 (extern static: X) +alloc3 (extern static: X) 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 093e228a0c..8c9a37bce8 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 @@ -18,21 +18,21 @@ - StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 - StorageLive(_5); // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 -- _5 = const {alloc2: *const i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 +- _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 + _6 = const FOO::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 // ty::Const - // + ty: *const i32 -- // + val: Value(Scalar(alloc2)) +- // + val: Value(Scalar(alloc3)) + // + ty: &[&i32; 1] + // + val: Unevaluated(FOO, [], Some(promoted[0])) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 -- // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) } +- // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } - _4 = &(*_5); // scope 1 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46 @@ -55,5 +55,5 @@ } } - -- alloc2 (extern static: X) +- alloc3 (extern static: X) diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index 0517e7fac4..db6e136916 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -31,7 +31,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index 0517e7fac4..db6e136916 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -31,7 +31,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 diff --git a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff index bccfa9da61..77ff8ef4e4 100644 --- a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff @@ -14,9 +14,6 @@ - _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:5:18: 5:23 - assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23 + _2 = const (2_u32, false); // scope 0 at $DIR/checked_add.rs:5:18: 5:23 -+ // mir::Constant -+ // + span: $DIR/checked_add.rs:5:18: 5:23 -+ // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [2, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23 } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff index 28c80b346e..d7bc035e66 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff @@ -22,7 +22,7 @@ // + val: Unevaluated(FOO, [], None) // mir::Constant // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[2706]::main::FOO), const_param_did: None }, substs: [], promoted: None }) } _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 _1 = move _2 as usize (Misc); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39 StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39 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 57a00ba12b..8dd55235ef 100644 --- a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff @@ -18,9 +18,6 @@ - assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29 + _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:5:13: 5:25 + _3 = const (3_u8, false); // scope 0 at $DIR/indirect.rs:5:13: 5:29 -+ // mir::Constant -+ // + span: $DIR/indirect.rs:5:13: 5:29 -+ // + literal: Const { ty: (u8, bool), val: Value(ByRef { alloc: Allocation { bytes: [3, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29 } diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff index 518974e24b..2d3289f7ce 100644 --- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -15,9 +15,6 @@ (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue-67019.rs:11:11: 11:17 - (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue-67019.rs:11:10: 11:19 + (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:11:10: 11:19 -+ // mir::Constant -+ // + span: $DIR/issue-67019.rs:11:10: 11:19 -+ // + literal: Const { ty: (u8, u8), val: Value(ByRef { alloc: Allocation { bytes: [1, 2], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:11:18: 11:19 _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:11:5: 11:20 // mir::Constant diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index d94c4f6fb2..a044d1dcfe 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -20,9 +20,6 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10 - _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14 + _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14 -+ // mir::Constant -+ // + span: $DIR/mutable_variable_aggregate.rs:7:13: 7:14 -+ // + literal: Const { ty: (i32, i32), val: Value(ByRef { alloc: Allocation { bytes: [42, 0, 0, 0, 99, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } nop; // scope 0 at $DIR/mutable_variable_aggregate.rs:4:11: 8:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:8:1: 8:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:8:1: 8:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index 5dad8e721f..afc6217846 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -23,13 +23,13 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6 StorageLive(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 - _4 = const {alloc0: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + _4 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 // ty::Const // + ty: *mut u32 - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19 - // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc0)) } + // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) } _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:9: 9:19 StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:18: 9:19 @@ -45,7 +45,7 @@ } } - alloc0 (static: STATIC, size: 4, align: 4) { + alloc1 (static: STATIC, size: 4, align: 4) { 2a 00 00 00 │ *... } diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff index 537f1b6253..4c3f66cd09 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff @@ -27,9 +27,6 @@ - _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 - assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 + _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 -+ // mir::Constant -+ // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18 -+ // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 } diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff index 537f1b6253..4c3f66cd09 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff @@ -27,9 +27,6 @@ - _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 - assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 + _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 -+ // mir::Constant -+ // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18 -+ // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18 } diff --git a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff index 0d141a070f..13ef30d89a 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff @@ -16,24 +16,24 @@ StorageLive(_1); // scope 0 at $DIR/read_immutable_static.rs:7:9: 7:10 StorageLive(_2); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 StorageLive(_3); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 - _3 = const {alloc0: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 + _3 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 // ty::Const // + ty: &u8 - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/read_immutable_static.rs:7:13: 7:16 - // + literal: Const { ty: &u8, val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 + _2 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 StorageLive(_4); // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 - _5 = const {alloc0: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 + _5 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 // ty::Const // + ty: &u8 - // + val: Value(Scalar(alloc0)) + // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/read_immutable_static.rs:7:19: 7:22 - // + literal: Const { ty: &u8, val: Value(Scalar(alloc0)) } + // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 - _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:22 + _4 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 @@ -48,7 +48,7 @@ } } - alloc0 (static: FOO, size: 1, align: 1) { + alloc1 (static: FOO, size: 1, align: 1) { 02 │ . } diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff index ae77443e01..4e19465189 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff @@ -17,7 +17,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/ref_deref.rs:5:6: 5:10 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _2 = _4; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 - _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 + _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff index 402a28f3f9..a58dabdaa4 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff @@ -20,7 +20,7 @@ + // + val: Unevaluated(main, [], Some(promoted[0])) + // mir::Constant + // + span: $DIR/ref_deref.rs:5:6: 5:10 -+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 - StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index b97d7d1be1..bb265b2af7 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -17,7 +17,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/ref_deref_project.rs:5:6: 5:17 - // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff index 48ede27112..bb7570fabb 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff @@ -20,7 +20,7 @@ + // + val: Unevaluated(main, [], Some(promoted[0])) + // mir::Constant + // + span: $DIR/ref_deref_project.rs:5:6: 5:17 -+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 - StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 diff --git a/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff b/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff index 97808246dd..c6ac8d6fb1 100644 --- a/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff +++ b/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff @@ -9,9 +9,6 @@ - _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:6:5: 6:10 - assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10 + _1 = const (4_u32, false); // scope 0 at $DIR/return_place.rs:6:5: 6:10 -+ // mir::Constant -+ // + span: $DIR/return_place.rs:6:5: 6:10 -+ // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10 } diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index 27791852d6..d5a36182e3 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -24,7 +24,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index 27791852d6..d5a36182e3 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -24,7 +24,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff index b8f9cd34c9..15253a364e 100644 --- a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff @@ -18,9 +18,6 @@ StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14 - _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14 + _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14 -+ // mir::Constant -+ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:14 -+ // + literal: Const { ty: (u32, u32), val: Value(ByRef { alloc: Allocation { bytes: [1, 0, 0, 0, 2, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:5:5: 5:15 // mir::Constant // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12 diff --git a/src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff b/src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff index e60a1f3e75..d3c7136c64 100644 --- a/src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff +++ b/src/test/mir-opt/deaggregator_test.bar.Deaggregator.diff @@ -12,9 +12,6 @@ - _0 = Baz { x: move _2, y: const 0f32, z: const false }; // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35 + (_0.0: usize) = move _2; // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35 + (_0.1: f32) = const 0f32; // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35 - // mir::Constant - // + span: $DIR/deaggregator_test.rs:9:20: 9:23 - // + literal: Const { ty: f32, val: Value(Scalar(0x00000000)) } + (_0.2: bool) = const false; // scope 0 at $DIR/deaggregator_test.rs:9:5: 9:35 StorageDead(_2); // scope 0 at $DIR/deaggregator_test.rs:9:34: 9:35 return; // scope 0 at $DIR/deaggregator_test.rs:10:2: 10:2 diff --git a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir index 6da0460286..d19229aaba 100644 --- a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir +++ b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir @@ -14,7 +14,7 @@ }, } */ -fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6 {String, ()}]) -> () { +fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6]) -> () { let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 let mut _2: (); // in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 let _3: std::string::String; // in scope 0 at $DIR/generator-drop-cleanup.rs:11:13: 11:15 diff --git a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir index 296a459b99..642d9b3fb3 100644 --- a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir +++ b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` before StateTransform -fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 28:6 {Foo, Bar, ()}], _2: ()) -> () +fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 28:6], _2: ()) -> () yields () { let mut _0: (); // return place in scope 0 at $DIR/generator-storage-dead-unwind.rs:22:19: 22:19 diff --git a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir index 990aa1ec08..539988cad2 100644 --- a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir +++ b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir @@ -10,7 +10,7 @@ storage_conflicts: BitMatrix(0x0) {}, } */ -fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]>, _2: u8) -> GeneratorState<(), ()> { +fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]>, _2: u8) -> GeneratorState<(), ()> { debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19 let mut _0: std::ops::GeneratorState<(), ()>; // return place in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 let _3: HasDrop; // in scope 0 at $DIR/generator-tiny.rs:20:13: 20:15 @@ -27,7 +27,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 } bb0: { - _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]))); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 + _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]))); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 } @@ -43,7 +43,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 StorageLive(_7); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 discriminant(_0) = 0; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 - discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 + discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 return; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 } diff --git a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff index 2c4952402a..64a3f52f3a 100644 --- a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff @@ -12,9 +12,6 @@ StorageLive(_3); // scope 0 at $DIR/if-condition-int.rs:53:8: 53:9 _3 = _1; // scope 0 at $DIR/if-condition-int.rs:53:8: 53:9 _2 = Eq(move _3, const -42f32); // scope 0 at $DIR/if-condition-int.rs:53:8: 53:18 - // mir::Constant - // + span: $DIR/if-condition-int.rs:53:13: 53:18 - // + literal: Const { ty: f32, val: Value(Scalar(0xc2280000)) } StorageDead(_3); // scope 0 at $DIR/if-condition-int.rs:53:17: 53:18 switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35 } 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 fba88c83eb..9035b46f4c 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -13,13 +13,13 @@ } + scope 2 (inlined g) { // at $DIR/inline-generator.rs:9:28: 9:31 + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32 ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32 + debug pointer => _3; // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32 -+ let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]; // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32 ++ let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32 + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]>::new_unchecked) { // at $DIR/inline-generator.rs:9:14: 9:32 ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new_unchecked) { // at $DIR/inline-generator.rs:9:14: 9:32 + debug pointer => _5; // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32 -+ let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]; // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32 ++ let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32 + } + } + } @@ -58,7 +58,7 @@ + _5 = move _3; // scope 4 at $DIR/inline-generator.rs:9:14: 9:32 + StorageLive(_6); // scope 5 at $DIR/inline-generator.rs:9:14: 9:32 + _6 = move _5; // scope 5 at $DIR/inline-generator.rs:9:14: 9:32 -+ (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]) = move _6; // scope 5 at $DIR/inline-generator.rs:9:14: 9:32 ++ (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]) = move _6; // scope 5 at $DIR/inline-generator.rs:9:14: 9:32 + StorageDead(_6); // scope 5 at $DIR/inline-generator.rs:9:14: 9:32 + StorageDead(_5); // scope 4 at $DIR/inline-generator.rs:9:14: 9:32 StorageDead(_3); // scope 0 at $DIR/inline-generator.rs:9:31: 9:32 @@ -71,7 +71,7 @@ + StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_11); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_12); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 -+ _12 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 ++ _12 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 + switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 } @@ -115,7 +115,7 @@ + StorageDead(_9); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 + ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 + discriminant(_1) = 0; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 -+ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 3; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 ++ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]))) = 3; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 + goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:11: 15:39 + } + @@ -125,7 +125,7 @@ + StorageDead(_8); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 + ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 + discriminant(_1) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 -+ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 ++ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]))) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46 + goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:41: 15:41 + } + 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 1aabee83be..5ceefce611 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 @@ -38,7 +38,7 @@ fn bar() -> bool { // + val: Unevaluated(bar, [], Some(promoted[1])) // mir::Constant // + span: $DIR/inline-retag.rs:12:7: 12:9 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) } Retag(_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 _4 = &(*_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 Retag(_4); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 @@ -52,7 +52,7 @@ fn bar() -> bool { // + val: Unevaluated(bar, [], Some(promoted[0])) // mir::Constant // + span: $DIR/inline-retag.rs:12:11: 12:14 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } Retag(_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 _7 = &(*_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 Retag(_7); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff index 95a8ef997f..e955feb7d1 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -66,7 +66,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index 95a8ef997f..e955feb7d1 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -66,7 +66,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff index 261eb3b27e..ff8c410a72 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff @@ -87,7 +87,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index 261eb3b27e..ff8c410a72 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -87,7 +87,7 @@ // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index a37df4da9a..acb8aca759 100644 --- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -50,7 +50,7 @@ // + val: Unevaluated(discriminant, [T], Some(promoted[2])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:70:42: 70:44 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) } _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 - _5 = discriminant_value::(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45 @@ -74,7 +74,7 @@ // + val: Unevaluated(discriminant, [T], Some(promoted[1])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:71:42: 71:45 - // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) } + // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) } _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46 @@ -98,7 +98,7 @@ // + val: Unevaluated(discriminant, [T], Some(promoted[0])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:72:42: 72:47 - // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) } _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - _13 = discriminant_value::(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48 diff --git a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff new file mode 100644 index 0000000000..d2056ac13a --- /dev/null +++ b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff @@ -0,0 +1,63 @@ +- // MIR for `bound` before LowerSliceLenCalls ++ // MIR for `bound` after LowerSliceLenCalls + + fn bound(_1: usize, _2: &[u8]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_slice_len.rs:4:14: 4:19 + debug slice => _2; // in scope 0 at $DIR/lower_slice_len.rs:4:28: 4:33 + let mut _0: u8; // return place in scope 0 at $DIR/lower_slice_len.rs:4:45: 4:47 + let mut _3: bool; // in scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27 + let mut _4: usize; // in scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13 + let mut _5: usize; // in scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 + let mut _6: &[u8]; // in scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21 + let _7: usize; // in scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20 + let mut _8: usize; // in scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 + let mut _9: bool; // in scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27 + StorageLive(_4); // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13 + _4 = _1; // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13 + StorageLive(_5); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 + StorageLive(_6); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21 + _6 = &(*_2); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21 +- _5 = core::slice::::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 +- // mir::Constant +- // + span: $DIR/lower_slice_len.rs:5:22: 5:25 +- // + literal: Const { ty: for<'r> fn(&'r [u8]) -> usize {core::slice::::len}, val: Value(Scalar()) } ++ _5 = Len((*_6)); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 ++ goto -> bb1; // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 + } + + bb1: { + StorageDead(_6); // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27 + StorageDead(_5); // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27 + StorageDead(_4); // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27 + switchInt(move _3) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6 + } + + bb2: { + StorageLive(_7); // scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20 + _7 = _1; // scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20 + _8 = Len((*_2)); // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 + _9 = Lt(_7, _8); // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 + assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb4; // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 + } + + bb3: { + _0 = const 42_u8; // scope 0 at $DIR/lower_slice_len.rs:8:9: 8:11 + goto -> bb5; // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6 + } + + bb4: { + _0 = (*_2)[_7]; // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 + StorageDead(_7); // scope 0 at $DIR/lower_slice_len.rs:7:5: 7:6 + goto -> bb5; // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6 + } + + bb5: { + StorageDead(_3); // scope 0 at $DIR/lower_slice_len.rs:9:5: 9:6 + return; // scope 0 at $DIR/lower_slice_len.rs:10:2: 10:2 + } + } + diff --git a/src/test/mir-opt/lower_slice_len.rs b/src/test/mir-opt/lower_slice_len.rs new file mode 100644 index 0000000000..f2438e6974 --- /dev/null +++ b/src/test/mir-opt/lower_slice_len.rs @@ -0,0 +1,14 @@ +// compile-flags: -Z mir-opt-level=3 + +// EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff +pub fn bound(index: usize, slice: &[u8]) -> u8 { + if index < slice.len() { + slice[index] + } else { + 42 + } +} + +fn main() { + let _ = bound(1, &[1, 2, 3]); +} diff --git a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir index 5af242376c..c27ee528b8 100644 --- a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir +++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir @@ -57,7 +57,7 @@ fn full_tested_match() -> () { // + val: Unevaluated(full_tested_match, [], Some(promoted[0])) // mir::Constant // + span: $DIR/match_false_edges.rs:16:14: 16:15 - // + literal: Const { ty: &std::option::Option, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &std::option::Option, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[4011]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15 _4 = &shallow _2; // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27 StorageLive(_7); // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27 diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index c6ef403c3c..787310d072 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 @@ -127,7 +127,7 @@ fn array_casts() -> () { // + val: Unevaluated(array_casts, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[317d]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL 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 4bab5a9748..8abc6a3e4b 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 @@ -113,7 +113,7 @@ fn main() -> () { StorageLive(_14); // scope 1 at $DIR/retag.rs:40:31: 43:6 _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:40:31: 43:6 // closure - // + def_id: DefId(0:14 ~ retag[317d]::main::{closure#0}) + // + def_id: DefId(0:14 ~ retag[13e7]::main::{closure#0}) // + substs: [ // i8, // for<'r> extern "rust-call" fn((&'r i32,)) -> &'r i32, @@ -153,7 +153,7 @@ fn main() -> () { // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/retag.rs:47:21: 47:23 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[13e7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } Retag(_28); // scope 7 at $DIR/retag.rs:47:21: 47:23 _23 = &(*_28); // scope 7 at $DIR/retag.rs:47:21: 47:23 Retag(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23 diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff index a698d8abcd..598e8247ef 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff @@ -38,9 +38,6 @@ // mir::Constant // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:12 // + literal: Const { ty: fn(((), ())) {use_zst}, val: Value(Scalar()) } - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 - // + literal: Const { ty: ((), ()), val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir new file mode 100644 index 0000000000..373be9f174 --- /dev/null +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -0,0 +1,106 @@ +// MIR for `main` after SimplifyCfg-after-uninhabited-enum-branching + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 18:11 + let _1: Plop; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13 + let mut _2: Test1; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46 + let _3: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + let mut _4: &Test1; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22 + let mut _5: isize; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20 + let _6: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 + let _7: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + let _8: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + let _9: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + let mut _10: isize; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20 + let _11: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 + let _12: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + let _13: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + scope 1 { + debug plop => _1; // in scope 1 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13 + StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46 + discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46 + (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48 + (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48 + StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:47: 19:48 + StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22 + _4 = &(_1.1: Test1); // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22 + _5 = discriminant((*_4)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20 + switchInt(move _5) -> [2_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20 + } + + bb1: { + StorageLive(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _3 = &(*_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + StorageDead(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 + goto -> bb3; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + } + + bb2: { + StorageLive(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _3 = &(*_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + StorageDead(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 + goto -> bb3; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + } + + bb3: { + StorageDead(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7 + StorageDead(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7 + StorageLive(_9); // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20 + switchInt(move _10) -> [2_isize: bb5, otherwise: bb4]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20 + } + + bb4: { + StorageLive(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _9 = &(*_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + StorageDead(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 + goto -> bb6; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + } + + bb5: { + StorageLive(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _9 = &(*_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + StorageDead(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 + goto -> bb6; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + } + + bb6: { + StorageDead(_9); // scope 1 at $DIR/uninhabited_enum_branching2.rs:33:6: 33:7 + _0 = const (); // scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 34:2 + StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:1: 34:2 + return; // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:2: 34:2 + } +} diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff new file mode 100644 index 0000000000..f9488bae4c --- /dev/null +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff @@ -0,0 +1,160 @@ +- // MIR for `main` before UninhabitedEnumBranching ++ // MIR for `main` after UninhabitedEnumBranching + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 18:11 + let _1: Plop; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13 + let mut _2: Test1; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46 + let _3: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + let mut _4: &Test1; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22 + let mut _5: isize; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20 + let _6: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 + let _7: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + let _8: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + let _9: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + let mut _10: isize; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20 + let _11: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 + let _12: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + let _13: &str; // in scope 0 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + scope 1 { + debug plop => _1; // in scope 1 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:9: 19:13 + StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46 + discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:38: 19:46 + (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48 + (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:16: 19:48 + StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:19:47: 19:48 + StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22 + _4 = &(_1.1: Test1); // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22 + _5 = discriminant((*_4)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20 +- switchInt(move _5) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20 ++ switchInt(move _5) -> [2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20 + } + + bb1: { + StorageLive(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _3 = &(*_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 + StorageDead(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 + goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + } + + bb2: { + _3 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + } + + bb3: { + StorageLive(_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 + _6 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + _3 = &(*_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 + StorageDead(_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34 + goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + } + + bb4: { + StorageLive(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _3 = &(*_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 + StorageDead(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 + goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6 + } + + bb5: { + StorageDead(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7 + StorageDead(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7 + StorageLive(_9); // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20 +- switchInt(move _10) -> [0_isize: bb7, 1_isize: bb8, 2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20 ++ switchInt(move _10) -> [2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20 + } + + bb6: { + StorageLive(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _9 = &(*_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 + StorageDead(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 + goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + } + + bb7: { + _9 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + } + + bb8: { + StorageLive(_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 + _11 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + _9 = &(*_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 + StorageDead(_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34 + goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + } + + bb9: { + StorageLive(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + // ty::Const + // + ty: &str + // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) + // mir::Constant + // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + _9 = &(*_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 + StorageDead(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 + goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6 + } + + bb10: { + StorageDead(_9); // scope 1 at $DIR/uninhabited_enum_branching2.rs:33:6: 33:7 + _0 = const (); // scope 0 at $DIR/uninhabited_enum_branching2.rs:18:11: 34:2 + StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:1: 34:2 + return; // scope 0 at $DIR/uninhabited_enum_branching2.rs:34:2: 34:2 + } + } + diff --git a/src/test/mir-opt/uninhabited_enum_branching2.rs b/src/test/mir-opt/uninhabited_enum_branching2.rs new file mode 100644 index 0000000000..e22e94314d --- /dev/null +++ b/src/test/mir-opt/uninhabited_enum_branching2.rs @@ -0,0 +1,34 @@ +enum Empty { } + +// test matching an enum with uninhabited variants +enum Test1 { + A(Empty), + B(Empty), + C, + D, +} + +struct Plop { + xx: u32, + test1: Test1, +} + +// EMIT_MIR uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff +// EMIT_MIR uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +fn main() { + let plop = Plop { xx: 51, test1: Test1::C }; + + match &plop.test1 { + Test1::A(_) => "A(Empty)", + Test1::B(_) => "B(Empty)", + Test1::C => "C", + Test1::D => "D", + }; + + match plop.test1 { + Test1::A(_) => "A(Empty)", + Test1::B(_) => "B(Empty)", + Test1::C => "C", + Test1::D => "D", + }; +} diff --git a/src/test/pretty/ast-stmt-expr-attr.rs b/src/test/pretty/ast-stmt-expr-attr.rs index a32903a640..32d1da390c 100644 --- a/src/test/pretty/ast-stmt-expr-attr.rs +++ b/src/test/pretty/ast-stmt-expr-attr.rs @@ -39,7 +39,7 @@ fn syntax() { #![attr] }; let _ = - #[attr] loop { + #[attr] loop { #![attr] }; let _ = diff --git a/src/test/pretty/block-comment-wchar.pp b/src/test/pretty/block-comment-wchar.pp index 2bfcdd75e1..2d0a10d4c2 100644 --- a/src/test/pretty/block-comment-wchar.pp +++ b/src/test/pretty/block-comment-wchar.pp @@ -90,7 +90,7 @@ fn f() { } fn main() { - // Taken from http://www.unicode.org/Public/UNIDATA/PropList.txt + // Taken from https://www.unicode.org/Public/UNIDATA/PropList.txt let chars = ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u{85}', '\u{A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', diff --git a/src/test/pretty/block-comment-wchar.rs b/src/test/pretty/block-comment-wchar.rs index 93373c5da6..075230196e 100644 --- a/src/test/pretty/block-comment-wchar.rs +++ b/src/test/pretty/block-comment-wchar.rs @@ -86,7 +86,7 @@ fn f() { } fn main() { - // Taken from http://www.unicode.org/Public/UNIDATA/PropList.txt + // Taken from https://www.unicode.org/Public/UNIDATA/PropList.txt let chars = ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u{85}', '\u{A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', diff --git a/src/test/pretty/cast-lt.pp b/src/test/pretty/cast-lt.pp index 4f6a924909..e6c4d19569 100644 --- a/src/test/pretty/cast-lt.pp +++ b/src/test/pretty/cast-lt.pp @@ -8,6 +8,6 @@ extern crate std; // pretty-mode:expanded // pp-exact:cast-lt.pp -macro_rules! negative { ($ e : expr) => { $ e < 0 } } +macro_rules! negative { ($e : expr) => { $e < 0 } } fn main() { (1 as i32) < 0; } diff --git a/src/test/pretty/delimited-token-groups.rs b/src/test/pretty/delimited-token-groups.rs index 125f2b0fa1..257c032b53 100644 --- a/src/test/pretty/delimited-token-groups.rs +++ b/src/test/pretty/delimited-token-groups.rs @@ -2,7 +2,7 @@ #![feature(rustc_attrs)] -macro_rules! mac { ($ ($ tt : tt) *) => () } +macro_rules! mac { ($($tt : tt) *) => () } mac! { struct S { field1 : u8, field2 : u16, } impl Clone for S diff --git a/src/test/pretty/hir-pretty-loop.pp b/src/test/pretty/hir-pretty-loop.pp new file mode 100644 index 0000000000..19b3a1775c --- /dev/null +++ b/src/test/pretty/hir-pretty-loop.pp @@ -0,0 +1,9 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// pretty-compare-only +// pretty-mode:hir +// pp-exact:hir-pretty-loop.pp + +pub fn foo() { loop { break ; } } diff --git a/src/test/pretty/hir-pretty-loop.rs b/src/test/pretty/hir-pretty-loop.rs new file mode 100644 index 0000000000..87a3ef8b8f --- /dev/null +++ b/src/test/pretty/hir-pretty-loop.rs @@ -0,0 +1,9 @@ +// pretty-compare-only +// pretty-mode:hir +// pp-exact:hir-pretty-loop.pp + +pub fn foo(){ + loop{ + break; + } +} diff --git a/src/test/pretty/macro.rs b/src/test/pretty/macro.rs index 1e1e1dbfb3..d3865d93a3 100644 --- a/src/test/pretty/macro.rs +++ b/src/test/pretty/macro.rs @@ -2,6 +2,6 @@ #![feature(decl_macro)] -pub(crate) macro mac { ($ arg : expr) => { $ arg + $ arg } } +pub(crate) macro mac { ($arg : expr) => { $arg + $arg } } fn main() { } diff --git a/src/test/pretty/macro_rules.rs b/src/test/pretty/macro_rules.rs index da223d164f..3b13f2530d 100644 --- a/src/test/pretty/macro_rules.rs +++ b/src/test/pretty/macro_rules.rs @@ -11,9 +11,9 @@ macro_rules! matcher_brackets { } macro_rules! all_fragments { - ($ b : block, $ e : expr, $ i : ident, $ it : item, $ l : lifetime, $ lit - : literal, $ m : meta, $ p : pat, $ pth : path, $ s : stmt, $ tt : tt, $ - ty : ty, $ vis : vis) => { } ; + ($b : block, $e : expr, $i : ident, $it : item, $l : lifetime, $lit : + literal, $m : meta, $p : pat, $pth : path, $s : stmt, $tt : tt, $ty : ty, + $vis : vis) => { } ; } fn main() { } diff --git a/src/test/pretty/stmt_expr_attributes.rs b/src/test/pretty/stmt_expr_attributes.rs index 231351433c..e4a3acade8 100644 --- a/src/test/pretty/stmt_expr_attributes.rs +++ b/src/test/pretty/stmt_expr_attributes.rs @@ -166,9 +166,8 @@ fn _11() { #[rustc_dummy] for _ in 0..0 { #![rustc_dummy] }; - // FIXME: pp bug, two spaces after the loop let _ = - #[rustc_dummy] loop { + #[rustc_dummy] loop { #![rustc_dummy] }; let _ = diff --git a/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile new file mode 100644 index 0000000000..bc4562bef3 --- /dev/null +++ b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) --edition=2018 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile index d3d398f1fa..78fbf811f1 100644 --- a/src/test/run-make-fulldeps/coverage-reports/Makefile +++ b/src/test/run-make-fulldeps/coverage-reports/Makefile @@ -87,7 +87,7 @@ endif # Run it in order to generate some profiling data, # with `LLVM_PROFILE_FILE=` environment variable set to # output the coverage stats for this run. - LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \ + LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \ $(call RUN,$@) || \ ( \ status=$$?; \ @@ -97,8 +97,11 @@ endif ) \ ) - # Run it through rustdoc as well to cover doctests - LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \ + # Run it through rustdoc as well to cover doctests. + # `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone + # might result in overwritten files and failed tests, as rustdoc spawns each + # doctest as its own process, so make sure the filename is as unique as possible. + LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \ $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \ -L "$(TMPDIR)" -Zinstrument-coverage \ @@ -106,7 +109,7 @@ endif # Postprocess the profiling data so it can be used by the llvm-cov tool "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \ - "$(TMPDIR)"/$@-*.profraw \ + "$(TMPDIR)"/$@*.profraw \ -o "$(TMPDIR)"/$@.profdata # Generate a coverage report using `llvm-cov show`. @@ -118,8 +121,7 @@ endif --instr-profile="$(TMPDIR)"/$@.profdata \ $(call BIN,"$(TMPDIR)"/$@) \ $$( \ - for file in $(TMPDIR)/rustdoc-$@/*/rust_out; \ - do \ + for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \ [ -x "$$file" ] && printf "%s %s " -object $$file; \ done \ ) \ diff --git a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c index 52af3dceb1..c89f8272b1 100644 --- a/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c +++ b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c @@ -1,4 +1,4 @@ -// Pragma needed cause of gcc bug on windows: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 +// Pragma needed cause of gcc bug on windows: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 #include diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 443e2df357..d3862309ce 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -12,7 +12,6 @@ extern crate rustc_span; extern crate rustc_symbol_mangling; extern crate rustc_target; -use rustc_codegen_ssa::back::linker::LinkerInfo; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CodegenResults, CrateInfo}; use rustc_data_structures::fx::FxHashMap; @@ -38,8 +37,7 @@ impl CodegenBackend for TheBackend { allocator_module: None, metadata_module: None, metadata, - linker_info: LinkerInfo::new(tcx, "fake_target_cpu".to_string()), - crate_info: CrateInfo::new(tcx), + crate_info: CrateInfo::new(tcx, "fake_target_cpu".to_string()), }) } diff --git a/src/test/run-make-fulldeps/pgo-branch-weights/Makefile b/src/test/run-make-fulldeps/pgo-branch-weights/Makefile index 0656346e95..9773e3f1fd 100644 --- a/src/test/run-make-fulldeps/pgo-branch-weights/Makefile +++ b/src/test/run-make-fulldeps/pgo-branch-weights/Makefile @@ -1,25 +1,11 @@ # needs-profiler-support # ignore-windows-gnu -# ignore-aarch64 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works # properly. Since we only have GCC on the CI ignore the test for now. -include ../tools.mk -# This test makes sure that instrumented binaries record the right counts for -# functions being called and branches being taken. We run an instrumented binary -# with an argument that causes a know path through the program and then check -# that the expected counts get added to the use-phase LLVM IR. - -# LLVM doesn't support instrumenting binaries that use SEH: -# https://github.com/rust-lang/rust/issues/61002 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMMON_FLAGS=-Cpanic=abort -endif - # For some very small programs GNU ld seems to not properly handle # instrumentation sections correctly. Neither Gold nor LLD have that problem. ifeq ($(UNAME),Linux) diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile index f1ac39aa0e..a7d5c56163 100644 --- a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile @@ -8,14 +8,6 @@ COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)" -# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC: -# https://github.com/rust-lang/rust/issues/61002 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMPILE_FLAGS+= -Cpanic=abort -endif - all: $(RUSTC) $(COMPILE_FLAGS) test.rs $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile index 3fbfeb09eb..425bfc28a9 100644 --- a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile @@ -4,14 +4,6 @@ COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)" -# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC: -# https://github.com/rust-lang/rust/issues/61002 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMPILE_FLAGS+= -Cpanic=abort -endif - all: $(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs # We expect symbols starting with "__llvm_profile_". diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile index 69b19801bf..6533355be3 100644 --- a/src/test/run-make-fulldeps/pgo-gen/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen/Makefile @@ -8,14 +8,6 @@ COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)" -# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC: -# https://github.com/rust-lang/rust/issues/61002 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMPILE_FLAGS+= -Cpanic=abort -endif - all: $(RUSTC) $(COMPILE_FLAGS) test.rs $(call RUN,test) || exit 1 diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile index 876a9b2c43..c0195dcbb3 100644 --- a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile +++ b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile @@ -6,20 +6,6 @@ -include ../tools.mk -# This test makes sure that indirect call promotion is performed. The test -# programs calls the same function a thousand times through a function pointer. -# Only PGO data provides the information that it actually always is the same -# function. We verify that the indirect call promotion pass inserts a check -# whether it can make a direct call instead of the indirect call. - -# LLVM doesn't support instrumenting binaries that use SEH: -# https://github.com/rust-lang/rust/issues/61002 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMMON_FLAGS=-Cpanic=abort -endif - all: # We don't compile `opaque` with either optimizations or instrumentation. # We don't compile `opaque` with either optimizations or instrumentation. diff --git a/src/test/run-make-fulldeps/pgo-use/Makefile b/src/test/run-make-fulldeps/pgo-use/Makefile index 01bc211df1..d7863c9c58 100644 --- a/src/test/run-make-fulldeps/pgo-use/Makefile +++ b/src/test/run-make-fulldeps/pgo-use/Makefile @@ -18,14 +18,6 @@ COMMON_FLAGS=-Copt-level=2 -Ccodegen-units=1 -Cllvm-args=-disable-preinline -# LLVM doesn't support instrumenting binaries that use SEH: -# https://github.com/rust-lang/rust/issues/61002 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMMON_FLAGS+= -Cpanic=abort -endif - ifeq ($(UNAME),Darwin) # macOS does not have the `tac` command, but `tail -r` does the same thing TAC := tail -r diff --git a/src/test/run-make-fulldeps/print-cfg/Makefile b/src/test/run-make-fulldeps/print-cfg/Makefile index 08303a46d1..013bf3baca 100644 --- a/src/test/run-make-fulldeps/print-cfg/Makefile +++ b/src/test/run-make-fulldeps/print-cfg/Makefile @@ -6,6 +6,8 @@ all: default $(RUSTC) --target i686-pc-windows-msvc --print cfg | $(CGREP) msvc $(RUSTC) --target i686-apple-darwin --print cfg | $(CGREP) macos $(RUSTC) --target i686-unknown-linux-gnu --print cfg | $(CGREP) gnu + $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) target_abi= + $(RUSTC) --target arm-unknown-linux-gnueabihf --print cfg | $(CGREP) eabihf ifdef IS_WINDOWS default: diff --git a/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json index 58e924a989..34357182c2 100644 --- a/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json +++ b/src/test/run-make-fulldeps/rustdoc-target-spec-json-path/target.json @@ -8,7 +8,6 @@ "executables": true, "has-elf-tls": true, "has-rpath": true, - "is-builtin": true, "linker-is-gnu": true, "llvm-target": "x86_64-unknown-linux-gnu", "max-atomic-width": 64, diff --git a/src/test/run-make-fulldeps/rustdoc-themes/Makefile b/src/test/run-make-fulldeps/rustdoc-themes/Makefile index f5a471e66e..f3d07b25c4 100644 --- a/src/test/run-make-fulldeps/rustdoc-themes/Makefile +++ b/src/test/run-make-fulldeps/rustdoc-themes/Makefile @@ -5,6 +5,6 @@ OUTPUT_DIR := "$(TMPDIR)/rustdoc-themes" all: - cp $(S)/src/librustdoc/html/static/themes/light.css $(TMPDIR)/test.css + cp $(S)/src/librustdoc/html/static/css/themes/light.css $(TMPDIR)/test.css $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs --theme $(TMPDIR)/test.css $(HTMLDOCCK) $(OUTPUT_DIR) foo.rs diff --git a/src/test/run-make-fulldeps/target-specs/Makefile b/src/test/run-make-fulldeps/target-specs/Makefile index aff15ce38b..dff7a966c9 100644 --- a/src/test/run-make-fulldeps/target-specs/Makefile +++ b/src/test/run-make-fulldeps/target-specs/Makefile @@ -7,3 +7,5 @@ all: RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm $(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json - + $(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin' + $(RUSTC) foo.rs --target=mismatching-data-layout diff --git a/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json b/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json new file mode 100644 index 0000000000..b36fa993d9 --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/definitely-not-builtin-target.json @@ -0,0 +1,7 @@ +{ + "arch": "x86_64", + "is-builtin": true, + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "llvm-target": "x86_64-unknown-unknown-gnu", + "target-pointer-width": "64" +} diff --git a/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json b/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json new file mode 100644 index 0000000000..d12caaad14 --- /dev/null +++ b/src/test/run-make-fulldeps/target-specs/mismatching-data-layout.json @@ -0,0 +1,6 @@ +{ + "arch": "x86_64", + "data-layout": "e-m:e-i64:16:32:64", + "llvm-target": "x86_64-unknown-unknown-gnu", + "target-pointer-width": "64" +} diff --git a/src/test/run-make/emit-path-unhashed/Makefile b/src/test/run-make/emit-path-unhashed/Makefile new file mode 100644 index 0000000000..b6b2d8af64 --- /dev/null +++ b/src/test/run-make/emit-path-unhashed/Makefile @@ -0,0 +1,37 @@ +-include ../../run-make-fulldeps/tools.mk + +OUT=$(TMPDIR)/emit + +# --emit KIND=PATH should not affect crate hash vs --emit KIND +all: $(OUT)/a/libfoo.rlib $(OUT)/b/libfoo.rlib $(OUT)/c/libfoo.rlib \ + $(TMPDIR)/libfoo.rlib + $(RUSTC) -Zls $(TMPDIR)/libfoo.rlib > $(TMPDIR)/base.txt + $(RUSTC) -Zls $(OUT)/a/libfoo.rlib > $(TMPDIR)/a.txt + $(RUSTC) -Zls $(OUT)/b/libfoo.rlib > $(TMPDIR)/b.txt + $(RUSTC) -Zls $(OUT)/c/libfoo.rlib > $(TMPDIR)/c.txt + + diff $(TMPDIR)/base.txt $(TMPDIR)/a.txt + diff $(TMPDIR)/base.txt $(TMPDIR)/b.txt + + # Different KIND parameters do affect hash. + # diff exits 1 on difference, 2 on trouble + diff $(TMPDIR)/base.txt $(TMPDIR)/c.txt ; test "$$?" -eq 1 + +# Default output name +$(TMPDIR)/libfoo.rlib: foo.rs + $(RUSTC) --emit link foo.rs + +# Output named with -o +$(OUT)/a/libfoo.rlib: foo.rs + mkdir -p $(OUT)/a + $(RUSTC) --emit link -o $@ foo.rs + +# Output named with KIND=PATH +$(OUT)/b/libfoo.rlib: foo.rs + mkdir -p $(OUT)/b + $(RUSTC) --emit link=$@ foo.rs + +# Output multiple kinds +$(OUT)/c/libfoo.rlib: foo.rs + mkdir -p $(OUT)/c + $(RUSTC) --emit link=$@,metadata foo.rs diff --git a/src/test/run-make/emit-path-unhashed/foo.rs b/src/test/run-make/emit-path-unhashed/foo.rs new file mode 100644 index 0000000000..c1bfaa6cab --- /dev/null +++ b/src/test/run-make/emit-path-unhashed/foo.rs @@ -0,0 +1 @@ +#![crate_type = "rlib"] diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/Makefile b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile new file mode 100644 index 0000000000..0f874333fa --- /dev/null +++ b/src/test/run-make/raw-dylib-alt-calling-convention/Makefile @@ -0,0 +1,18 @@ +# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions. + +# only-i686-pc-windows-msvc + +-include ../../run-make-fulldeps/tools.mk + +all: + $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c) + $(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll + $(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs + $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)" + "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt + +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.txt output.txt +else + $(DIFF) output.txt "$(TMPDIR)"/output.txt +endif diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs new file mode 100644 index 0000000000..3710507f5e --- /dev/null +++ b/src/test/run-make/raw-dylib-alt-calling-convention/driver.rs @@ -0,0 +1,5 @@ +extern crate raw_dylib_alt_calling_convention_test; + +fn main() { + raw_dylib_alt_calling_convention_test::library_function(); +} diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/extern.c b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c new file mode 100644 index 0000000000..8f64abf2fb --- /dev/null +++ b/src/test/run-make/raw-dylib-alt-calling-convention/extern.c @@ -0,0 +1,123 @@ +#include +#include + +struct S { + uint8_t x; + int32_t y; +}; + +struct S2 { + int32_t x; + uint8_t y; +}; + +struct S3 { + uint8_t x[5]; +}; + +__declspec(dllexport) void __stdcall stdcall_fn_1(int i) { + printf("stdcall_fn_1(%d)\n", i); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_2(uint8_t i, float f) { + printf("stdcall_fn_2(%d, %.1f)\n", i, f); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_3(double d) { + printf("stdcall_fn_3(%.1f)\n", d); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_4(uint8_t i, uint8_t j, float f) { + printf("stdcall_fn_4(%d, %d, %.1f)\n", i, j, f); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_5(struct S s, int i) { + printf("stdcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +// Test that stdcall support works correctly with the nullable pointer optimization. +__declspec(dllexport) void __stdcall stdcall_fn_6(struct S* s) { + if (s) { + printf("stdcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y); + } else { + printf("stdcall_fn_6(null)\n"); + } + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_7(struct S2 s, int i) { + printf("stdcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +// Verify that we compute the correct amount of space in the argument list for a 5-byte struct. +__declspec(dllexport) void __stdcall stdcall_fn_8(struct S3 s, struct S3 t) { + printf("stdcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n", + s.x[0], s.x[1], s.x[2], s.x[3], s.x[4], + t.x[0], t.x[1], t.x[2], t.x[3], t.x[4] + ); + fflush(stdout); +} + +// test whether f64/double values are aligned on 4-byte or 8-byte boundaries. +__declspec(dllexport) void __stdcall stdcall_fn_9(uint8_t x, double y) { + printf("stdcall_fn_9(%d, %.1f)\n", x, y); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_1(int i) { + printf("fastcall_fn_1(%d)\n", i); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_2(uint8_t i, float f) { + printf("fastcall_fn_2(%d, %.1f)\n", i, f); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_3(double d) { + printf("fastcall_fn_3(%.1f)\n", d); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_4(uint8_t i, uint8_t j, float f) { + printf("fastcall_fn_4(%d, %d, %.1f)\n", i, j, f); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_5(struct S s, int i) { + printf("fastcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_6(struct S* s) { + if (s) { + printf("fastcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y); + } else { + printf("fastcall_fn_6(null)\n"); + } + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_7(struct S2 s, int i) { + printf("fastcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_8(struct S3 s, struct S3 t) { + printf("fastcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n", + s.x[0], s.x[1], s.x[2], s.x[3], s.x[4], + t.x[0], t.x[1], t.x[2], t.x[3], t.x[4] + ); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) { + printf("fastcall_fn_9(%d, %.1f)\n", x, y); + fflush(stdout); +} diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs new file mode 100644 index 0000000000..ba0f1418ab --- /dev/null +++ b/src/test/run-make/raw-dylib-alt-calling-convention/lib.rs @@ -0,0 +1,71 @@ +#![feature(raw_dylib)] + +#[repr(C)] +#[derive(Clone)] +struct S { + x: u8, + y: i32, +} + +#[repr(C)] +#[derive(Clone)] +struct S2 { + x: i32, + y: u8, +} + +#[repr(C)] +#[derive(Clone)] +struct S3 { + x: [u8; 5], +} + +#[link(name = "extern", kind = "raw-dylib")] +extern "stdcall" { + fn stdcall_fn_1(i: i32); + fn stdcall_fn_2(c: u8, f: f32); + fn stdcall_fn_3(d: f64); + fn stdcall_fn_4(i: u8, j: u8, f: f32); + fn stdcall_fn_5(a: S, b: i32); + fn stdcall_fn_6(a: Option<&S>); + fn stdcall_fn_7(a: S2, b: i32); + fn stdcall_fn_8(a: S3, b: S3); + fn stdcall_fn_9(x: u8, y: f64); +} + +#[link(name = "extern", kind = "raw-dylib")] +extern "fastcall" { + fn fastcall_fn_1(i: i32); + fn fastcall_fn_2(c: u8, f: f32); + fn fastcall_fn_3(d: f64); + fn fastcall_fn_4(i: u8, j: u8, f: f32); + fn fastcall_fn_5(a: S, b: i32); + fn fastcall_fn_6(a: Option<&S>); + fn fastcall_fn_7(a: S2, b: i32); + fn fastcall_fn_8(a: S3, b: S3); + fn fastcall_fn_9(x: u8, y: f64); +} + +pub fn library_function() { + unsafe { + stdcall_fn_1(14); + stdcall_fn_2(16, 3.5); + stdcall_fn_3(3.5); + stdcall_fn_4(1, 2, 3.0); + stdcall_fn_5(S { x: 1, y: 2 }, 16); + stdcall_fn_6(Some(&S { x: 10, y: 12 })); + stdcall_fn_7(S2 { x: 15, y: 16 }, 3); + stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + stdcall_fn_9(1, 3.0); + + fastcall_fn_1(14); + fastcall_fn_2(16, 3.5); + fastcall_fn_3(3.5); + fastcall_fn_4(1, 2, 3.0); + fastcall_fn_5(S { x: 1, y: 2 }, 16); + fastcall_fn_6(Some(&S { x: 10, y: 12 })); + fastcall_fn_7(S2 { x: 15, y: 16 }, 3); + fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + fastcall_fn_9(1, 3.0); + } +} diff --git a/src/test/run-make/raw-dylib-alt-calling-convention/output.txt b/src/test/run-make/raw-dylib-alt-calling-convention/output.txt new file mode 100644 index 0000000000..be598a2202 --- /dev/null +++ b/src/test/run-make/raw-dylib-alt-calling-convention/output.txt @@ -0,0 +1,18 @@ +stdcall_fn_1(14) +stdcall_fn_2(16, 3.5) +stdcall_fn_3(3.5) +stdcall_fn_4(1, 2, 3.0) +stdcall_fn_5(S { x: 1, y: 2 }, 16) +stdcall_fn_6(S { x: 10, y: 12 }) +stdcall_fn_7(S2 { x: 15, y: 16 }, 3) +stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }) +stdcall_fn_9(1, 3.0) +fastcall_fn_1(14) +fastcall_fn_2(16, 3.5) +fastcall_fn_3(3.5) +fastcall_fn_4(1, 2, 3.0) +fastcall_fn_5(S { x: 1, y: 2 }, 16) +fastcall_fn_6(S { x: 10, y: 12 }) +fastcall_fn_7(S2 { x: 15, y: 16 }, 3) +fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }) +fastcall_fn_9(1, 3.0) diff --git a/src/test/run-make/raw-dylib/Makefile b/src/test/run-make/raw-dylib-c/Makefile similarity index 96% rename from src/test/run-make/raw-dylib/Makefile rename to src/test/run-make/raw-dylib-c/Makefile index 7ce46fd933..26ab4d3476 100644 --- a/src/test/run-make/raw-dylib/Makefile +++ b/src/test/run-make/raw-dylib-c/Makefile @@ -1,7 +1,6 @@ # Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc -# only-windows -# only-msvc +# only-windows-msvc -include ../../run-make-fulldeps/tools.mk diff --git a/src/test/run-make/raw-dylib/driver.rs b/src/test/run-make/raw-dylib-c/driver.rs similarity index 100% rename from src/test/run-make/raw-dylib/driver.rs rename to src/test/run-make/raw-dylib-c/driver.rs diff --git a/src/test/run-make/raw-dylib/extern_1.c b/src/test/run-make/raw-dylib-c/extern_1.c similarity index 100% rename from src/test/run-make/raw-dylib/extern_1.c rename to src/test/run-make/raw-dylib-c/extern_1.c diff --git a/src/test/run-make/raw-dylib/extern_2.c b/src/test/run-make/raw-dylib-c/extern_2.c similarity index 100% rename from src/test/run-make/raw-dylib/extern_2.c rename to src/test/run-make/raw-dylib-c/extern_2.c diff --git a/src/test/run-make/raw-dylib/lib.rs b/src/test/run-make/raw-dylib-c/lib.rs similarity index 100% rename from src/test/run-make/raw-dylib/lib.rs rename to src/test/run-make/raw-dylib-c/lib.rs diff --git a/src/test/run-make/raw-dylib/output.txt b/src/test/run-make/raw-dylib-c/output.txt similarity index 100% rename from src/test/run-make/raw-dylib/output.txt rename to src/test/run-make/raw-dylib-c/output.txt diff --git a/src/test/run-make/track-path-dep-info/Makefile b/src/test/run-make/track-path-dep-info/Makefile new file mode 100644 index 0000000000..465d374478 --- /dev/null +++ b/src/test/run-make/track-path-dep-info/Makefile @@ -0,0 +1,13 @@ +-include ../../run-make-fulldeps/tools.mk + +# FIXME(eddyb) provide `HOST_RUSTC` and `TARGET_RUSTC` +# instead of hardcoding them everywhere they're needed. +ifeq ($(IS_MUSL_HOST),1) +ADDITIONAL_ARGS := $(RUSTFLAGS) +endif + +all: + # Proc macro + $(BARE_RUSTC) $(ADDITIONAL_ARGS) --out-dir $(TMPDIR) macro_def.rs + EXISTING_PROC_MACRO_ENV=1 $(RUSTC) --emit dep-info macro_use.rs + $(CGREP) "emojis.txt:" < $(TMPDIR)/macro_use.d diff --git a/src/test/run-make/track-path-dep-info/emojis.txt b/src/test/run-make/track-path-dep-info/emojis.txt new file mode 100644 index 0000000000..e1a728461f --- /dev/null +++ b/src/test/run-make/track-path-dep-info/emojis.txt @@ -0,0 +1 @@ +👾👾👾👾👾👾 diff --git a/src/test/run-make/track-path-dep-info/macro_def.rs b/src/test/run-make/track-path-dep-info/macro_def.rs new file mode 100644 index 0000000000..8777ce21f8 --- /dev/null +++ b/src/test/run-make/track-path-dep-info/macro_def.rs @@ -0,0 +1,11 @@ +#![feature(track_path)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn access_tracked_paths(_: TokenStream) -> TokenStream { + tracked_path::path("emojis.txt"); + TokenStream::new() +} diff --git a/src/test/run-make/track-path-dep-info/macro_use.rs b/src/test/run-make/track-path-dep-info/macro_use.rs new file mode 100644 index 0000000000..3c49fd05dd --- /dev/null +++ b/src/test/run-make/track-path-dep-info/macro_use.rs @@ -0,0 +1,6 @@ +#[macro_use] +extern crate macro_def; + +access_tracked_paths!(); + +fn main() {} diff --git a/src/test/run-make/unstable-flag-required/Makefile b/src/test/run-make/unstable-flag-required/Makefile index aa20d6aa4b..a9aad54162 100644 --- a/src/test/run-make/unstable-flag-required/Makefile +++ b/src/test/run-make/unstable-flag-required/Makefile @@ -2,4 +2,4 @@ all: $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr - $(RUSTC) --force-warns dead_code x.rs 2>&1 | diff - force-warns.stderr + $(RUSTC) --force-warn dead_code x.rs 2>&1 | diff - force-warn.stderr diff --git a/src/test/run-make/unstable-flag-required/force-warns.stderr b/src/test/run-make/unstable-flag-required/force-warn.stderr similarity index 65% rename from src/test/run-make/unstable-flag-required/force-warns.stderr rename to src/test/run-make/unstable-flag-required/force-warn.stderr index e0936196a1..1b70dc83bd 100644 --- a/src/test/run-make/unstable-flag-required/force-warns.stderr +++ b/src/test/run-make/unstable-flag-required/force-warn.stderr @@ -1,2 +1,2 @@ -error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warns=lints` +error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warn=lints` diff --git a/src/test/rustdoc-gui/README.md b/src/test/rustdoc-gui/README.md index 499a98a3d2..8efe7a578b 100644 --- a/src/test/rustdoc-gui/README.md +++ b/src/test/rustdoc-gui/README.md @@ -8,5 +8,17 @@ test what's being currently displayed in the web page. You can find more information and its documentation in its [repository][browser-ui-test]. +If you need to have more information on the tests run, you can use `--test-args`: + +```bash +$ ./x.py test src/test/rustdoc-gui --stage 1 --jobs 8 --test-args --debug +``` + +There are three options supported: + + * `--debug`: allows to see puppeteer commands. + * `--no-headless`: disable headless mode so you can see what's going on. + * `--show-text`: by default, text isn't rendered because of issues with fonts, it enables it back. + [browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/ [puppeteer]: https://pptr.dev/ diff --git a/src/test/rustdoc-gui/auto-hide-trait-implementations.goml b/src/test/rustdoc-gui/auto-hide-trait-implementations.goml new file mode 100644 index 0000000000..7b1358fedc --- /dev/null +++ b/src/test/rustdoc-gui/auto-hide-trait-implementations.goml @@ -0,0 +1,13 @@ +// Checks that the setting "auto hide trait implementations" is working as expected. +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) + +// We now set the setting to auto hide all trait implementations. +local-storage: {"rustdoc-auto-hide-trait-implementations": "true" } +// We reload to ensure the trait implementations are collapsed as expected. +reload: + +// We now check that all matching elements don't have the open attributes. +assert-attribute-false: ("#trait-implementations-list > details", {"open": ""}, ALL) diff --git a/src/test/rustdoc-gui/ayu-code-tag-colors.goml b/src/test/rustdoc-gui/ayu-code-tag-colors.goml new file mode 100644 index 0000000000..50af36fa3d --- /dev/null +++ b/src/test/rustdoc-gui/ayu-code-tag-colors.goml @@ -0,0 +1,13 @@ +// The ayu theme has a different color for the "" tags in the doc blocks. We need to +// check that the rule isn't applied on other "" elements. +goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html +// We need to show the text, otherwise the colors aren't "computed" by the web browser. +show-text: true +// We set the theme to ayu. +local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"} +// We reload to get the text appearing and the theme applied. +reload: + +assert-css: (".docblock code", {"color": "rgb(255, 180, 84)"}, ALL) +// It includes variants and the "titles" as well (for example: "impl RefUnwindSafe for AnEnum"). +assert-css: ("div:not(.docblock) > code", {"color": "rgb(197, 197, 197)"}, ALL) diff --git a/src/test/rustdoc-gui/basic-code.goml b/src/test/rustdoc-gui/basic-code.goml new file mode 100644 index 0000000000..27deb2c989 --- /dev/null +++ b/src/test/rustdoc-gui/basic-code.goml @@ -0,0 +1,3 @@ +goto: file://|DOC_PATH|/test_docs/index.html +click: ".srclink" +assert-count: (".line-numbers", 1) diff --git a/src/test/rustdoc-gui/basic.goml b/src/test/rustdoc-gui/basic.goml new file mode 100644 index 0000000000..44fcec3393 --- /dev/null +++ b/src/test/rustdoc-gui/basic.goml @@ -0,0 +1,4 @@ +goto: file://|DOC_PATH|/test_docs/index.html +assert: ("#functions") +goto: ./struct.Foo.html +assert: ("div.type-decl") diff --git a/src/test/rustdoc-gui/check_info_sign_position.goml b/src/test/rustdoc-gui/check_info_sign_position.goml new file mode 100644 index 0000000000..94e3fe79c9 --- /dev/null +++ b/src/test/rustdoc-gui/check_info_sign_position.goml @@ -0,0 +1,9 @@ +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 > .information > .compile_fail", { "margin-top": "16px" }) +// Checks that the other codeblocks don't have this top margin. +assert-css: ("ol > li > .information > .compile_fail", { "margin-top": "0px" }) +assert-css: ("ol > li > .information > .ignore", { "margin-top": "0px" }) +assert-css: (".docblock > .information > .ignore", { "margin-top": "0px" }) diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml new file mode 100644 index 0000000000..ee4dad444e --- /dev/null +++ b/src/test/rustdoc-gui/code-blocks-overflow.goml @@ -0,0 +1,8 @@ +// This test ensures that codeblocks content don't overflow. +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": "796px", "overflow-x": "auto"}, ALL) diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml new file mode 100644 index 0000000000..00326e9bbc --- /dev/null +++ b/src/test/rustdoc-gui/code-sidebar-toggle.goml @@ -0,0 +1,6 @@ +goto: file://|DOC_PATH|/test_docs/index.html +click: ".srclink" +click: "#sidebar-toggle" +wait-for: 500 +fail: true +assert-css: ("#source-sidebar", { "left": "-300px" }) diff --git a/src/test/rustdoc-gui/default-settings.goml b/src/test/rustdoc-gui/default-settings.goml new file mode 100644 index 0000000000..68b674a11f --- /dev/null +++ b/src/test/rustdoc-gui/default-settings.goml @@ -0,0 +1,8 @@ +// This test ensures that the default settings are correctly applied. +// +// The "settings" crate uses "ayu" as default setting, which is what we will +// check. +goto: file://|DOC_PATH|/settings/index.html +// Wait a bit to be sure the default theme is applied. +wait-for: 1000 +assert-css: ("body", {"background-color": "rgb(15, 20, 25)"}) diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml new file mode 100644 index 0000000000..9ab7cd0fa0 --- /dev/null +++ b/src/test/rustdoc-gui/docblock-table-overflow.goml @@ -0,0 +1,9 @@ +// This test ensures that the type declaration content overflow is handled inside the
 directly.
+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 "

" should have the same scroll width. +compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"]) +assert-property: (".top-doc .docblock", {"scrollWidth": "816"}) +// However, since there is overflow in the , its scroll width is bigger. +assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"}) diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml new file mode 100644 index 0000000000..5cf8a5e136 --- /dev/null +++ b/src/test/rustdoc-gui/escape-key.goml @@ -0,0 +1,34 @@ +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") +wait-for: "#search > h1" // The search element is empty before the first search +assert-attribute: ("#search", {"class": "content"}) +assert-attribute: ("#main", {"class": "content hidden"}) +press-key: "Escape" +assert-attribute: ("#search", {"class": "content hidden"}) +assert-attribute: ("#main", {"class": "content"}) + +// Check that focusing the search input brings back the search results +focus: ".search-input" +assert-attribute: ("#search", {"class": "content"}) +assert-attribute: ("#main", {"class": "content hidden"}) + +// Now let's check that when the help popup is displayed and we press Escape, it doesn't +// hide the search results too. +click: "#help-button" +assert-attribute: ("#help", {"class": ""}) +press-key: "Escape" +assert-attribute: ("#help", {"class": "hidden"}) +assert-attribute: ("#search", {"class": "content"}) +assert-attribute: ("#main", {"class": "content hidden"}) + +// Check that Escape hides the search results when a search result is focused. +focus: ".search-input" +assert: ".search-input:focus" +press-key: "ArrowDown" +assert-false: ".search-input:focus" +assert: "#results a:focus" +press-key: "Escape" +assert-attribute: ("#help", {"class": "hidden"}) +assert-attribute: ("#search", {"class": "content hidden"}) +assert-attribute: ("#main", {"class": "content"}) diff --git a/src/test/rustdoc-gui/font-weight.goml b/src/test/rustdoc-gui/font-weight.goml new file mode 100644 index 0000000000..92ad92a8c3 --- /dev/null +++ b/src/test/rustdoc-gui/font-weight.goml @@ -0,0 +1,20 @@ +goto: file://|DOC_PATH|/lib2/struct.Foo.html +// This test checks that the font weight is correctly applied. +assert-css: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"}) +assert-css: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"}) +assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"}) +assert-css: ("#associatedtype\.X > .code-header", {"font-weight": "600"}) +assert-css: ("#associatedconstant\.Y > .code-header", {"font-weight": "600"}) + +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|/lib2/trait.Trait.html +assert-count: (".methods .type", 1) +assert-css: (".methods .type", {"font-weight": "600"}) +assert-count: (".methods .constant", 1) +assert-css: (".methods .constant", {"font-weight": "600"}) +assert-css: (".methods .method", {"font-weight": "600"}) diff --git a/src/test/rustdoc-gui/hash-item-expansion.goml b/src/test/rustdoc-gui/hash-item-expansion.goml new file mode 100644 index 0000000000..42bc1c1002 --- /dev/null +++ b/src/test/rustdoc-gui/hash-item-expansion.goml @@ -0,0 +1,15 @@ +// This test ensures that the element corresponding to the hash is displayed. +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. +assert-attribute: ("#implementations + details", {"open": ""}) +// We collapse it. +click: "#implementations + details > summary" +// We check that it was collapsed as expected. +assert-attribute-false: ("#implementations + details", {"open": ""}) +// To ensure that we will click on the currently hidden method. +assert-text: (".sidebar-links > a", "must_use") +click: ".sidebar-links > a" +// We check that the impl block was opened as expected so that we can see the method. +assert-attribute: ("#implementations + details", {"open": ""}) diff --git a/src/test/rustdoc-gui/impl-default-expansion.goml b/src/test/rustdoc-gui/impl-default-expansion.goml new file mode 100644 index 0000000000..b268ec68d4 --- /dev/null +++ b/src/test/rustdoc-gui/impl-default-expansion.goml @@ -0,0 +1,3 @@ +// This test ensures that the impl blocks are open by default. +goto: file://|DOC_PATH|/test_docs/struct.Foo.html +assert-attribute: ("#main > details.implementors-toggle", {"open": ""}) diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml new file mode 100644 index 0000000000..c9042eb481 --- /dev/null +++ b/src/test/rustdoc-gui/implementors.goml @@ -0,0 +1,16 @@ +// 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 +assert: "#implementors-list" +// There are supposed to be two implementors listed. +assert-count: ("#implementors-list .impl", 2) +// Now we check that both implementors have an anchor, an ID and a similar DOM. +assert: ("#implementors-list .impl:nth-child(1) > a.anchor") +assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever"}) +assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"}) +assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band" + +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" diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml new file mode 100644 index 0000000000..44b79e6091 --- /dev/null +++ b/src/test/rustdoc-gui/item-info-width.goml @@ -0,0 +1,7 @@ +// This test ensures that the item information don't take 100% of the width if unnecessary. +goto: file://|DOC_PATH|/lib2/struct.Foo.html +// 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": "807px"}) +assert-css: (".item-info .stab", {"width": "343px"}) diff --git a/src/test/rustdoc-gui/item-summary-table.goml b/src/test/rustdoc-gui/item-summary-table.goml new file mode 100644 index 0000000000..6bf4e288c4 --- /dev/null +++ b/src/test/rustdoc-gui/item-summary-table.goml @@ -0,0 +1,6 @@ +// This test ensures that
elements aren't display in items summary. +goto: file://|DOC_PATH|/lib2/summary_table/index.html +// We check that we picked the right item first. +assert-text: (".item-table .item-left", "Foo") +// Then we check that its summary is empty. +assert-text: (".item-table .item-right", "") diff --git a/src/test/rustdoc-gui/label-next-to-symbol.goml b/src/test/rustdoc-gui/label-next-to-symbol.goml new file mode 100644 index 0000000000..4fef4e655f --- /dev/null +++ b/src/test/rustdoc-gui/label-next-to-symbol.goml @@ -0,0 +1,36 @@ +// 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 + +// Desktop view +size: (1080, 600) +assert: (".stab.deprecated") +assert: (".stab.portability") + +// make sure that deprecated and portability are different colours +assert-css: (".item-table .item-left .stab.deprecated", { "background-color": "rgb(255, 196, 196)" }) +assert-css: (".item-table .item-left .stab.portability", { "background-color": "rgb(243, 223, 255)" }) + +// table like view +assert-css: (".item-right.docblock-short", { "padding-left": "0px" }) +compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", ".item-left .stab.deprecated", {"y": 2}) +compare-elements-position: (".item-left .stab.deprecated", ".item-left .stab.portability", ("y")) + +// Ensure no wrap +compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", {"y": 2}) +// compare parent elements +compare-elements-position: ("//*[@class='item-left module-item']//a[text()='replaced_function']/..", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']/..", ("y")) + + +// Mobile view +size: (600, 600) +// staggered layout with 2em spacing +assert-css: (".item-right.docblock-short", { "padding-left": "32px" }) +compare-elements-position-near: ("//*[@class='item-left module-item']//a[text()='replaced_function']", ".item-left .stab.deprecated", {"y": 1}) +compare-elements-position: (".item-left .stab.deprecated", ".item-left .stab.portability", ("y")) + +// Ensure wrap +compare-elements-position-near-false: ("//*[@class='item-left module-item']//a[text()='replaced_function']", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", {"y": 12}) +// compare parent elements +compare-elements-position-false: ("//*[@class='item-left module-item']//a[text()='replaced_function']/..", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']/..", ("y")) +compare-elements-position-false: (".item-left .stab.deprecated", "//*[@class='item-right docblock-short']//p[text()='a thing with a label']", ("y")) diff --git a/src/test/rustdoc-gui/list_code_block.goml b/src/test/rustdoc-gui/list_code_block.goml new file mode 100644 index 0000000000..7d3490e9d9 --- /dev/null +++ b/src/test/rustdoc-gui/list_code_block.goml @@ -0,0 +1,3 @@ +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/module-items-font.goml b/src/test/rustdoc-gui/module-items-font.goml new file mode 100644 index 0000000000..817b148bee --- /dev/null +++ b/src/test/rustdoc-gui/module-items-font.goml @@ -0,0 +1,4 @@ +// This test checks that the correct font is used on module items (in index.html pages). +goto: file://|DOC_PATH|/test_docs/index.html +assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, sans-serif'}, ALL) +assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'}, ALL) diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml new file mode 100644 index 0000000000..a098dbd9f1 --- /dev/null +++ b/src/test/rustdoc-gui/search-filter.goml @@ -0,0 +1,17 @@ +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "test") +// Waiting for the search results to appear... +wait-for: "#titles" +assert-text: ("#results .externcrate", "test_docs") +text: (".search-input", "") +// We now want to change the crate filter. +click: "#crate-search" +// We select "lib2" option then press enter to change the filter. +press-key: "ArrowDown" +press-key: "Enter" +// We now make the search again. +write: (".search-input", "test") +// Waiting for the search results to appear... +wait-for: "#titles" +// We check that there is no more "test_docs" appearing. +assert-false: "#results .externcrate" diff --git a/src/test/rustdoc-gui/search-input-mobile.goml b/src/test/rustdoc-gui/search-input-mobile.goml new file mode 100644 index 0000000000..5c95db70ae --- /dev/null +++ b/src/test/rustdoc-gui/search-input-mobile.goml @@ -0,0 +1,11 @@ +// 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 +size: (463, 700) +// We first check that the search input isn't already focused. +assert-false: ("input.search-input:focus") +click: "input.search-input" +reload: +size: (750, 700) +click: "input.search-input" +assert: ("input.search-input:focus") diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml new file mode 100644 index 0000000000..bb8ecb98fa --- /dev/null +++ b/src/test/rustdoc-gui/search-result-color.goml @@ -0,0 +1,41 @@ +// 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 + +// 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: + +// Waiting for the search results to appear... +wait-for: "#titles" +assert-css: ("//*[@class='desc']//*[text()='Just a normal struct.']", {"color": "rgb(197, 197, 197)"}) +assert-css: ("//*[@class='result-name']/*[text()='test_docs::']", {"color": "rgb(0, 150, 207)"}) + +// Checking the color for "keyword". +assert-css: ("//*[@class='result-name']//*[text()='(keyword)']", {"color": "rgb(120, 135, 151)"}) + +// Dark theme +local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"} +reload: + +// Waiting for the search results to appear... +wait-for: "#titles" +assert-css: ("//*[@class='desc']//*[text()='Just a normal struct.']", {"color": "rgb(221, 221, 221)"}) +assert-css: ("//*[@class='result-name']/*[text()='test_docs::']", {"color": "rgb(221, 221, 221)"}) + +// Checking the color for "keyword". +assert-css: ("//*[@class='result-name']//*[text()='(keyword)']", {"color": "rgb(221, 221, 221)"}) + +// Light theme +local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} +reload: + +// Waiting for the search results to appear... +wait-for: "#titles" +assert-css: ("//*[@class='desc']//*[text()='Just a normal struct.']", {"color": "rgb(0, 0, 0)"}) +assert-css: ("//*[@class='result-name']/*[text()='test_docs::']", {"color": "rgb(0, 0, 0)"}) + +// Checking the color for "keyword". +assert-css: ("//*[@class='result-name']//*[text()='(keyword)']", {"color": "rgb(0, 0, 0)"}) diff --git a/src/test/rustdoc-gui/search-result-colors.goml b/src/test/rustdoc-gui/search-result-colors.goml new file mode 100644 index 0000000000..6ed6200615 --- /dev/null +++ b/src/test/rustdoc-gui/search-result-colors.goml @@ -0,0 +1,14 @@ +goto: file://|DOC_PATH|/test_docs/index.html +// We set the theme so we're sure that the corect values will be used, whatever the computer +// this test is running on. +local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"} +// If the text isn't displayed, the browser doesn't compute color style correctly... +show-text: true +// We reload the page so the local storage settings are being used. +reload: +write: (".search-input", "thisisanalias") +// Waiting for the search results to appear... +wait-for: "#titles" +// Checking that the colors for the alias element are the ones expected. +assert-css: (".result-name > .alias", {"color": "rgb(255, 255, 255)"}) +assert-css: (".result-name > .alias > .grey", {"color": "rgb(204, 204, 204)"}) diff --git a/src/test/rustdoc-gui/search-result-description.goml b/src/test/rustdoc-gui/search-result-description.goml new file mode 100644 index 0000000000..d8cb6ee573 --- /dev/null +++ b/src/test/rustdoc-gui/search-result-description.goml @@ -0,0 +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 +// 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 new file mode 100644 index 0000000000..ea94e5640f --- /dev/null +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -0,0 +1,12 @@ +goto: file://|DOC_PATH|/test_docs/index.html +size: (900, 1000) +write: (".search-input", "test") +// Waiting for the search results to appear... +wait-for: "#titles" +// 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": "320px"}) +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. +assert-css: (".search-results div.desc", {"width": "570px"}) diff --git a/src/test/rustdoc-gui/search-result-go-to-first.goml b/src/test/rustdoc-gui/search-result-go-to-first.goml new file mode 100644 index 0000000000..5d709f6588 --- /dev/null +++ b/src/test/rustdoc-gui/search-result-go-to-first.goml @@ -0,0 +1,20 @@ +// This test ensures that the "go_to_first" feature is working as expected. + +// 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") + +// 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 +// Waiting for the search results to appear... +wait-for: "#titles" +assert-text-false: (".fqn .in-band", "Struct test_docs::Foo") +// Ensure that the search results are displayed, not the "normal" content. +assert-css: ("#main", {"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 +// Waiting for the page to load... +wait-for: 500 +assert-text: (".fqn .in-band", "Struct test_docs::Foo") diff --git a/src/test/rustdoc-gui/search-result-keyword.goml b/src/test/rustdoc-gui/search-result-keyword.goml new file mode 100644 index 0000000000..5342d431d9 --- /dev/null +++ b/src/test/rustdoc-gui/search-result-keyword.goml @@ -0,0 +1,10 @@ +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "CookieMonster") +// Waiting for the search results to appear... +wait-for: "#titles" +// Note: The two next assert commands could be merged as one but readability would be +// less good. +// +// Checking that the CSS is displaying " (keyword)" in italic. +assert-text: (".result-name span.keyword > i", "(keyword)") +assert-text: (".result-name span.keyword", "CookieMonster (keyword)") diff --git a/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml b/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml new file mode 100644 index 0000000000..a61ec672ae --- /dev/null +++ b/src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml @@ -0,0 +1,21 @@ +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "Foo") +// Waiting for the search results to appear... +wait-for: "#titles" +assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) + +// To go back to the original "state" +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "-> String") +// Waiting for the search results to appear... +wait-for: "#titles" +// With this search, only the last tab shouldn't be empty so it should be selected. +assert-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"}) + +// To go back to the original "state" +goto: file://|DOC_PATH|/test_docs/index.html +write: (".search-input", "-> Something") +// Waiting for the search results to appear... +wait-for: "#titles" +// With this search, all the tabs are empty so the first one should remain selected. +assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"}) diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml new file mode 100644 index 0000000000..42d945d0eb --- /dev/null +++ b/src/test/rustdoc-gui/shortcuts.goml @@ -0,0 +1,26 @@ +// Check that the various shortcuts are working. +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" +assert: "input.search-input:focus" +press-key: "Escape" +assert-false: "input.search-input:focus" +// We now check for the help popup. +press-key: "?" +assert-css: ("#help", {"display": "flex"}) +assert-false: "#help.hidden" +press-key: "Escape" +assert-css: ("#help.hidden", {"display": "none"}) +// Check for the themes list. +assert-css: ("#theme-choices", {"display": "none"}) +press-key: "t" +assert-css: ("#theme-choices", {"display": "block"}) +press-key: "t" +// We ensure that 't' hides back the menu. +assert-css: ("#theme-choices", {"display": "none"}) +press-key: "t" +assert-css: ("#theme-choices", {"display": "block"}) +press-key: "Escape" +// We ensure that 'Escape' hides the menu too. +assert-css: ("#theme-choices", {"display": "none"}) diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml new file mode 100644 index 0000000000..7138f91667 --- /dev/null +++ b/src/test/rustdoc-gui/sidebar-mobile.goml @@ -0,0 +1,20 @@ +// 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 +// Switching to "mobile view" by reducing the width to 600px. +size: (600, 600) +assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"}) +// Opening the sidebar menu. +click: ".sidebar-menu" +assert-css: (".sidebar-elems", {"display": "block", "left": "0px"}) +// Closing the sidebar menu. +click: ".sidebar-menu" +assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"}) +// 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" +assert-css: (".sidebar-elems", {"display": "block", "left": "0px"}) +// When we tab out of the sidebar, close it. +focus: ".search-input" +assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"}) diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml new file mode 100644 index 0000000000..c8ebb8c56f --- /dev/null +++ b/src/test/rustdoc-gui/sidebar.goml @@ -0,0 +1,60 @@ +goto: file://|DOC_PATH|/test_docs/index.html +assert-text: (".sidebar > .location", "Crate test_docs") +// In modules, we only have one "location" element. +assert-count: (".sidebar .location", 1) +assert-text: (".sidebar-elems > #all-types", "See all test_docs's items") +// We check that we have the crates list and that the "current" on is "test_docs". +assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs") +// And we're also supposed to have the list of items in the current module. +assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords") +assert-text: ("#structs + .item-table .item-left > a", "Foo") +click: "#structs + .item-table .item-left > a" + +// PAGE: struct.Foo.html +assert-count: (".sidebar .location", 2) +// We check that there is no crate listed outside of the top level. +assert-false: ".sidebar-elems > .crate" +// We now go back to the crate page to click on the "lib2" crate link. +goto: file://|DOC_PATH|/test_docs/index.html +click: ".sidebar-elems > .crate > ul > li:first-child > a" + +// PAGE: lib2/index.html +goto: file://|DOC_PATH|/lib2/index.html +assert-text: (".sidebar > .location", "Crate lib2") +// We check that we have the crates list and that the "current" on is now "lib2". +assert-text: (".sidebar-elems > .crate > ul > li > a.current", "lib2") +// We now go to the "foobar" function page. +assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits") +assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions") +assert-text: (".sidebar-elems > .items > ul > 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) +// There is a "
" tag between "in" and "lib2", but it doesn't count as a space. +assert-text: (".sidebar .sidebar-elems .location", "Other items inlib2") +// We check that we don't have the crate list. +assert-false: ".sidebar-elems > .crate" + +goto: ./module/index.html +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 +assert-text: (".sidebar > .location", "Module sub_sub_module") +// We check that we don't have the crate list. +assert-false: ".sidebar-elems > .crate" +assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions") +assert-text: ("#functions + .item-table .item-left > a", "foo") diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml new file mode 100644 index 0000000000..d7bae93c21 --- /dev/null +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -0,0 +1,15 @@ +goto: file://|DOC_PATH|/src/test_docs/lib.rs.html +// Check that we can click on the line number. +click: (40, 224) // This is the position of the span for line 4. +// Unfortunately, "#4" isn't a valid query selector, so we have to go around that limitation +// by instead getting the nth span. +assert-attribute: (".line-numbers > span:nth-child(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"}) +// This is to ensure that the content is correctly align with the line numbers. +compare-elements-position: ("//*[@id='1']", ".rust > span", ("y")) diff --git a/src/test/rustdoc-gui/src/lib2.rs b/src/test/rustdoc-gui/src/lib2.rs deleted file mode 100644 index 73384cbf90..0000000000 --- a/src/test/rustdoc-gui/src/lib2.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod module { - pub mod sub_module { - pub mod sub_sub_module { - pub fn foo() {} - } - pub fn bar() {} - } - pub fn whatever() {} -} - -pub fn foobar() {} diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.lock b/src/test/rustdoc-gui/src/lib2/Cargo.lock new file mode 100644 index 0000000000..a5873ceb32 --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "implementors" +version = "0.1.0" + +[[package]] +name = "lib2" +version = "0.1.0" +dependencies = [ + "implementors", +] diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.toml b/src/test/rustdoc-gui/src/lib2/Cargo.toml new file mode 100644 index 0000000000..2e37f3f667 --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "lib2" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" + +[dependencies] +implementors = { path = "./implementors" } diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock new file mode 100644 index 0000000000..cad99a991a --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "implementors" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml new file mode 100644 index 0000000000..7ef1052c49 --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "implementors" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs new file mode 100644 index 0000000000..6417a6ac5a --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs @@ -0,0 +1,11 @@ +pub trait Whatever { + type Foo; + + fn method() {} +} + +pub struct Struct; + +impl Whatever for Struct { + type Foo = u8; +} diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs new file mode 100644 index 0000000000..cb63a9f600 --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -0,0 +1,77 @@ +// ignore-tidy-linelength + +#![feature(doc_cfg)] + +pub mod module { + pub mod sub_module { + pub mod sub_sub_module { + pub fn foo() {} + } + pub fn bar() {} + } + pub fn whatever() {} +} + +pub fn foobar() {} + +pub type Alias = u32; + +#[doc(cfg(feature = "foo-method"))] +pub struct Foo { + pub x: Alias, +} + +impl Foo { + pub fn a_method(&self) {} +} + +pub trait Trait { + type X; + const Y: u32; + + fn foo() {} +} + +impl Trait for Foo { + type X = u32; + const Y: u32 = 0; +} + + +impl implementors::Whatever for Foo { + type Foo = u32; +} + +pub mod sub_mod { + /// ```txt + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// ``` + /// + /// ``` + /// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + /// ``` + pub struct Foo; +} + +pub mod long_trait { + use std::ops::DerefMut; + + pub trait ALongNameBecauseItHelpsTestingTheCurrentProblem: DerefMut + + From + Send + Sync + AsRef + 'static {} +} + +pub mod long_table { + /// | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | + /// | ----------- | ----------- | ----------- | ----------- | + /// | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | + /// + /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq + pub struct Foo; +} + +pub mod summary_table { + /// | header 1 | header 2 | + /// | -------- | -------- | + /// | content | content | + pub struct Foo; +} diff --git a/src/test/rustdoc-gui/src/settings/.cargo/config.toml b/src/test/rustdoc-gui/src/settings/.cargo/config.toml new file mode 100644 index 0000000000..bbb8d11a2e --- /dev/null +++ b/src/test/rustdoc-gui/src/settings/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustdocflags = ["--default-theme", "ayu"] diff --git a/src/test/rustdoc-gui/src/settings/.package-cache b/src/test/rustdoc-gui/src/settings/.package-cache deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/test/rustdoc-gui/src/settings/Cargo.lock b/src/test/rustdoc-gui/src/settings/Cargo.lock new file mode 100644 index 0000000000..6f0de1ac1e --- /dev/null +++ b/src/test/rustdoc-gui/src/settings/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "settings" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/settings/Cargo.toml b/src/test/rustdoc-gui/src/settings/Cargo.toml new file mode 100644 index 0000000000..c8a211a47c --- /dev/null +++ b/src/test/rustdoc-gui/src/settings/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "settings" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/settings/lib.rs b/src/test/rustdoc-gui/src/settings/lib.rs new file mode 100644 index 0000000000..b76b4321d6 --- /dev/null +++ b/src/test/rustdoc-gui/src/settings/lib.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.lock b/src/test/rustdoc-gui/src/test_docs/Cargo.lock new file mode 100644 index 0000000000..6b80f6e88e --- /dev/null +++ b/src/test/rustdoc-gui/src/test_docs/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "test_docs" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.toml b/src/test/rustdoc-gui/src/test_docs/Cargo.toml new file mode 100644 index 0000000000..7f3c65746f --- /dev/null +++ b/src/test/rustdoc-gui/src/test_docs/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "test_docs" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs similarity index 84% rename from src/test/rustdoc-gui/src/lib.rs rename to src/test/rustdoc-gui/src/test_docs/lib.rs index 5141b6d192..bed72ccb9f 100644 --- a/src/test/rustdoc-gui/src/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -3,7 +3,9 @@ #![crate_name = "test_docs"] #![feature(doc_keyword)] +#![feature(doc_cfg)] +use std::convert::AsRef; use std::fmt; /// Basic function with some code examples: @@ -35,6 +37,12 @@ impl Foo { } } +impl AsRef for Foo { + fn as_ref(&self) -> &str { + "hello" + } +} + /// Just a normal enum. #[doc(alias = "ThisIsAnAlias")] pub enum WhoLetTheDogOut { @@ -90,11 +98,18 @@ pub trait AnotherOne { /// ``` pub fn check_list_code_block() {} +/// a thing with a label +#[deprecated(since = "1.0.0", note = "text why this deprecated")] +#[doc(cfg(unix))] +pub fn replaced_function() {} + +/// Some doc with `code`! pub enum AnEnum { WithVariants { and: usize, sub: usize, variants: usize }, } #[doc(keyword = "CookieMonster")] +/// Some keyword. pub mod keyword {} /// Just some type alias. diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml new file mode 100644 index 0000000000..5221cda2f1 --- /dev/null +++ b/src/test/rustdoc-gui/theme-change.goml @@ -0,0 +1,10 @@ +goto: file://|DOC_PATH|/test_docs/index.html +click: "#theme-picker" +click: "#theme-choices > button:first-child" +wait-for: 500 +// should be the ayu theme so let's check the color +assert-css: ("body", { "background-color": "rgb(15, 20, 25)" }) +click: "#theme-choices > button:last-child" +wait-for: 500 +// should be the light theme so let's check the color +assert-css: ("body", { "background-color": "rgb(255, 255, 255)" }) diff --git a/src/test/rustdoc-gui/toggle-docs-mobile.goml b/src/test/rustdoc-gui/toggle-docs-mobile.goml new file mode 100644 index 0000000000..471d88701d --- /dev/null +++ b/src/test/rustdoc-gui/toggle-docs-mobile.goml @@ -0,0 +1,21 @@ +goto: file://|DOC_PATH|/test_docs/struct.Foo.html +size: (433, 600) +assert-attribute: (".top-doc", {"open": ""}) +click: (4, 280) // This is the position of the top doc comment toggle +assert-attribute-false: (".top-doc", {"open": ""}) +click: (4, 280) +assert-attribute: (".top-doc", {"open": ""}) +// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. +click: (3, 280) +assert-attribute: (".top-doc", {"open": ""}) + +// Now we do the same but with a little bigger width +size: (600, 600) +assert-attribute: (".top-doc", {"open": ""}) +click: (4, 240) // New Y position since all search elements are back on one line. +assert-attribute-false: (".top-doc", {"open": ""}) +click: (4, 240) +assert-attribute: (".top-doc", {"open": ""}) +// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. +click: (3, 240) +assert-attribute: (".top-doc", {"open": ""}) diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml new file mode 100644 index 0000000000..136868f317 --- /dev/null +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -0,0 +1,10 @@ +goto: file://|DOC_PATH|/test_docs/index.html +assert-attribute: ("#main > details.top-doc", {"open": ""}) +click: "#toggle-all-docs" +wait-for: 1000 +// This is now collapsed so there shouldn't be the "open" attribute on details. +assert-attribute-false: ("#main > details.top-doc", {"open": ""}) +click: "#toggle-all-docs" +wait-for: 1000 +// Not collapsed anymore so the "open" attribute should be back. +assert-attribute: ("#main > details.top-doc", {"open": ""}) diff --git a/src/test/rustdoc-gui/toggle-implementors.goml b/src/test/rustdoc-gui/toggle-implementors.goml new file mode 100644 index 0000000000..15521ff0f4 --- /dev/null +++ b/src/test/rustdoc-gui/toggle-implementors.goml @@ -0,0 +1,4 @@ +// This test ensures that the implementors toggle are not open by default. +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 new file mode 100644 index 0000000000..bc97b38c86 --- /dev/null +++ b/src/test/rustdoc-gui/toggled-open-implementations.goml @@ -0,0 +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 +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 new file mode 100644 index 0000000000..739745792c --- /dev/null +++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml @@ -0,0 +1,7 @@ +goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html +assert-text: (".sidebar-links a:nth-of-type(1)", "another") +assert-text: (".sidebar-links a:nth-of-type(2)", "func1") +assert-text: (".sidebar-links a:nth-of-type(3)", "func2") +assert-text: (".sidebar-links a:nth-of-type(4)", "func3") +assert-text: (".sidebar-links a:nth-of-type(5)", "hello") +assert-text: (".sidebar-links a:nth-of-type(6)", "why_not") diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml new file mode 100644 index 0000000000..0a316e220a --- /dev/null +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -0,0 +1,8 @@ +// This test ensures that the type declaration content overflow is handled inside the
 directly.
+goto: file://|DOC_PATH|/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html
+// We set a fixed size so there is no chance of "random" resize.
+size: (1100, 800)
+// Logically, the  scroll width should be the width of the window.
+assert-property: ("body", {"scrollWidth": "1100"})
+// However, since there is overflow in the type declaration, its scroll width is bigger.
+assert-property: (".type-decl pre", {"scrollWidth": "1324"})
diff --git a/src/test/rustdoc-gui/type-weight.rs b/src/test/rustdoc-gui/type-weight.rs
deleted file mode 100644
index 8b6518e7f3..0000000000
--- a/src/test/rustdoc-gui/type-weight.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-goto: file://|DOC_PATH|/test_docs/type.SomeType.html
-assert-all: (".top-block .docblock p", {"font-weight": "400"})
diff --git a/src/test/rustdoc-js-std/alias-4.js b/src/test/rustdoc-js-std/alias-4.js
new file mode 100644
index 0000000000..bf2bb4d298
--- /dev/null
+++ b/src/test/rustdoc-js-std/alias-4.js
@@ -0,0 +1,7 @@
+const QUERY = '<';
+
+const EXPECTED = {
+    'others': [
+        { 'name': 'Ord' },
+    ],
+};
diff --git a/src/test/rustdoc-js-std/typed-query.js b/src/test/rustdoc-js-std/typed-query.js
new file mode 100644
index 0000000000..f656aa7298
--- /dev/null
+++ b/src/test/rustdoc-js-std/typed-query.js
@@ -0,0 +1,12 @@
+// exact-check
+
+const QUERY = 'macro:print';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'print' },
+        { 'path': 'std', 'name': 'eprint' },
+        { 'path': 'std', 'name': 'println' },
+        { 'path': 'std', 'name': 'eprintln' },
+    ],
+};
diff --git a/src/test/rustdoc-js/generics-trait.js b/src/test/rustdoc-js/generics-trait.js
new file mode 100644
index 0000000000..7876622435
--- /dev/null
+++ b/src/test/rustdoc-js/generics-trait.js
@@ -0,0 +1,23 @@
+const QUERY = [
+    'Result',
+    'OtherThingxxxxxxxx',
+];
+
+const EXPECTED = [
+    {
+        'in_args': [
+            { 'path': 'generics_trait', 'name': 'beta' },
+        ],
+        'returned': [
+            { 'path': 'generics_trait', 'name': 'bet' },
+        ],
+    },
+    {
+        'in_args': [
+            { 'path': 'generics_trait', 'name': 'alpha' },
+        ],
+        'returned': [
+            { 'path': 'generics_trait', 'name': 'alef' },
+        ],
+    },
+];
diff --git a/src/test/rustdoc-js/generics-trait.rs b/src/test/rustdoc-js/generics-trait.rs
new file mode 100644
index 0000000000..20db117ccd
--- /dev/null
+++ b/src/test/rustdoc-js/generics-trait.rs
@@ -0,0 +1,8 @@
+pub trait SomeTrait {}
+pub trait OtherThingxxxxxxxx {}
+
+pub fn alef() -> Result { loop {} }
+pub fn bet() -> Result { loop {} }
+
+pub fn alpha(_param: Result) { loop {} }
+pub fn beta(_param: Result) { loop {} }
diff --git a/src/test/rustdoc-js/generics.js b/src/test/rustdoc-js/generics.js
new file mode 100644
index 0000000000..49a80ae236
--- /dev/null
+++ b/src/test/rustdoc-js/generics.js
@@ -0,0 +1,44 @@
+// exact-check
+
+const QUERY = [
+  '"R

"', + '"P"', + 'P', + '"ExtraCreditStructMulti"', +]; + +const EXPECTED = [ + { + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'others': [ + { 'path': 'generics', 'name': 'P' }, + ], + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'returned': [ + { 'path': 'generics', 'name': 'alef' }, + ], + 'in_args': [ + { 'path': 'generics', 'name': 'alpha' }, + ], + }, + { + 'in_args': [ + { 'path': 'generics', 'name': 'extracreditlabhomework' }, + ], + 'returned': [], + }, +]; diff --git a/src/test/rustdoc-js/generics.rs b/src/test/rustdoc-js/generics.rs new file mode 100644 index 0000000000..a0dc086e9f --- /dev/null +++ b/src/test/rustdoc-js/generics.rs @@ -0,0 +1,21 @@ +pub struct P; +pub struct Q; +pub struct R(T); + +// returns test +pub fn alef() -> R

{ loop {} } +pub fn bet() -> R { loop {} } + +// in_args test +pub fn alpha(_x: R

) { loop {} } +pub fn beta(_x: R) { loop {} } + +// test case with multiple appearances of the same type +pub struct ExtraCreditStructMulti { t: T, u: U } +pub struct ExtraCreditInnerMulti {} +pub fn extracreditlabhomework( + _param: ExtraCreditStructMulti +) { loop {} } +pub fn redherringmatchforextracredit( + _param: ExtraCreditStructMulti +) { loop {} } diff --git a/src/test/rustdoc-js/summaries.js b/src/test/rustdoc-js/summaries.js index f175e47342..dfb11e8041 100644 --- a/src/test/rustdoc-js/summaries.js +++ b/src/test/rustdoc-js/summaries.js @@ -5,7 +5,7 @@ const QUERY = ['summaries', 'summaries::Sidebar', 'summaries::Sidebar2']; const EXPECTED = [ { 'others': [ - { 'path': '', 'name': 'summaries', 'desc': 'This summary has a link and code.' }, + { 'path': '', 'name': 'summaries', 'desc': 'This summary has a link, [code], and Sidebar2 intra-doc.' }, ], }, { diff --git a/src/test/rustdoc-js/summaries.rs b/src/test/rustdoc-js/summaries.rs index beb91e286b..418c9f8d0e 100644 --- a/src/test/rustdoc-js/summaries.rs +++ b/src/test/rustdoc-js/summaries.rs @@ -1,9 +1,11 @@ #![crate_type = "lib"] #![crate_name = "summaries"] -//! This *summary* has a [link] and `code`. +//! This *summary* has a [link], [`code`], and [`Sidebar2`] intra-doc. //! -//! This is the second paragraph. +//! This is the second paragraph. It should not be rendered. +//! To test that intra-doc links are resolved properly, [`code`] should render +//! the square brackets, and [`Sidebar2`] should not. //! //! [link]: https://example.com diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.rs b/src/test/rustdoc-ui/intra-doc/field-ice.rs new file mode 100644 index 0000000000..c5d501e38d --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/field-ice.rs @@ -0,0 +1,11 @@ +#![deny(rustdoc::broken_intra_doc_links)] +//~^NOTE the lint level is defined here + +/// [`Foo::bar`] +/// [`Foo::bar()`] +//~^ERROR incompatible link kind for `Foo::bar` +//~|HELP to link to the field, remove the disambiguator +//~|NOTE this link resolved to a field, which is not a function +pub struct Foo { + pub bar: u8 +} diff --git a/src/test/rustdoc-ui/intra-doc/field-ice.stderr b/src/test/rustdoc-ui/intra-doc/field-ice.stderr new file mode 100644 index 0000000000..ccb05b84a7 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/field-ice.stderr @@ -0,0 +1,15 @@ +error: incompatible link kind for `Foo::bar` + --> $DIR/field-ice.rs:5:6 + | +LL | /// [`Foo::bar()`] + | ^^^^^^^^^^^^ help: to link to the field, remove the disambiguator: ``Foo::bar`` + | +note: the lint level is defined here + --> $DIR/field-ice.rs:1:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this link resolved to a field, which is not a function + +error: aborting due to previous error + diff --git a/src/test/rustdoc-ui/nocapture-fail.rs b/src/test/rustdoc-ui/nocapture-fail.rs new file mode 100644 index 0000000000..7706bd1f3e --- /dev/null +++ b/src/test/rustdoc-ui/nocapture-fail.rs @@ -0,0 +1,12 @@ +// check-pass +// compile-flags:--test -Zunstable-options --nocapture +// normalize-stderr-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +/// ```compile_fail +/// fn foo() { +/// Input: 123 +/// } +/// ``` +pub struct Foo; diff --git a/src/test/rustdoc-ui/nocapture-fail.stderr b/src/test/rustdoc-ui/nocapture-fail.stderr new file mode 100644 index 0000000000..16a5ac47cd --- /dev/null +++ b/src/test/rustdoc-ui/nocapture-fail.stderr @@ -0,0 +1,18 @@ +error: struct literal body without path + --> $DIR/nocapture-fail.rs:8:10 + | +LL | fn foo() { + | __________^ +LL | | Input: 123 +LL | | } + | |_^ + | +help: you might have forgotten to add the struct literal inside the block + | +LL | fn foo() { SomeStruct { +LL | Input: 123 +LL | } } + | + +error: aborting due to previous error + diff --git a/src/test/rustdoc-ui/nocapture-fail.stdout b/src/test/rustdoc-ui/nocapture-fail.stdout new file mode 100644 index 0000000000..754f77db53 --- /dev/null +++ b/src/test/rustdoc-ui/nocapture-fail.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/nocapture-fail.rs - Foo (line 7) - compile fail ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/test/rustdoc-ui/nocapture.rs b/src/test/rustdoc-ui/nocapture.rs new file mode 100644 index 0000000000..321f5ca08e --- /dev/null +++ b/src/test/rustdoc-ui/nocapture.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags:--test -Zunstable-options --nocapture +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +/// ``` +/// println!("hello!"); +/// eprintln!("stderr"); +/// ``` +pub struct Foo; diff --git a/src/test/rustdoc-ui/nocapture.stderr b/src/test/rustdoc-ui/nocapture.stderr new file mode 100644 index 0000000000..af6415db3c --- /dev/null +++ b/src/test/rustdoc-ui/nocapture.stderr @@ -0,0 +1 @@ +stderr diff --git a/src/test/rustdoc-ui/nocapture.stdout b/src/test/rustdoc-ui/nocapture.stdout new file mode 100644 index 0000000000..4880e75da7 --- /dev/null +++ b/src/test/rustdoc-ui/nocapture.stdout @@ -0,0 +1,7 @@ + +running 1 test +hello! +test $DIR/nocapture.rs - Foo (line 6) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.rs b/src/test/rustdoc-ui/renamed-lint-still-applies.rs index 05a32d3cc3..a4d3a4b497 100644 --- a/src/test/rustdoc-ui/renamed-lint-still-applies.rs +++ b/src/test/rustdoc-ui/renamed-lint-still-applies.rs @@ -1,7 +1,6 @@ // compile-args: --crate-type lib #![deny(broken_intra_doc_links)] -// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the -// stable channel. +//~^ WARNING renamed to `rustdoc::broken_intra_doc_links` //! [x] //~^ ERROR unresolved link diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr index 3040cad532..8e2a2cdd75 100644 --- a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr +++ b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr @@ -1,13 +1,19 @@ +warning: lint `broken_intra_doc_links` has been renamed to `rustdoc::broken_intra_doc_links` + --> $DIR/renamed-lint-still-applies.rs:2:9 + | +LL | #![deny(broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::broken_intra_doc_links` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + warning: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls` - --> $DIR/renamed-lint-still-applies.rs:8:9 + --> $DIR/renamed-lint-still-applies.rs:7:9 | LL | #![deny(rustdoc::non_autolinks)] | ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls` - | - = note: `#[warn(renamed_and_removed_lints)]` on by default error: unresolved link to `x` - --> $DIR/renamed-lint-still-applies.rs:5:6 + --> $DIR/renamed-lint-still-applies.rs:4:6 | LL | //! [x] | ^ no item named `x` in scope @@ -17,21 +23,20 @@ note: the lint level is defined here | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ - = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(broken_intra_doc_links)]` = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` error: this URL is not a hyperlink - --> $DIR/renamed-lint-still-applies.rs:10:5 + --> $DIR/renamed-lint-still-applies.rs:9:5 | LL | //! http://example.com | ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `` | note: the lint level is defined here - --> $DIR/renamed-lint-still-applies.rs:8:9 + --> $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; 1 warning emitted +error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.rs b/src/test/rustdoc-ui/unknown-renamed-lints.rs index 9096cce127..ddf03dd079 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.rs +++ b/src/test/rustdoc-ui/unknown-renamed-lints.rs @@ -14,8 +14,7 @@ //~^ ERROR renamed to `rustdoc::bare_urls` #![deny(private_doc_tests)] -// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the -// stable channel. +//~^ ERROR renamed to `rustdoc::private_doc_tests` #![deny(rustdoc)] //~^ ERROR removed: use `rustdoc::all` instead diff --git a/src/test/rustdoc-ui/unknown-renamed-lints.stderr b/src/test/rustdoc-ui/unknown-renamed-lints.stderr index 51e06821cf..b105f47d75 100644 --- a/src/test/rustdoc-ui/unknown-renamed-lints.stderr +++ b/src/test/rustdoc-ui/unknown-renamed-lints.stderr @@ -14,7 +14,7 @@ error: unknown lint: `rustdoc::x` --> $DIR/unknown-renamed-lints.rs:7:9 | LL | #![deny(rustdoc::x)] - | ^^^^^^^^^^ + | ^^^^^^^^^^ help: did you mean: `rustdoc::all` error: lint `intra_doc_link_resolution_failure` has been renamed to `rustdoc::broken_intra_doc_links` --> $DIR/unknown-renamed-lints.rs:9:9 @@ -40,19 +40,25 @@ error: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls` LL | #![deny(rustdoc::non_autolinks)] | ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls` +error: lint `private_doc_tests` has been renamed to `rustdoc::private_doc_tests` + --> $DIR/unknown-renamed-lints.rs:16:9 + | +LL | #![deny(private_doc_tests)] + | ^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::private_doc_tests` + error: lint `rustdoc` has been removed: use `rustdoc::all` instead - --> $DIR/unknown-renamed-lints.rs:20:9 + --> $DIR/unknown-renamed-lints.rs:19:9 | LL | #![deny(rustdoc)] | ^^^^^^^ error: unknown lint: `rustdoc::intra_doc_link_resolution_failure` - --> $DIR/unknown-renamed-lints.rs:24:9 + --> $DIR/unknown-renamed-lints.rs:23:9 | LL | #![deny(rustdoc::intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Compilation failed, aborting rustdoc -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index 51cd4a6cbf..6a588fbd56 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -8,14 +8,6 @@ pub extern "C" fn f() {} #[export_name = "bar"] pub extern "C" fn g() {} -// @matches foo/enum.Foo.html '//*[@class="rust enum"]' \ -// '#\[repr\(i64\)\]\n#\[must_use\]' -#[repr(i64)] -#[must_use] -pub enum Foo { - Bar, -} - // @has foo/struct.Repr.html '//*[@class="docblock type-decl"]' '#[repr(C, align(8))]' #[repr(C, align(8))] pub struct Repr; diff --git a/src/test/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs b/src/test/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs new file mode 100644 index 0000000000..1595312228 --- /dev/null +++ b/src/test/rustdoc/auxiliary/cross-crate-hidden-impl-parameter.rs @@ -0,0 +1,5 @@ +#[doc(hidden)] +pub enum HiddenType {} + +#[doc(hidden)] +pub trait HiddenTrait {} diff --git a/src/test/rustdoc/auxiliary/issue-85454.rs b/src/test/rustdoc/auxiliary/issue-85454.rs new file mode 100644 index 0000000000..45664dfc38 --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-85454.rs @@ -0,0 +1,17 @@ +// @has issue_85454/trait.FromResidual.html +// @has - '//pre[@class="rust trait"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }' +pub trait FromResidual::Residual> { + fn from_residual(residual: R) -> Self; +} + +pub trait Try: FromResidual { + type Output; + type Residual; + fn from_output(output: Self::Output) -> Self; + fn branch(self) -> ControlFlow; +} + +pub enum ControlFlow { + Continue(C), + Break(B), +} diff --git a/src/test/rustdoc/auxiliary/issue-86620-1.rs b/src/test/rustdoc/auxiliary/issue-86620-1.rs new file mode 100644 index 0000000000..f6debf6fb4 --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-86620-1.rs @@ -0,0 +1,11 @@ +#![crate_name = "issue_86620_1"] + +pub trait VZip { + fn vzip() -> usize; +} + +impl VZip for T { + fn vzip() -> usize { + 0 + } +} diff --git a/src/test/rustdoc/auxiliary/reexports.rs b/src/test/rustdoc/auxiliary/reexports.rs new file mode 100644 index 0000000000..e04b786a86 --- /dev/null +++ b/src/test/rustdoc/auxiliary/reexports.rs @@ -0,0 +1,42 @@ +#![feature(decl_macro)] + +pub macro addr_of($place:expr) { + &raw const $place +} + +pub macro addr_of_self($place:expr) { + &raw const $place +} + +pub macro addr_of_crate($place:expr) { + &raw const $place +} + +pub struct Foo; +pub struct FooSelf; +pub struct FooCrate; + +pub enum Bar { Foo, } +pub enum BarSelf { Foo, } +pub enum BarCrate { Foo, } + +pub fn foo() {} +pub fn foo_self() {} +pub fn foo_crate() {} + +pub type Type = i32; +pub type TypeSelf = i32; +pub type TypeCrate = i32; + +pub union Union { + a: i8, + b: i8, +} +pub union UnionSelf { + a: i8, + b: i8, +} +pub union UnionCrate { + a: i8, + b: i8, +} diff --git a/src/test/rustdoc/cap-lints.rs b/src/test/rustdoc/cap-lints.rs index b66f75695f..15910e1e90 100644 --- a/src/test/rustdoc/cap-lints.rs +++ b/src/test/rustdoc/cap-lints.rs @@ -3,8 +3,7 @@ // therefore should not concern itself with the lints. #[deny(warnings)] -// @has cap_lints/struct.Foo.html //pre '#[must_use]' -#[must_use] +// @has cap_lints/struct.Foo.html //* 'Struct Foo' pub struct Foo { field: i32, } diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index be5ae93392..fb8ea7e33c 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -7,12 +7,20 @@ #![feature(foo, foo2)] #![feature(staged_api)] -// @has 'foo/fn.foo.html' '//pre' 'pub unsafe fn foo() -> u32' +// @has 'foo/fn.foo.html' '//pre' 'pub fn foo() -> u32' +// @has - '//span[@class="since"]' '1.0.0 (const: unstable)' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="foo", issue = "none")] -pub const unsafe fn foo() -> u32 { 42 } +pub const fn foo() -> u32 { 42 } + +// @has 'foo/fn.foo_unsafe.html' '//pre' 'pub unsafe fn foo_unsafe() -> u32' +// @has - '//span[@class="since"]' '1.0.0 (const: unstable)' +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo", issue = "none")] +pub const unsafe fn foo_unsafe() -> u32 { 42 } // @has 'foo/fn.foo2.html' '//pre' 'pub const fn foo2() -> u32' +// @!has - '//span[@class="since"]' #[unstable(feature = "humans", issue = "none")] pub const fn foo2() -> u32 { 42 } @@ -22,7 +30,9 @@ pub const fn foo2() -> u32 { 42 } #[rustc_const_stable(feature = "rust1", since = "1.0.0")] pub const fn bar2() -> u32 { 42 } + // @has 'foo/fn.foo2_gated.html' '//pre' 'pub const unsafe fn foo2_gated() -> u32' +// @!has - '//span[@class="since"]' #[unstable(feature = "foo2", issue = "none")] pub const unsafe fn foo2_gated() -> u32 { 42 } @@ -33,19 +43,23 @@ pub const unsafe fn foo2_gated() -> u32 { 42 } pub const unsafe fn bar2_gated() -> u32 { 42 } // @has 'foo/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32' +// @!has - '//span[@class="since"]' pub const unsafe fn bar_not_gated() -> u32 { 42 } pub struct Foo; impl Foo { // @has 'foo/struct.Foo.html' '//div[@id="method.gated"]/h4[@class="code-header"]' 'pub fn gated() -> u32' + // @has - '//span[@class="since"]' '1.0.0 (const: unstable)' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="foo", issue = "none")] pub const fn gated() -> u32 { 42 } + // @has 'foo/struct.Foo.html' '//div[@id="method.gated_unsafe"]/h4[@class="code-header"]' 'pub unsafe fn gated_unsafe() -> u32' + // @has - '//span[@class="since"]' '1.0.0 (const: unstable)' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="foo", issue = "none")] - pub const unsafe fn gated() -> u32 { 42 } + pub const unsafe fn gated_unsafe() -> u32 { 42 } // @has 'foo/struct.Foo.html' '//div[@id="method.stable_impl"]/h4[@class="code-header"]' 'pub const fn stable_impl() -> u32' // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)' diff --git a/src/test/rustdoc/const-generics/const-evaluatable-checked.rs b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs new file mode 100644 index 0000000000..1c074fdb3f --- /dev/null +++ b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs @@ -0,0 +1,7 @@ +#![crate_name = "foo"] +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] +// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647 +// @has foo/struct.Ice.html '//pre[@class="rust struct"]' \ +// 'pub struct Ice where [(); N + 1]: ;' +pub struct Ice where [(); N + 1]:; diff --git a/src/test/rustdoc/cross-crate-hidden-impl-parameter.rs b/src/test/rustdoc/cross-crate-hidden-impl-parameter.rs new file mode 100644 index 0000000000..eb2ced2f7f --- /dev/null +++ b/src/test/rustdoc/cross-crate-hidden-impl-parameter.rs @@ -0,0 +1,35 @@ +// Issue #86448: test for cross-crate `doc(hidden)` +#![crate_name = "foo"] + +// aux-build:cross-crate-hidden-impl-parameter.rs +extern crate cross_crate_hidden_impl_parameter; + +pub use ::cross_crate_hidden_impl_parameter::{HiddenType, HiddenTrait}; // OK, not re-exported + +pub enum MyLibType {} + +// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CHiddenType%3E"]' 'impl From for MyLibType' +impl From for MyLibType { + fn from(it: HiddenType) -> MyLibType { + match it {} + } +} + +pub struct T(T); + +// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CT%3CT%3CT%3CT%3CHiddenType%3E%3E%3E%3E%3E"]' 'impl From>>>> for MyLibType' +impl From>>>> for MyLibType { + fn from(it: T>>>) -> MyLibType { + todo!() + } +} + +// @!has foo/enum.MyLibType.html '//*[@id="impl-HiddenTrait"]' 'impl HiddenTrait for MyLibType' +impl HiddenTrait for MyLibType {} + +// @!has foo/struct.T.html '//*[@id="impl-From%3CMyLibType%3E"]' 'impl From for T>>>' +impl From for T>>> { + fn from(it: MyLibType) -> T>>> { + match it {} + } +} diff --git a/src/test/rustdoc/decl_macro.rs b/src/test/rustdoc/decl_macro.rs index ede3f455a2..fe19dadbe0 100644 --- a/src/test/rustdoc/decl_macro.rs +++ b/src/test/rustdoc/decl_macro.rs @@ -9,7 +9,7 @@ pub macro my_macro() { } -// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok:tt)*) {' +// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok : tt) *) {' // @has - //pre '...' // @has - //pre '}' pub macro my_macro_2($($tok:tt)*) { @@ -18,8 +18,8 @@ pub macro my_macro_2($($tok:tt)*) { // @has decl_macro/macro.my_macro_multi.html //pre 'pub macro my_macro_multi {' // @has - //pre '(_) => { ... },' -// @has - //pre '($foo:ident . $bar:expr) => { ... },' -// @has - //pre '($($foo:literal),+) => { ... }' +// @has - //pre '($foo : ident.$bar : expr) => { ... },' +// @has - //pre '($($foo : literal), +) => { ... },' // @has - //pre '}' pub macro my_macro_multi { (_) => { @@ -33,7 +33,7 @@ pub macro my_macro_multi { } } -// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo:expr) {' +// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo : expr) {' // @has - //pre '...' // @has - //pre '}' pub macro by_example_single { @@ -42,12 +42,12 @@ pub macro by_example_single { mod a { mod b { - // @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo:expr) {' + // @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo : expr) {' pub(in super) macro by_example_vis { ($foo:expr) => {} } mod c { - // @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {' + // @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo : expr) {' pub(in a) macro by_example_vis_named { ($foo:expr) => {} } diff --git a/src/test/rustdoc/default-theme.rs b/src/test/rustdoc/default-theme.rs new file mode 100644 index 0000000000..ecb8f0b3b4 --- /dev/null +++ b/src/test/rustdoc/default-theme.rs @@ -0,0 +1,7 @@ +// compile-flags: --default-theme ayu + +// @has default_theme/index.html +// @has - '//script[@id="default-settings"]/@data-theme' 'ayu' +// @has - '//script[@id="default-settings"]/@data-use_system_theme' 'false' + +pub fn whatever() {} diff --git a/src/test/rustdoc/deprecated.rs b/src/test/rustdoc/deprecated.rs index a286856b2c..b3178da98e 100644 --- a/src/test/rustdoc/deprecated.rs +++ b/src/test/rustdoc/deprecated.rs @@ -1,6 +1,6 @@ -// @has deprecated/index.html '//*[@class="docblock-short"]/span[@class="stab deprecated"]' \ +// @has deprecated/index.html '//*[@class="item-left module-item"]/span[@class="stab deprecated"]' \ // 'Deprecated' -// @has - '//*[@class="docblock-short"]' 'Deprecated docs' +// @has - '//*[@class="item-right docblock-short"]' 'Deprecated docs' // @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' @@ -8,7 +8,7 @@ #[deprecated(since = "1.0.0", note = "text")] pub struct S; -// @matches deprecated/index.html '//*[@class="docblock-short"]' '^Docs' +// @matches deprecated/index.html '//*[@class="item-right docblock-short"]' '^Docs' /// Docs pub struct T; diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs index 1fc80b3e76..416ffb6009 100644 --- a/src/test/rustdoc/doc-cfg.rs +++ b/src/test/rustdoc/doc-cfg.rs @@ -12,7 +12,7 @@ pub struct Portable; // @has doc_cfg/unix_only/index.html \ // '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \ // 'This is supported on Unix only.' -// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AARM\Z' +// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z' // @count - '//*[@class="stab portability"]' 2 #[doc(cfg(unix))] pub mod unix_only { @@ -42,7 +42,7 @@ pub mod unix_only { // @has doc_cfg/wasi_only/index.html \ // '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \ // 'This is supported on WASI only.' -// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z' +// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z' // @count - '//*[@class="stab portability"]' 2 #[doc(cfg(target_os = "wasi"))] pub mod wasi_only { @@ -74,7 +74,7 @@ pub mod wasi_only { // the portability header is different on the module view versus the full view // @has doc_cfg/index.html -// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\Aavx\Z' +// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\Aavx\Z' // @has doc_cfg/fn.uses_target_feature.html // @has - '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \ diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs index cec504ea15..886ec67503 100644 --- a/src/test/rustdoc/duplicate-cfg.rs +++ b/src/test/rustdoc/duplicate-cfg.rs @@ -2,13 +2,14 @@ #![feature(doc_cfg)] // @has 'foo/index.html' -// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync$' -// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only' +// @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$' +// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only' // @has 'foo/struct.Foo.html' // @has '-' '//*[@class="stab portability"]' 'sync' #[doc(cfg(feature = "sync"))] #[doc(cfg(feature = "sync"))] +/// my feature sync struct pub struct Foo; // @has 'foo/bar/index.html' diff --git a/src/test/rustdoc/duplicate-flags.rs b/src/test/rustdoc/duplicate-flags.rs new file mode 100644 index 0000000000..dde36df2cf --- /dev/null +++ b/src/test/rustdoc/duplicate-flags.rs @@ -0,0 +1,4 @@ +// compile-flags: --document-private-items --document-private-items + +// @has duplicate_flags/struct.Private.html +struct Private; diff --git a/src/test/rustdoc/ensure-src-link.rs b/src/test/rustdoc/ensure-src-link.rs index 4b6270b26d..6189acb725 100644 --- a/src/test/rustdoc/ensure-src-link.rs +++ b/src/test/rustdoc/ensure-src-link.rs @@ -2,5 +2,5 @@ // This test ensures that the [src] link is present on traits items. -// @has foo/trait.Iterator.html '//div[@id="method.zip"]/a[@class="srclink"]' "[src]" +// @has foo/trait.Iterator.html '//div[@id="method.zip"]//a[@class="srclink"]' "[src]" pub use std::iter::Iterator; diff --git a/src/test/rustdoc/extern-default-method.rs b/src/test/rustdoc/extern-default-method.rs index 810c591c53..efa2025b4b 100644 --- a/src/test/rustdoc/extern-default-method.rs +++ b/src/test/rustdoc/extern-default-method.rs @@ -4,4 +4,6 @@ extern crate rustdoc_extern_default_method as ext; // @count extern_default_method/struct.Struct.html '//*[@id="method.provided"]' 1 +// @has extern_default_method/struct.Struct.html '//div[@id="method.provided"]//a[@class="fnname"]/@href' #method.provided +// @has extern_default_method/struct.Struct.html '//div[@id="method.provided"]//a[@class="anchor"]/@href' #method.provided pub use ext::Struct; diff --git a/src/test/rustdoc/for-lifetime.rs b/src/test/rustdoc/for-lifetime.rs deleted file mode 100644 index 34a7eae31c..0000000000 --- a/src/test/rustdoc/for-lifetime.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![crate_name = "foo"] -#![crate_type = "lib"] - -pub struct Foo { - pub some_func: for<'a> fn(val: &'a i32) -> i32, - pub some_trait: dyn for<'a> Trait<'a>, -} - -// @has foo/struct.Foo.html '//span[@id="structfield.some_func"]' "some_func: for<'a> fn(val: &'a i32) -> i32" -// @has foo/struct.Foo.html '//span[@id="structfield.some_trait"]' "some_trait: dyn Trait<'a>" - -pub trait Trait<'a> {} diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs new file mode 100644 index 0000000000..b75b8de52f --- /dev/null +++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs @@ -0,0 +1,61 @@ +#![crate_name = "foo"] + +// @has foo/trait.Trait.html +pub trait Trait<'x> {} + +// @has foo/fn.test1.html +// @has - '//pre' "pub fn test1() where for<'a> &'a T: Iterator," +pub fn test1() +where + for<'a> &'a T: Iterator, +{ +} + +// @has foo/fn.test2.html +// @has - '//pre' "pub fn test2() where for<'a, 'b> &'a T: Trait<'b>," +pub fn test2() +where + for<'a, 'b> &'a T: Trait<'b>, +{ +} + +// @has foo/fn.test3.html +// @has - '//pre' "pub fn test3() where F: for<'a, 'b> Fn(&'a u8, &'b u8)," +pub fn test3() +where + F: for<'a, 'b> Fn(&'a u8, &'b u8), +{ +} + +// @has foo/struct.Foo.html +pub struct Foo<'a> { + _x: &'a u8, + pub some_trait: &'a dyn for<'b> Trait<'b>, + pub some_func: for<'c> fn(val: &'c i32) -> i32, +} + +// @has - '//span[@id="structfield.some_func"]' "some_func: for<'c> fn(val: &'c i32) -> i32" +// @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>" + +impl<'a> Foo<'a> { + // @has - '//h4[@class="code-header"]' "pub fn bar() where T: Trait<'a>," + pub fn bar() + where + T: Trait<'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>" +impl<'a> B<'a> for dyn for<'b> Trait<'b> {} + +// @has foo/struct.Bar.html +// @has - '//span[@id="structfield.bar"]' "bar: &'a (dyn for<'b> Trait<'b> + Unpin)" +// @has - '//span[@id="structfield.baz"]' "baz: &'a (dyn Unpin + for<'b> Trait<'b>)" +pub struct Bar<'a> { + pub bar: &'a (dyn for<'b> Trait<'b> + Unpin), + pub baz: &'a (dyn Unpin + for<'b> Trait<'b>), +} diff --git a/src/test/rustdoc/inline_cross/macros.rs b/src/test/rustdoc/inline_cross/macros.rs index f9bf982659..9cb933c177 100644 --- a/src/test/rustdoc/inline_cross/macros.rs +++ b/src/test/rustdoc/inline_cross/macros.rs @@ -7,8 +7,10 @@ extern crate macros; -// @has foo/index.html '//*[@class="docblock-short"]/span[@class="stab deprecated"]' Deprecated -// @has - '//*[@class="docblock-short"]/span[@class="stab unstable"]' Experimental +// @has foo/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \ +// Deprecated +// @has - '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \ +// Experimental // @has foo/macro.my_macro.html // @has - '//*[@class="docblock"]' 'docs for my_macro' diff --git a/src/test/rustdoc/internal.rs b/src/test/rustdoc/internal.rs index a1e322fb9a..f316eb24a4 100644 --- a/src/test/rustdoc/internal.rs +++ b/src/test/rustdoc/internal.rs @@ -2,9 +2,11 @@ // Check that the unstable marker is not added for "rustc_private". -// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab unstable"]' -// @!matches internal/index.html '//*[@class="docblock-short"]/span[@class="stab internal"]' -// @matches - '//*[@class="docblock-short"]' 'Docs' +// @!matches internal/index.html \ +// '//*[@class="item-right docblock-short"]/span[@class="stab unstable"]' +// @!matches internal/index.html \ +// '//*[@class="item-right docblock-short"]/span[@class="stab internal"]' +// @matches - '//*[@class="item-right docblock-short"]' 'Docs' // @!has internal/struct.S.html '//*[@class="stab unstable"]' // @!has internal/struct.S.html '//*[@class="stab internal"]' diff --git a/src/test/rustdoc/intra-doc/macros-disambiguators.rs b/src/test/rustdoc/intra-doc/macros-disambiguators.rs new file mode 100644 index 0000000000..cd4caa6a89 --- /dev/null +++ b/src/test/rustdoc/intra-doc/macros-disambiguators.rs @@ -0,0 +1,25 @@ +#![crate_name = "foo"] +#![deny(rustdoc::broken_intra_doc_links)] + +//! [foo!()] +// @has foo/index.html '//a[@href="macro.foo.html"]' 'foo!()' + +//! [foo!{}] +// @has - '//a[@href="macro.foo.html"]' 'foo!{}' + +//! [foo![]](foo![]) +// @has - '//a[@href="macro.foo.html"]' 'foo![]' + +//! [foo1](foo!()) +// @has - '//a[@href="macro.foo.html"]' 'foo1' + +//! [foo2](foo!{}) +// @has - '//a[@href="macro.foo.html"]' 'foo2' + +//! [foo3](foo![]) +// @has - '//a[@href="macro.foo.html"]' 'foo3' + +#[macro_export] +macro_rules! foo { + () => {}; +} diff --git a/src/test/rustdoc/intra-doc/type-alias.rs b/src/test/rustdoc/intra-doc/type-alias.rs new file mode 100644 index 0000000000..f3609ccd0a --- /dev/null +++ b/src/test/rustdoc/intra-doc/type-alias.rs @@ -0,0 +1,19 @@ +// Regression test for issue #86120. + +#![deny(broken_intra_doc_links)] +#![crate_name = "foo"] + +pub struct Foo; + +/// You should really try [`Self::bar`]! +pub type Bar = Foo; + +impl Bar { + pub fn bar() {} +} + +/// The minimum is [`Self::MIN`]. +pub type Int = i32; + +// @has foo/type.Bar.html '//a[@href="struct.Foo.html#method.bar"]' 'Self::bar' +// @has foo/type.Int.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MIN"]' 'Self::MIN' diff --git a/src/test/rustdoc/issue-19055.rs b/src/test/rustdoc/issue-19055.rs deleted file mode 100644 index dbaf744dc4..0000000000 --- a/src/test/rustdoc/issue-19055.rs +++ /dev/null @@ -1,20 +0,0 @@ -// @has issue_19055/trait.Any.html -pub trait Any {} - -impl<'any> Any + 'any { - // @has - '//*[@id="method.is"]' 'fn is' - pub fn is(&self) -> bool { loop {} } - - // @has - '//*[@id="method.downcast_ref"]' 'fn downcast_ref' - pub fn downcast_ref(&self) -> Option<&T> { loop {} } - - // @has - '//*[@id="method.downcast_mut"]' 'fn downcast_mut' - pub fn downcast_mut(&mut self) -> Option<&mut T> { loop {} } -} - -pub trait Foo { - fn foo(&self) {} -} - -// @has - '//*[@id="method.foo"]' 'fn foo' -impl Foo for Any {} diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 11caa34d4b..4e92ae49a2 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -1,17 +1,17 @@ #![feature(staged_api)] -#![doc(issue_tracker_base_url = "http://issue_url/")] +#![doc(issue_tracker_base_url = "https://issue_url/")] #![unstable(feature="test", issue = "32374")] -// @matches issue_32374/index.html '//*[@class="docblock-short"]/span[@class="stab deprecated"]' \ +// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \ // 'Deprecated' -// @matches issue_32374/index.html '//*[@class="docblock-short"]/span[@class="stab unstable"]' \ +// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \ // 'Experimental' -// @matches issue_32374/index.html '//*[@class="docblock-short"]/text()' 'Docs' +// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs' // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \ // '👎 Deprecated since 1.0.0: text' -// @has - 'test #32374' +// @has - 'test #32374' // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \ // '🔬 This is a nightly-only experimental API. \(test\s#32374\)$' /// Docs diff --git a/src/test/rustdoc/issue-46377.rs b/src/test/rustdoc/issue-46377.rs index 236afb20be..4489f038c5 100644 --- a/src/test/rustdoc/issue-46377.rs +++ b/src/test/rustdoc/issue-46377.rs @@ -1,3 +1,3 @@ -// @has 'issue_46377/index.html' '//*[@class="docblock-short"]' 'Check out this struct!' +// @has 'issue_46377/index.html' '//*[@class="item-right docblock-short"]' 'Check out this struct!' /// # Check out this struct! pub struct SomeStruct; diff --git a/src/test/rustdoc/issue-55364.rs b/src/test/rustdoc/issue-55364.rs index bc0ad14be0..70aa10767b 100644 --- a/src/test/rustdoc/issue-55364.rs +++ b/src/test/rustdoc/issue-55364.rs @@ -29,8 +29,8 @@ pub mod subone { // @has - '//section[@id="main"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo' // @has - '//section[@id="main"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar' // Though there should be such links later -// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.foo.html"]' 'foo' -// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td/a[@class="fn"][@href="fn.bar.html"]' 'bar' +// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.foo.html"]' 'foo' +// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.bar.html"]' 'bar' /// See either [foo] or [bar]. pub mod subtwo { @@ -68,8 +68,8 @@ pub mod subthree { // Next we go *deeper* - In order to ensure it's not just "this or parent" // we test `crate::` and a `super::super::...` chain // @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html -// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo' -// @has - '//section[@id="main"]/table//tr[@class="module-item"]/td[@class="docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar' +// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo' +// @has - '//section[@id="main"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar' pub mod subfour { pub mod subfive { pub mod subsix { diff --git a/src/test/rustdoc/issue-85454.rs b/src/test/rustdoc/issue-85454.rs index 45664dfc38..3351b5c835 100644 --- a/src/test/rustdoc/issue-85454.rs +++ b/src/test/rustdoc/issue-85454.rs @@ -1,4 +1,10 @@ -// @has issue_85454/trait.FromResidual.html +// aux-build:issue-85454.rs +// build-aux-docs +#![crate_name = "foo"] + +extern crate issue_85454; + +// @has foo/trait.FromResidual.html // @has - '//pre[@class="rust trait"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }' pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; @@ -15,3 +21,9 @@ pub enum ControlFlow { Continue(C), Break(B), } + +pub mod reexport { + // @has foo/reexport/trait.FromResidual.html + // @has - '//pre[@class="rust trait"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }' + pub use issue_85454::*; +} diff --git a/src/test/rustdoc/issue-86620.rs b/src/test/rustdoc/issue-86620.rs new file mode 100644 index 0000000000..b14e266f7f --- /dev/null +++ b/src/test/rustdoc/issue-86620.rs @@ -0,0 +1,9 @@ +// aux-build:issue-86620-1.rs + +extern crate issue_86620_1; + +use issue_86620_1::*; + +// @!has issue_86620/struct.S.html '//div[@id="method.vzip"]//a[@class="fnname"]/@href' #tymethod.vzip +// @has issue_86620/struct.S.html '//div[@id="method.vzip"]//a[@class="anchor"]/@href' #method.vzip +pub struct S; diff --git a/src/test/rustdoc/macro_rules-matchers.rs b/src/test/rustdoc/macro_rules-matchers.rs new file mode 100644 index 0000000000..5f8340e731 --- /dev/null +++ b/src/test/rustdoc/macro_rules-matchers.rs @@ -0,0 +1,45 @@ +// This is a regression test for issue #86208. +// It is also a general test of macro_rules! display. + +#![crate_name = "foo"] + +// @has 'foo/macro.todo.html' +// @has - '//span[@class="macro"]' 'macro_rules!' +// @has - '//span[@class="ident"]' 'todo' +// Note: count = 2 * ('=' + '>') + '+' = 2 * (1 + 1) + 1 = 5 +// @count - '//pre[@class="rust macro"]//span[@class="op"]' 5 + +// @has - '{ ()' +// @has - '//span[@class="op"]' '=' +// @has - '//span[@class="op"]' '>' +// @has - '{ ... };' + +// @has - '($(' +// @has - '//span[@class="macro-nonterminal"]' '$' +// @has - '//span[@class="macro-nonterminal"]' 'arg' +// @has - ':' +// @has - '//span[@class="ident"]' 'tt' +// @has - '),' +// @has - '//span[@class="op"]' '+' +// @has - ')' +pub use std::todo; + +mod mod1 { + // @has 'foo/macro.macro1.html' + // @has - 'macro_rules!' + // @has - 'macro1' + // @has - '{ ()' + // @has - '($(' + // @has - '//span[@class="macro-nonterminal"]' '$' + // @has - '//span[@class="macro-nonterminal"]' 'arg' + // @has - ':' + // @has - 'expr' + // @has - '),' + // @has - '+' + // @has - ')' + #[macro_export] + macro_rules! macro1 { + () => {}; + ($($arg:expr),+) => { stringify!($($arg),+) }; + } +} diff --git a/src/test/rustdoc/macros.rs b/src/test/rustdoc/macros.rs index ae0cf7a147..1cd454720e 100644 --- a/src/test/rustdoc/macros.rs +++ b/src/test/rustdoc/macros.rs @@ -1,7 +1,7 @@ // @has macros/macro.my_macro.html //pre 'macro_rules! my_macro {' // @has - //pre '() => { ... };' -// @has - //pre '($a:tt) => { ... };' -// @has - //pre '($e:expr) => { ... };' +// @has - //pre '($a : tt) => { ... };' +// @has - //pre '($e : expr) => { ... };' #[macro_export] macro_rules! my_macro { () => []; @@ -12,8 +12,8 @@ macro_rules! my_macro { // Check that exported macro defined in a module are shown at crate root. // @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {' // @has - //pre '() => { ... };' -// @has - //pre '($a:tt) => { ... };' -// @has - //pre '($e:expr) => { ... };' +// @has - //pre '($a : tt) => { ... };' +// @has - //pre '($e : expr) => { ... };' mod sub { #[macro_export] macro_rules! my_sub_macro { diff --git a/src/test/rustdoc/must-use.rs b/src/test/rustdoc/must-use.rs deleted file mode 100644 index b52557fe22..0000000000 --- a/src/test/rustdoc/must-use.rs +++ /dev/null @@ -1,11 +0,0 @@ -// @has must_use/struct.Struct.html //pre '#[must_use]' -#[must_use] -pub struct Struct { - field: i32, -} - -// @has must_use/enum.Enum.html //pre '#[must_use = "message"]' -#[must_use = "message"] -pub enum Enum { - Variant(i32), -} diff --git a/src/test/rustdoc/recursive-deref-sidebar.rs b/src/test/rustdoc/recursive-deref-sidebar.rs new file mode 100644 index 0000000000..fcb636ade8 --- /dev/null +++ b/src/test/rustdoc/recursive-deref-sidebar.rs @@ -0,0 +1,22 @@ +use std::ops::Deref; + +pub struct A {} +impl A { pub fn foo_a(&self) {} } + +pub struct B {} +impl B { pub fn foo_b(&self) {} } + +pub struct C {} +impl C { pub fn foo_c(&self) {} } + +// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_b' +impl Deref for A { + type Target = B; + fn deref(&self) -> &B { todo!() } +} + +// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c' +impl Deref for B { + type Target = C; + fn deref(&self) -> &C { todo!() } +} diff --git a/src/test/rustdoc/recursive-deref.rs b/src/test/rustdoc/recursive-deref.rs new file mode 100644 index 0000000000..3d17bce472 --- /dev/null +++ b/src/test/rustdoc/recursive-deref.rs @@ -0,0 +1,22 @@ +use std::ops::Deref; + +pub struct A; +pub struct B; + +// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A' +impl Deref for A { + type Target = B; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B' +impl Deref for B { + type Target = A; + + fn deref(&self) -> &Self::Target { + panic!() + } +} diff --git a/src/test/rustdoc/reexport-check.rs b/src/test/rustdoc/reexport-check.rs index 9a22903a94..db1f90c699 100644 --- a/src/test/rustdoc/reexport-check.rs +++ b/src/test/rustdoc/reexport-check.rs @@ -4,15 +4,15 @@ extern crate reexport_check; // @!has 'foo/index.html' '//code' 'pub use self::i32;' -// @has 'foo/index.html' '//tr[@class="deprecated module-item"]' 'i32' +// @has 'foo/index.html' '//div[@class="item-left deprecated module-item"]' 'i32' // @has 'foo/i32/index.html' #[allow(deprecated, deprecated_in_future)] pub use std::i32; // @!has 'foo/index.html' '//code' 'pub use self::string::String;' -// @has 'foo/index.html' '//tr[@class="module-item"]' 'String' +// @has 'foo/index.html' '//div[@class="item-left module-item"]' 'String' pub use std::string::String; -// @has 'foo/index.html' '//td[@class="docblock-short"]' 'Docs in original' +// @has 'foo/index.html' '//div[@class="item-right docblock-short"]' 'Docs in original' // this is a no-op, but shows what happens if there's an attribute that isn't a doc-comment #[doc(inline)] pub use reexport_check::S; diff --git a/src/test/rustdoc/reexports-priv.rs b/src/test/rustdoc/reexports-priv.rs new file mode 100644 index 0000000000..ff7424033a --- /dev/null +++ b/src/test/rustdoc/reexports-priv.rs @@ -0,0 +1,53 @@ +// aux-build: reexports.rs +// compile-flags: --document-private-items + +#![crate_name = "foo"] + +extern crate reexports; + +// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {' +pub use reexports::addr_of; +// @has 'foo/macro.addr_of_crate.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {' +pub(crate) use reexports::addr_of_crate; +// @has 'foo/macro.addr_of_self.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_self($place : expr) {' +pub(self) use reexports::addr_of_self; + +// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;' +pub use reexports::Foo; +// @has 'foo/struct.FooCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooCrate;' +pub(crate) use reexports::FooCrate; +// @has 'foo/struct.FooSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooSelf;' +pub(self) use reexports::FooSelf; + +// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {' +pub use reexports::Bar; +// @has 'foo/enum.BarCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarCrate {' +pub(crate) use reexports::BarCrate; +// @has 'foo/enum.BarSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarSelf {' +pub(self) use reexports::BarSelf; + +// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()' +pub use reexports::foo; +// @has 'foo/fn.foo_crate.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_crate()' +pub(crate) use reexports::foo_crate; +// @has 'foo/fn.foo_self.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_self()' +pub(self) use reexports::foo_self; + +// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type =' +pub use reexports::Type; +// @has 'foo/type.TypeCrate.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeCrate =' +pub(crate) use reexports::TypeCrate; +// @has 'foo/type.TypeSelf.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeSelf =' +pub(self) use reexports::TypeSelf; + +// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {' +pub use reexports::Union; +// @has 'foo/union.UnionCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionCrate {' +pub(crate) use reexports::UnionCrate; +// @has 'foo/union.UnionSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionSelf {' +pub(self) use reexports::UnionSelf; + +pub mod foo { + // @!has 'foo/foo/union.Union.html' + use crate::reexports::Union; +} diff --git a/src/test/rustdoc/reexports.rs b/src/test/rustdoc/reexports.rs new file mode 100644 index 0000000000..ab4c5bc743 --- /dev/null +++ b/src/test/rustdoc/reexports.rs @@ -0,0 +1,47 @@ +// aux-build: reexports.rs + +#![crate_name = "foo"] + +extern crate reexports; + +// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {' +pub use reexports::addr_of; +// @!has 'foo/macro.addr_of_crate.html' +pub(crate) use reexports::addr_of_crate; +// @!has 'foo/macro.addr_of_self.html' +pub(self) use reexports::addr_of_self; + +// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;' +pub use reexports::Foo; +// @!has 'foo/struct.FooCrate.html' +pub(crate) use reexports::FooCrate; +// @!has 'foo/struct.FooSelf.html' +pub(self) use reexports::FooSelf; + +// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {' +pub use reexports::Bar; +// @!has 'foo/enum.BarCrate.html' +pub(crate) use reexports::BarCrate; +// @!has 'foo/enum.BarSelf.html' +pub(self) use reexports::BarSelf; + +// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()' +pub use reexports::foo; +// @!has 'foo/fn.foo_crate.html' +pub(crate) use reexports::foo_crate; +// @!has 'foo/fn.foo_self.html' +pub(self) use reexports::foo_self; + +// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type =' +pub use reexports::Type; +// @!has 'foo/type.TypeCrate.html' +pub(crate) use reexports::TypeCrate; +// @!has 'foo/type.TypeSelf.html' +pub(self) use reexports::TypeSelf; + +// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {' +pub use reexports::Union; +// @!has 'foo/union.UnionCrate.html' +pub(crate) use reexports::UnionCrate; +// @!has 'foo/union.UnionSelf.html' +pub(self) use reexports::UnionSelf; diff --git a/src/test/rustdoc/safe-intrinsic.rs b/src/test/rustdoc/safe-intrinsic.rs new file mode 100644 index 0000000000..d3bb8514b7 --- /dev/null +++ b/src/test/rustdoc/safe-intrinsic.rs @@ -0,0 +1,20 @@ +#![feature(intrinsics)] +#![feature(no_core)] + +#![no_core] +#![crate_name = "foo"] + +extern "rust-intrinsic" { + // @has 'foo/fn.abort.html' + // @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !' + pub fn abort() -> !; + // @has 'foo/fn.unreachable.html' + // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !' + pub fn unreachable() -> !; +} + +extern "C" { + // @has 'foo/fn.needs_drop.html' + // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "C" fn needs_drop() -> !' + pub fn needs_drop() -> !; +} diff --git a/src/test/rustdoc/same-crate-hidden-impl-parameter.rs b/src/test/rustdoc/same-crate-hidden-impl-parameter.rs new file mode 100644 index 0000000000..d55393af85 --- /dev/null +++ b/src/test/rustdoc/same-crate-hidden-impl-parameter.rs @@ -0,0 +1,36 @@ +// test for `doc(hidden)` with impl parameters in the same crate. +#![crate_name = "foo"] + +#[doc(hidden)] +pub enum HiddenType {} + +#[doc(hidden)] +pub trait HiddenTrait {} + +pub enum MyLibType {} + +// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CHiddenType%3E"]' 'impl From for MyLibType' +impl From for MyLibType { + fn from(it: HiddenType) -> MyLibType { + match it {} + } +} + +pub struct T(T); + +// @!has foo/enum.MyLibType.html '//*[@id="impl-From%3CT%3CT%3CT%3CT%3CHiddenType%3E%3E%3E%3E%3E"]' 'impl From>>>> for MyLibType' +impl From>>>> for MyLibType { + fn from(it: T>>>) -> MyLibType { + todo!() + } +} + +// @!has foo/enum.MyLibType.html '//*[@id="impl-HiddenTrait"]' 'impl HiddenTrait for MyLibType' +impl HiddenTrait for MyLibType {} + +// @!has foo/struct.T.html '//*[@id="impl-From%3CMyLibType%3E"]' 'impl From for T>>>' +impl From for T>>> { + fn from(it: MyLibType) -> T>>> { + match it {} + } +} diff --git a/src/test/rustdoc/short-docblock-codeblock.rs b/src/test/rustdoc/short-docblock-codeblock.rs index fc8d53ccf3..c6b318b067 100644 --- a/src/test/rustdoc/short-docblock-codeblock.rs +++ b/src/test/rustdoc/short-docblock-codeblock.rs @@ -1,8 +1,8 @@ #![crate_name = "foo"] -// @has foo/index.html '//*[@class="module-item"]//td[@class="docblock-short"]' "" -// @!has foo/index.html '//*[@id="module-item"]//td[@class="docblock-short"]' "Some text." -// @!has foo/index.html '//*[@id="module-item"]//td[@class="docblock-short"]' "let x = 12;" +// @has foo/index.html '//*[@class="item-right docblock-short"]' "" +// @!has foo/index.html '//*[@class="item-right docblock-short"]' "Some text." +// @!has foo/index.html '//*[@class="item-right docblock-short"]' "let x = 12;" /// ``` /// let x = 12; diff --git a/src/test/rustdoc/short-docblock.rs b/src/test/rustdoc/short-docblock.rs new file mode 100644 index 0000000000..74fa783174 --- /dev/null +++ b/src/test/rustdoc/short-docblock.rs @@ -0,0 +1,25 @@ +#![crate_name = "foo"] + +// @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'fooo' +// @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h1' 'fooo' +// @has foo/fn.foo.html '//h1[@id="fooo"]/a[@href="#fooo"]' 'fooo' + +/// # fooo +/// +/// foo +pub fn foo() {} + +// @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'mooood' +// @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h2' 'mooood' +// @has foo/foo/index.html '//h2[@id="mooood"]/a[@href="#mooood"]' 'mooood' + +/// ## mooood +/// +/// foo mod +pub mod foo {} + +// @has foo/index.html '//*[@class="item-right docblock-short"]/p/a[@href=\ +// "https://nougat.world"]/code' 'nougat' + +/// [`nougat`](https://nougat.world) +pub struct Bar; diff --git a/src/test/rustdoc/short-dockblock.rs b/src/test/rustdoc/short-dockblock.rs deleted file mode 100644 index 5493bca54c..0000000000 --- a/src/test/rustdoc/short-dockblock.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![crate_name = "foo"] - -// @has foo/index.html '//*[@class="docblock-short"]/p' 'fooo' -// @!has foo/index.html '//*[@class="docblock-short"]/p/h1' 'fooo' -// @has foo/fn.foo.html '//h1[@id="fooo"]/a[@href="#fooo"]' 'fooo' - -/// # fooo -/// -/// foo -pub fn foo() {} - -// @has foo/index.html '//*[@class="docblock-short"]/p' 'mooood' -// @!has foo/index.html '//*[@class="docblock-short"]/p/h2' 'mooood' -// @has foo/foo/index.html '//h2[@id="mooood"]/a[@href="#mooood"]' 'mooood' - -/// ## mooood -/// -/// foo mod -pub mod foo {} - -// @has foo/index.html '//*[@class="docblock-short"]/p/a[@href=\ -// "https://nougat.world"]/code' 'nougat' - -/// [`nougat`](https://nougat.world) -pub struct Bar; diff --git a/src/test/rustdoc/toggle-item-contents.rs b/src/test/rustdoc/toggle-item-contents.rs index 6e3c0b4c68..8d2046591d 100644 --- a/src/test/rustdoc/toggle-item-contents.rs +++ b/src/test/rustdoc/toggle-item-contents.rs @@ -9,7 +9,7 @@ pub struct PubStruct { // @has 'toggle_item_contents/struct.BigPubStruct.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' pub struct BigPubStruct { pub a: usize, pub b: usize, @@ -28,7 +28,7 @@ pub struct BigPubStruct { // @has 'toggle_item_contents/union.BigUnion.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' pub union BigUnion { pub a: usize, pub b: usize, @@ -62,8 +62,7 @@ pub struct PrivStruct { } // @has 'toggle_item_contents/enum.Enum.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show fields' +// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' pub enum Enum { A, B, C, D { @@ -72,9 +71,18 @@ pub enum Enum { } } +// @has 'toggle_item_contents/enum.EnumStructVariant.html' +// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' +pub enum EnumStructVariant { + A, B, C, + D { + a: u8, + } +} + // @has 'toggle_item_contents/enum.LargeEnum.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show variants' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants' pub enum LargeEnum { A, B, C, D, E, F(u8), G, H, I, J, K, L, M } @@ -90,7 +98,7 @@ pub trait Trait { // @has 'toggle_item_contents/trait.GinormousTrait.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated items' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 16 associated items' pub trait GinormousTrait { type A; type B; @@ -113,7 +121,7 @@ pub trait GinormousTrait { // @has 'toggle_item_contents/trait.HugeTrait.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show associated constants and methods' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods' pub trait HugeTrait { type A; const M: usize = 1; @@ -133,9 +141,30 @@ pub trait HugeTrait { fn bar(); } +// @has 'toggle_item_contents/trait.GiganticTrait.html' +// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method' +pub trait GiganticTrait { + type A; + type B; + type C; + type D; + type E; + type F; + type G; + type H; + type I; + type J; + type K; + type L; + const M: usize = 1; + #[must_use] + fn foo(); +} + // @has 'toggle_item_contents/trait.BigTrait.html' // @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show methods' +// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 14 methods' pub trait BigTrait { type A; #[must_use] diff --git a/src/test/rustdoc/trait-attributes.rs b/src/test/rustdoc/trait-attributes.rs deleted file mode 100644 index d0dfb8759e..0000000000 --- a/src/test/rustdoc/trait-attributes.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![crate_name = "foo"] - - -pub trait Foo { - // @has foo/trait.Foo.html '//div[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]' - #[must_use] - fn foo(); -} - -#[must_use] -pub struct Bar; - -impl Bar { - // @has foo/struct.Bar.html '//div[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]' - #[must_use] - pub fn bar() {} - - // @has foo/struct.Bar.html '//div[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]' - #[must_use] - pub fn bar2() {} -} diff --git a/src/test/rustdoc/trait-impl-items-links-and-anchors.rs b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs index 5b7c04c0d4..4d25835bf0 100644 --- a/src/test/rustdoc/trait-impl-items-links-and-anchors.rs +++ b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs @@ -1,6 +1,6 @@ pub trait MyTrait { type Assoc; - const VALUE: u32; + const VALUE: u32 = 12; fn trait_function(&self); fn defaulted(&self) {} fn defaulted_override(&self) {} @@ -38,23 +38,17 @@ impl MyTrait for Vec { } impl MyTrait for MyStruct { - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="type"]/@href' #associatedtype.Assoc // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3 // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc type Assoc = bool; - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="constant"]/@href' #associatedconstant.VALUE // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3 // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE const VALUE: u32 = 20; - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="fnname"]/@href' #tymethod.trait_function - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="anchor"]/@href' #method.trait_function-2 // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' trait.MyTrait.html#tymethod.trait_function // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function fn trait_function(&self) {} - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="fnname"]/@href' #method.defaulted_override - // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="anchor"]/@href' #method.defaulted_override-3 // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted_override // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override fn defaulted_override(&self) {} @@ -63,3 +57,10 @@ impl MyTrait for MyStruct { } pub struct MyStruct; + +// We check that associated items with default values aren't generated in the implementors list. +impl MyTrait for (u8, u8) { + // @!has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-4"]' + type Assoc = bool; + fn trait_function(&self) {} +} diff --git a/src/test/ui-fulldeps/internal-lints/default_hash_types.rs b/src/test/ui-fulldeps/internal-lints/default_hash_types.rs index 3786c6de7e..795c7d2dcb 100644 --- a/src/test/ui-fulldeps/internal-lints/default_hash_types.rs +++ b/src/test/ui-fulldeps/internal-lints/default_hash_types.rs @@ -1,22 +1,29 @@ // compile-flags: -Z unstable-options #![feature(rustc_private)] +#![deny(rustc::default_hash_types)] extern crate rustc_data_structures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::collections::{HashMap, HashSet}; -#[deny(rustc::default_hash_types)] +mod foo { + pub struct HashMap; +} + fn main() { let _map: HashMap = HashMap::default(); - //~^ ERROR Prefer FxHashMap over HashMap, it has better performance - //~^^ ERROR Prefer FxHashMap over HashMap, it has better performance + //~^ ERROR prefer `FxHashMap` over `HashMap`, it has better performance + //~^^ ERROR prefer `FxHashMap` over `HashMap`, it has better performance let _set: HashSet = HashSet::default(); - //~^ ERROR Prefer FxHashSet over HashSet, it has better performance - //~^^ ERROR Prefer FxHashSet over HashSet, it has better performance + //~^ ERROR prefer `FxHashSet` over `HashSet`, it has better performance + //~^^ ERROR prefer `FxHashSet` over `HashSet`, it has better performance // test that the lint doesn't also match the Fx variants themselves let _fx_map: FxHashMap = FxHashMap::default(); let _fx_set: FxHashSet = FxHashSet::default(); + + // test another struct of the same name + let _ = foo::HashMap; } 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 4f78f51b67..9d13ee89bc 100644 --- a/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr +++ b/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr @@ -1,37 +1,37 @@ -error: Prefer FxHashMap over HashMap, it has better performance - --> $DIR/default_hash_types.rs:12:15 +error: prefer `FxHashMap` over `HashMap`, it has better performance + --> $DIR/default_hash_types.rs:16:41 | LL | let _map: HashMap = HashMap::default(); - | ^^^^^^^ help: use: `FxHashMap` + | ^^^^^^^ | note: the lint level is defined here - --> $DIR/default_hash_types.rs:10:8 + --> $DIR/default_hash_types.rs:4:9 | -LL | #[deny(rustc::default_hash_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +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:12:41 +error: prefer `FxHashMap` over `HashMap`, it has better performance + --> $DIR/default_hash_types.rs:16:15 | LL | let _map: HashMap = HashMap::default(); - | ^^^^^^^ help: use: `FxHashMap` + | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary -error: Prefer FxHashSet over HashSet, it has better performance - --> $DIR/default_hash_types.rs:15:15 +error: prefer `FxHashSet` over `HashSet`, it has better performance + --> $DIR/default_hash_types.rs:19:33 | LL | let _set: HashSet = HashSet::default(); - | ^^^^^^^ help: use: `FxHashSet` + | ^^^^^^^ | = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary -error: Prefer FxHashSet over HashSet, it has better performance - --> $DIR/default_hash_types.rs:15:33 +error: prefer `FxHashSet` over `HashSet`, it has better performance + --> $DIR/default_hash_types.rs:19:15 | LL | let _set: HashSet = HashSet::default(); - | ^^^^^^^ help: use: `FxHashSet` + | ^^^^^^^^^^^^^^^ | = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary diff --git a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs index 448c57da75..bb246de0e5 100644 --- a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -19,7 +19,7 @@ use std::path::Path; mod gravy; pub fn main() { - rustc_span::with_default_session_globals(|| parse()); + rustc_span::create_default_session_globals_then(|| parse()); assert_eq!(gravy::foo(), 10); } diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index 091c834ecc..36ff8b01fd 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -202,7 +202,7 @@ impl MutVisitor for AddParens { } fn main() { - rustc_span::with_default_session_globals(|| run()); + rustc_span::create_default_session_globals_then(|| run()); } fn run() { diff --git a/src/test/ui-fulldeps/session-derive-errors.stderr b/src/test/ui-fulldeps/session-derive-errors.stderr index 2f1debe25b..c7853f5275 100644 --- a/src/test/ui-fulldeps/session-derive-errors.stderr +++ b/src/test/ui-fulldeps/session-derive-errors.stderr @@ -56,6 +56,8 @@ LL | #[message = "This error has a field, and references {name}"] error: invalid format string: expected `'}'` but string was terminated --> $DIR/session-derive-errors.rs:116:1 | +LL | #[derive(SessionDiagnostic)] + | ----------------- in this derive macro expansion LL | #[error = "E0123"] | - because of this opening brace LL | #[message = "This is missing a closing brace: {name"] @@ -67,6 +69,9 @@ LL | #[message = "This is missing a closing brace: {name"] error: invalid format string: unmatched `}` found --> $DIR/session-derive-errors.rs:125:1 | +LL | #[derive(SessionDiagnostic)] + | ----------------- in this derive macro expansion +LL | #[error = "E0123"] LL | #[message = "This is missing an opening brace: name}"] | ^ unmatched `}` in format string | diff --git a/src/test/ui/abi/unsupported.aarch64.stderr b/src/test/ui/abi/unsupported.aarch64.stderr new file mode 100644 index 0000000000..fdeb79f93e --- /dev/null +++ b/src/test/ui/abi/unsupported.aarch64.stderr @@ -0,0 +1,58 @@ +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:24:1 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:26:1 + | +LL | extern "amdgpu-kernel" fn amdgpu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"wasm"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:28:1 + | +LL | extern "wasm" fn wasm() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:33:1 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:35:1 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:37:1 + | +LL | extern "x86-interrupt" fn x86() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:39:1 + | +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unsupported_calling_conventions)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:44:1 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted 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 + +error: aborting due to 6 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0570`. diff --git a/src/test/ui/abi/unsupported.i686.stderr b/src/test/ui/abi/unsupported.i686.stderr new file mode 100644 index 0000000000..81b12653d2 --- /dev/null +++ b/src/test/ui/abi/unsupported.i686.stderr @@ -0,0 +1,39 @@ +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:24:1 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:26:1 + | +LL | extern "amdgpu-kernel" fn amdgpu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"wasm"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:28:1 + | +LL | extern "wasm" fn wasm() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:30:1 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:33:1 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:35:1 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/src/test/ui/abi/unsupported.rs b/src/test/ui/abi/unsupported.rs new file mode 100644 index 0000000000..f0debdcf62 --- /dev/null +++ b/src/test/ui/abi/unsupported.rs @@ -0,0 +1,48 @@ +// revisions: x64 i686 aarch64 +// +// [x64] needs-llvm-components: x86 +// [x64]compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +// [i686] needs-llvm-components: x86 +// [i686]compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib +// [aarch64] needs-llvm-components: aarch64 +// [aarch64]compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib +#![no_core] +#![feature( + no_core, + lang_items, + abi_ptx, + abi_msp430_interrupt, + abi_avr_interrupt, + abi_thiscall, + abi_amdgpu_kernel, + wasm_abi, + abi_x86_interrupt +)] +#[lang="sized"] +trait Sized { } + +extern "ptx-kernel" fn ptx() {} +//~^ ERROR is not a supported ABI +extern "amdgpu-kernel" fn amdgpu() {} +//~^ ERROR is not a supported ABI +extern "wasm" fn wasm() {} +//~^ ERROR is not a supported ABI +extern "aapcs" fn aapcs() {} +//[x64]~^ ERROR is not a supported ABI +//[i686]~^^ ERROR is not a supported ABI +extern "msp430-interrupt" fn msp430() {} +//~^ ERROR is not a supported ABI +extern "avr-interrupt" fn avr() {} +//~^ ERROR is not a supported ABI +extern "x86-interrupt" fn x86() {} +//[aarch64]~^ ERROR is not a supported ABI +extern "stdcall" fn stdcall() {} +//[x64]~^ WARN use of calling convention not supported +//[x64]~^^ WARN this was previously accepted +//[aarch64]~^^^ WARN use of calling convention not supported +//[aarch64]~^^^^ WARN this was previously accepted +extern "thiscall" fn thiscall() {} +//[x64]~^ WARN use of calling convention not supported +//[x64]~^^ WARN this was previously accepted +//[aarch64]~^^^ WARN use of calling convention not supported +//[aarch64]~^^^^ WARN this was previously accepted diff --git a/src/test/ui/abi/unsupported.x64.stderr b/src/test/ui/abi/unsupported.x64.stderr new file mode 100644 index 0000000000..60d067acf1 --- /dev/null +++ b/src/test/ui/abi/unsupported.x64.stderr @@ -0,0 +1,58 @@ +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:24:1 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:26:1 + | +LL | extern "amdgpu-kernel" fn amdgpu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"wasm"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:28:1 + | +LL | extern "wasm" fn wasm() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:30:1 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:33:1 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:35:1 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:39:1 + | +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unsupported_calling_conventions)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:44:1 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted 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 + +error: aborting due to 6 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0570`. diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr index 0851e1a5e9..628b48a45d 100644 --- a/src/test/ui/allocator/not-an-allocator.stderr +++ b/src/test/ui/allocator/not-an-allocator.stderr @@ -1,37 +1,61 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/not-an-allocator.rs:2:1 | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | - = note: required by `std::alloc::GlobalAlloc::alloc` +note: required by `std::alloc::GlobalAlloc::alloc` + --> $SRC_DIR/core/src/alloc/global.rs:LL:COL + | +LL | unsafe fn alloc(&self, layout: Layout) -> *mut u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/not-an-allocator.rs:2:1 | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | - = note: required by `std::alloc::GlobalAlloc::dealloc` +note: required by `std::alloc::GlobalAlloc::dealloc` + --> $SRC_DIR/core/src/alloc/global.rs:LL:COL + | +LL | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/not-an-allocator.rs:2:1 | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | - = note: required by `std::alloc::GlobalAlloc::realloc` +note: required by `std::alloc::GlobalAlloc::realloc` + --> $SRC_DIR/core/src/alloc/global.rs:LL:COL + | +LL | unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/not-an-allocator.rs:2:1 | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion LL | static A: usize = 0; | ^^^^^^^^^^^^^^^^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | - = note: required by `std::alloc::GlobalAlloc::alloc_zeroed` +note: required by `std::alloc::GlobalAlloc::alloc_zeroed` + --> $SRC_DIR/core/src/alloc/global.rs:LL:COL + | +LL | unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/allocator/two-allocators.stderr b/src/test/ui/allocator/two-allocators.stderr index dbf1054f10..7a914c2a39 100644 --- a/src/test/ui/allocator/two-allocators.stderr +++ b/src/test/ui/allocator/two-allocators.stderr @@ -4,6 +4,7 @@ error: cannot define multiple global allocators LL | static A: System = System; | -------------------------- previous global allocator defined here LL | #[global_allocator] + | ------------------- in this procedural macro expansion LL | static B: System = System; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator | diff --git a/src/test/ui/anon-params/anon-params-deprecated.fixed b/src/test/ui/anon-params/anon-params-deprecated.fixed index d288bba595..c09e207708 100644 --- a/src/test/ui/anon-params/anon-params-deprecated.fixed +++ b/src/test/ui/anon-params/anon-params-deprecated.fixed @@ -7,13 +7,13 @@ trait T { fn foo(_: i32); //~ WARNING anonymous parameters are deprecated - //~| WARNING hard error + //~| WARNING this is accepted in the current edition fn bar_with_default_impl(_: String, _: String) {} //~^ WARNING anonymous parameters are deprecated - //~| WARNING hard error + //~| WARNING this is accepted in the current edition //~| WARNING anonymous parameters are deprecated - //~| WARNING hard error + //~| WARNING this is accepted in the current edition } fn main() {} diff --git a/src/test/ui/anon-params/anon-params-deprecated.rs b/src/test/ui/anon-params/anon-params-deprecated.rs index d677e0c32b..6f7385da04 100644 --- a/src/test/ui/anon-params/anon-params-deprecated.rs +++ b/src/test/ui/anon-params/anon-params-deprecated.rs @@ -7,13 +7,13 @@ trait T { fn foo(i32); //~ WARNING anonymous parameters are deprecated - //~| WARNING hard error + //~| WARNING this is accepted in the current edition fn bar_with_default_impl(String, String) {} //~^ WARNING anonymous parameters are deprecated - //~| WARNING hard error + //~| WARNING this is accepted in the current edition //~| WARNING anonymous parameters are deprecated - //~| WARNING hard error + //~| WARNING this is accepted in the current edition } fn main() {} diff --git a/src/test/ui/anon-params/anon-params-deprecated.stderr b/src/test/ui/anon-params/anon-params-deprecated.stderr index c1bf5f690e..98d52d659a 100644 --- a/src/test/ui/anon-params/anon-params-deprecated.stderr +++ b/src/test/ui/anon-params/anon-params-deprecated.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![warn(anonymous_parameters)] | ^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #41686 warning: anonymous parameters are deprecated and will be removed in the next edition. @@ -18,7 +18,7 @@ warning: anonymous parameters are deprecated and will be removed in the next edi LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #41686 warning: anonymous parameters are deprecated and will be removed in the next edition. @@ -27,7 +27,7 @@ warning: anonymous parameters are deprecated and will be removed in the next edi LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #41686 warning: 3 warnings emitted diff --git a/src/test/ui/array-slice-vec/slice-panic-1.rs b/src/test/ui/array-slice-vec/slice-panic-1.rs index 8b27d055e2..4134c62377 100644 --- a/src/test/ui/array-slice-vec/slice-panic-1.rs +++ b/src/test/ui/array-slice-vec/slice-panic-1.rs @@ -17,7 +17,7 @@ impl Drop for Foo { fn foo() { let x: &[_] = &[Foo, Foo]; - &x[3..4]; + let _ = &x[3..4]; } fn main() { diff --git a/src/test/ui/array-slice-vec/slice-panic-2.rs b/src/test/ui/array-slice-vec/slice-panic-2.rs index 2ee564cadb..2f7178fb3e 100644 --- a/src/test/ui/array-slice-vec/slice-panic-2.rs +++ b/src/test/ui/array-slice-vec/slice-panic-2.rs @@ -21,7 +21,7 @@ fn bar() -> usize { fn foo() { let x: &[_] = &[Foo, Foo]; - &x[3..bar()]; + let _ = &x[3..bar()]; } fn main() { diff --git a/src/test/ui/array-slice-vec/slice.rs b/src/test/ui/array-slice-vec/slice.rs index 14e1ddf52e..a514e20277 100644 --- a/src/test/ui/array-slice-vec/slice.rs +++ b/src/test/ui/array-slice-vec/slice.rs @@ -67,14 +67,14 @@ impl IndexMut for Foo { fn main() { let mut x = Foo; - &x[..]; - &x[Foo..]; - &x[..Foo]; - &x[Foo..Foo]; - &mut x[..]; - &mut x[Foo..]; - &mut x[..Foo]; - &mut x[Foo..Foo]; + let _ = &x[..]; + let _ = &x[Foo..]; + let _ = &x[..Foo]; + let _ = &x[Foo..Foo]; + let _ = &mut x[..]; + let _ = &mut x[Foo..]; + let _ = &mut x[..Foo]; + let _ = &mut x[Foo..Foo]; unsafe { assert_eq!(COUNT, 8); } diff --git a/src/test/ui/asm/bad-options.stderr b/src/test/ui/asm/bad-options.stderr index 4e27a6e2cb..9039483be4 100644 --- a/src/test/ui/asm/bad-options.stderr +++ b/src/test/ui/asm/bad-options.stderr @@ -28,41 +28,41 @@ error: asm outputs are not allowed with the `noreturn` option LL | asm!("{}", out(reg) foo, options(noreturn)); | ^^^^^^^^^^^^ -error: expected one of `)` or `att_syntax`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/bad-options.rs:20:25 | LL | global_asm!("", options(nomem)); - | ^^^^^ expected one of `)` or `att_syntax` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)` or `att_syntax`, found `readonly` +error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` --> $DIR/bad-options.rs:22:25 | LL | global_asm!("", options(readonly)); - | ^^^^^^^^ expected one of `)` or `att_syntax` + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)` or `att_syntax`, found `noreturn` +error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` --> $DIR/bad-options.rs:24:25 | LL | global_asm!("", options(noreturn)); - | ^^^^^^^^ expected one of `)` or `att_syntax` + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)` or `att_syntax`, found `pure` +error: expected one of `)`, `att_syntax`, or `raw`, found `pure` --> $DIR/bad-options.rs:26:25 | LL | global_asm!("", options(pure)); - | ^^^^ expected one of `)` or `att_syntax` + | ^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)` or `att_syntax`, found `nostack` +error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` --> $DIR/bad-options.rs:28:25 | LL | global_asm!("", options(nostack)); - | ^^^^^^^ expected one of `)` or `att_syntax` + | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)` or `att_syntax`, found `preserves_flags` +error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` --> $DIR/bad-options.rs:30:25 | LL | global_asm!("", options(preserves_flags)); - | ^^^^^^^^^^^^^^^ expected one of `)` or `att_syntax` + | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: aborting due to 11 previous errors diff --git a/src/test/ui/asm/bad-reg.rs b/src/test/ui/asm/bad-reg.rs index da302b2487..06af08fab8 100644 --- a/src/test/ui/asm/bad-reg.rs +++ b/src/test/ui/asm/bad-reg.rs @@ -31,15 +31,26 @@ fn main() { //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand asm!("", in("ip") foo); //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand - asm!("", in("st(2)") foo); - //~^ ERROR invalid register `st(2)`: x87 registers are not currently supported as operands - asm!("", in("mm0") foo); - //~^ ERROR invalid register `mm0`: MMX registers are not currently supported as operands asm!("", in("k0") foo); //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand asm!("", in("ah") foo); //~^ ERROR invalid register `ah`: high byte registers cannot be used as an operand + asm!("", in("st(2)") foo); + //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output + asm!("", in("mm0") foo); + //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output + asm!("", out("st(2)") _); + asm!("", out("mm0") _); + asm!("{}", in(x87_reg) foo); + //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output + asm!("{}", in(mmx_reg) foo); + //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output + asm!("{}", out(x87_reg) _); + //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output + asm!("{}", out(mmx_reg) _); + //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output + // Explicit register conflicts // (except in/lateout which don't conflict) diff --git a/src/test/ui/asm/bad-reg.stderr b/src/test/ui/asm/bad-reg.stderr index 2bfb4854c3..14740bf62f 100644 --- a/src/test/ui/asm/bad-reg.stderr +++ b/src/test/ui/asm/bad-reg.stderr @@ -76,32 +76,56 @@ error: invalid register `ip`: the instruction pointer cannot be used as an opera LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ -error: invalid register `st(2)`: x87 registers are not currently supported as operands for inline asm +error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm --> $DIR/bad-reg.rs:34:18 | +LL | asm!("", in("k0") foo); + | ^^^^^^^^^^^^ + +error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64 + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", in("ah") foo); + | ^^^^^^^^^^^^ + +error: register class `x87_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:39:18 + | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ -error: invalid register `mm0`: MMX registers are not currently supported as operands for inline asm - --> $DIR/bad-reg.rs:36:18 +error: register class `mmx_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ -error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 +error: register class `x87_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:45:20 | -LL | asm!("", in("k0") foo); - | ^^^^^^^^^^^^ +LL | asm!("{}", in(x87_reg) foo); + | ^^^^^^^^^^^^^^^ -error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64 - --> $DIR/bad-reg.rs:40:18 +error: register class `mmx_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:47:20 | -LL | asm!("", in("ah") foo); - | ^^^^^^^^^^^^ +LL | asm!("{}", in(mmx_reg) foo); + | ^^^^^^^^^^^^^^^ + +error: register class `x87_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:49:20 + | +LL | asm!("{}", out(x87_reg) _); + | ^^^^^^^^^^^^^^ + +error: register class `mmx_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:51:20 + | +LL | asm!("{}", out(mmx_reg) _); + | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `ax` - --> $DIR/bad-reg.rs:46:33 + --> $DIR/bad-reg.rs:57:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -109,7 +133,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `ax` error: register `ax` conflicts with register `ax` - --> $DIR/bad-reg.rs:48:33 + --> $DIR/bad-reg.rs:59:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `ax` @@ -117,13 +141,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `ax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:51:34 + --> $DIR/bad-reg.rs:62:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -131,7 +155,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:53:34 + --> $DIR/bad-reg.rs:64:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -139,10 +163,10 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:53:18 + --> $DIR/bad-reg.rs:64:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 23 previous errors diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr index b1685bd4e0..bf6ea6b67f 100644 --- a/src/test/ui/asm/inline-syntax.arm.stderr +++ b/src/test/ui/asm/inline-syntax.arm.stderr @@ -13,7 +13,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:29:15 + --> $DIR/inline-syntax.rs:31:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^ @@ -25,7 +25,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:32:15 + --> $DIR/inline-syntax.rs:34:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^ @@ -37,7 +37,7 @@ LL | .intel_syntax aaa noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:35:15 + --> $DIR/inline-syntax.rs:37:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^ @@ -49,7 +49,7 @@ LL | .att_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:40:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^ @@ -61,7 +61,7 @@ LL | .att_syntax bbb noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:41:15 + --> $DIR/inline-syntax.rs:43:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^ @@ -73,7 +73,7 @@ LL | .intel_syntax noprefix; nop | ^ error: unknown directive - --> $DIR/inline-syntax.rs:47:13 + --> $DIR/inline-syntax.rs:49:13 | LL | .intel_syntax noprefix | ^ diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs index 2d54ef7bd6..481990398f 100644 --- a/src/test/ui/asm/inline-syntax.rs +++ b/src/test/ui/asm/inline-syntax.rs @@ -1,11 +1,13 @@ -// needs-llvm-components: arm // revisions: x86_64 arm //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu //[x86_64] check-pass +//[x86_64] needs-llvm-components: x86 //[x86_64_allowed] compile-flags: --target x86_64-unknown-linux-gnu //[x86_64_allowed] check-pass +//[x86_64_allowed] needs-llvm-components: x86 //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf //[arm] build-fail +//[arm] needs-llvm-components: arm #![feature(no_core, lang_items, rustc_attrs)] #![crate_type = "rlib"] diff --git a/src/test/ui/asm/inline-syntax.x86_64.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr index 59c9519432..dcbc17bb26 100644 --- a/src/test/ui/asm/inline-syntax.x86_64.stderr +++ b/src/test/ui/asm/inline-syntax.x86_64.stderr @@ -1,5 +1,5 @@ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:55:14 + --> $DIR/inline-syntax.rs:57:14 | LL | global_asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop"); = note: `#[warn(bad_asm_style)]` on by default warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:29:15 + --> $DIR/inline-syntax.rs:31:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:32:15 + --> $DIR/inline-syntax.rs:34:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:35:15 + --> $DIR/inline-syntax.rs:37:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:40:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:41:15 + --> $DIR/inline-syntax.rs:43:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:47:13 + --> $DIR/inline-syntax.rs:49:13 | LL | .intel_syntax noprefix | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-82869.rs b/src/test/ui/asm/issue-82869.rs similarity index 100% rename from src/test/ui/issues/issue-82869.rs rename to src/test/ui/asm/issue-82869.rs diff --git a/src/test/ui/issues/issue-82869.stderr b/src/test/ui/asm/issue-82869.stderr similarity index 100% rename from src/test/ui/issues/issue-82869.stderr rename to src/test/ui/asm/issue-82869.stderr diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr index afd262b851..33dca61dc8 100644 --- a/src/test/ui/asm/parse-error.stderr +++ b/src/test/ui/asm/parse-error.stderr @@ -64,11 +64,11 @@ error: argument to `sym` must be a path expression LL | asm!("{}", sym foo + bar); | ^^^^^^^^^ -error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo` +error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` --> $DIR/parse-error.rs:31:26 | LL | asm!("", options(foo)); - | ^^^ expected one of 8 possible tokens + | ^^^ expected one of 9 possible tokens error: expected one of `)` or `,`, found `foo` --> $DIR/parse-error.rs:33:32 @@ -76,11 +76,11 @@ error: expected one of `)` or `,`, found `foo` LL | asm!("", options(nomem foo)); | ^^^ expected one of `)` or `,` -error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo` +error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` --> $DIR/parse-error.rs:35:33 | LL | asm!("", options(nomem, foo)); - | ^^^ expected one of 8 possible tokens + | ^^^ expected one of 9 possible tokens error: arguments are not allowed after options --> $DIR/parse-error.rs:37:31 @@ -200,23 +200,23 @@ error: expected one of `,`, `.`, `?`, or an operator, found `FOO` LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator -error: expected one of `)` or `att_syntax`, found `FOO` +error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` --> $DIR/parse-error.rs:81:25 | LL | global_asm!("", options(FOO)); - | ^^^ expected one of `)` or `att_syntax` + | ^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)` or `att_syntax`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/parse-error.rs:83:25 | LL | global_asm!("", options(nomem FOO)); - | ^^^^^ expected one of `)` or `att_syntax` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)` or `att_syntax`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/parse-error.rs:85:25 | LL | global_asm!("", options(nomem, FOO)); - | ^^^^^ expected one of `)` or `att_syntax` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: arguments are not allowed after options --> $DIR/parse-error.rs:87:30 diff --git a/src/test/ui/associated-consts/associated-const-array-len.stderr b/src/test/ui/associated-consts/associated-const-array-len.stderr index 2fdfa3da30..ff56d112c8 100644 --- a/src/test/ui/associated-consts/associated-const-array-len.stderr +++ b/src/test/ui/associated-consts/associated-const-array-len.stderr @@ -1,11 +1,14 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/associated-const-array-len.rs:5:16 | -LL | const ID: usize; - | ---------------- required by `Foo::ID` -... LL | const X: [i32; ::ID] = [0, 1, 2]; | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | +note: required by `Foo::ID` + --> $DIR/associated-const-array-len.rs:2:5 + | +LL | const ID: usize; + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-consts/associated-const-private-impl.stderr b/src/test/ui/associated-consts/associated-const-private-impl.stderr index 1b9d7ac7e6..aa356c596f 100644 --- a/src/test/ui/associated-consts/associated-const-private-impl.stderr +++ b/src/test/ui/associated-consts/associated-const-private-impl.stderr @@ -1,6 +1,9 @@ error[E0624]: associated constant `ID` is private --> $DIR/associated-const-private-impl.rs:13:30 | +LL | const ID: i32 = 1; + | ------------------ private associated constant defined here +... LL | assert_eq!(1, bar1::Foo::ID); | ^^ private associated constant diff --git a/src/test/ui/associated-consts/issue-63496.stderr b/src/test/ui/associated-consts/issue-63496.stderr index 34e947030a..cea56cd594 100644 --- a/src/test/ui/associated-consts/issue-63496.stderr +++ b/src/test/ui/associated-consts/issue-63496.stderr @@ -1,9 +1,6 @@ error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:21 | -LL | const C: usize; - | --------------- required by `A::C` -LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); | ^^^^ | | @@ -12,13 +9,15 @@ LL | fn f() -> ([u8; A::C], [u8; A::C]); | = note: cannot satisfy `_: A` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` +note: required by `A::C` + --> $DIR/issue-63496.rs:2:5 + | +LL | const C: usize; + | ^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:33 | -LL | const C: usize; - | --------------- required by `A::C` -LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); | ^^^^ | | @@ -27,6 +26,11 @@ LL | fn f() -> ([u8; A::C], [u8; A::C]); | = note: cannot satisfy `_: A` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` +note: required by `A::C` + --> $DIR/issue-63496.rs:2:5 + | +LL | const C: usize; + | ^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 92d74e38cf..33ab4bb967 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -16,8 +16,6 @@ LL | const X: usize; error[E0283]: type annotations needed --> $DIR/issue-48027.rs:3:32 | -LL | const X: usize; - | --------------- required by `Bar::X` LL | fn return_n(&self) -> [u8; Bar::X]; | ^^^^^^ | | @@ -26,6 +24,11 @@ LL | fn return_n(&self) -> [u8; Bar::X]; | = note: cannot satisfy `_: Bar` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` +note: required by `Bar::X` + --> $DIR/issue-48027.rs:2:5 + | +LL | const X: usize; + | ^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs index 73b23da5bc..7950dd3e99 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -29,7 +29,6 @@ impl Bar for AssocNoCopy { impl Thing for AssocNoCopy { type Out = Box>; //~^ ERROR the trait bound `String: Copy` is not satisfied - //~| ERROR the trait bound `String: Copy` is not satisfied fn func() -> Self::Out { Box::new(AssocNoCopy) diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index 414d74d478..0f1d35be0e 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -4,12 +4,6 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | type Out = Box>; | ^^^^^^^^^^^ the trait `Copy` is not implemented for `String` -error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 - | -LL | type Out = Box>; - | ^^^^^^^^^^^ the trait `Copy` is not implemented for `String` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr b/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr index bd3cac1f88..bffa5150fe 100644 --- a/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.full_tait.stderr @@ -7,16 +7,8 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/duplicate.rs:6:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:11:36 + --> $DIR/duplicate.rs:10:36 | LL | struct SI1> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -24,7 +16,7 @@ LL | struct SI1> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:13:36 + --> $DIR/duplicate.rs:12:36 | LL | struct SI2> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -32,7 +24,7 @@ LL | struct SI2> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:15:39 + --> $DIR/duplicate.rs:14:39 | LL | struct SI3> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -40,7 +32,7 @@ LL | struct SI3> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:17:45 + --> $DIR/duplicate.rs:16:45 | LL | struct SW1 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -48,7 +40,7 @@ LL | struct SW1 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:19:45 + --> $DIR/duplicate.rs:18:45 | LL | struct SW2 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -56,7 +48,7 @@ LL | struct SW2 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:21:48 + --> $DIR/duplicate.rs:20:48 | LL | struct SW3 where T: Iterator { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -64,7 +56,7 @@ LL | struct SW3 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:24:34 + --> $DIR/duplicate.rs:23:34 | LL | enum EI1> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -72,7 +64,7 @@ LL | enum EI1> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:26:34 + --> $DIR/duplicate.rs:25:34 | LL | enum EI2> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -80,7 +72,7 @@ LL | enum EI2> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:28:37 + --> $DIR/duplicate.rs:27:37 | LL | enum EI3> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -88,7 +80,7 @@ LL | enum EI3> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:30:43 + --> $DIR/duplicate.rs:29:43 | LL | enum EW1 where T: Iterator { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -96,7 +88,7 @@ LL | enum EW1 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:32:43 + --> $DIR/duplicate.rs:31:43 | LL | enum EW2 where T: Iterator { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -104,7 +96,7 @@ LL | enum EW2 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:34:46 + --> $DIR/duplicate.rs:33:46 | LL | enum EW3 where T: Iterator { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -112,7 +104,7 @@ LL | enum EW3 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:37:35 + --> $DIR/duplicate.rs:36:35 | LL | union UI1> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -120,7 +112,7 @@ LL | union UI1> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:39:35 + --> $DIR/duplicate.rs:38:35 | LL | union UI2> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -128,7 +120,7 @@ LL | union UI2> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:41:38 + --> $DIR/duplicate.rs:40:38 | LL | union UI3> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -136,7 +128,7 @@ LL | union UI3> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:43:44 + --> $DIR/duplicate.rs:42:44 | LL | union UW1 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -144,7 +136,7 @@ LL | union UW1 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:45:44 + --> $DIR/duplicate.rs:44:44 | LL | union UW2 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -152,7 +144,7 @@ LL | union UW2 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:47:47 + --> $DIR/duplicate.rs:46:47 | LL | union UW3 where T: Iterator { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -160,7 +152,7 @@ LL | union UW3 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:50:32 + --> $DIR/duplicate.rs:49:32 | LL | fn FI1>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -168,7 +160,7 @@ LL | fn FI1>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:52:32 + --> $DIR/duplicate.rs:51:32 | LL | fn FI2>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -176,7 +168,7 @@ LL | fn FI2>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:54:35 + --> $DIR/duplicate.rs:53:35 | LL | fn FI3>() {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -184,7 +176,7 @@ LL | fn FI3>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:56:43 + --> $DIR/duplicate.rs:55:43 | LL | fn FW1() where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -192,7 +184,7 @@ LL | fn FW1() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:58:43 + --> $DIR/duplicate.rs:57:43 | LL | fn FW2() where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -200,7 +192,7 @@ LL | fn FW2() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:60:46 + --> $DIR/duplicate.rs:59:46 | LL | fn FW3() where T: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -208,7 +200,7 @@ LL | fn FW3() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:66:40 + --> $DIR/duplicate.rs:65:40 | LL | fn FAPIT1(_: impl Iterator) {} | ---------- ^^^^^^^^^^ re-bound here @@ -216,7 +208,7 @@ LL | fn FAPIT1(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:68:40 + --> $DIR/duplicate.rs:67:40 | LL | fn FAPIT2(_: impl Iterator) {} | ---------- ^^^^^^^^^^ re-bound here @@ -224,7 +216,7 @@ LL | fn FAPIT2(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:70:43 + --> $DIR/duplicate.rs:69:43 | LL | fn FAPIT3(_: impl Iterator) {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -232,79 +224,7 @@ LL | fn FAPIT3(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:73:39 - | -LL | const CIT1: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:75:39 - | -LL | const CIT2: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:77:42 - | -LL | const CIT3: impl Iterator = iter::empty(); - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:79:40 - | -LL | static SIT1: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:81:40 - | -LL | static SIT2: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:83:43 - | -LL | static SIT3: impl Iterator = iter::empty(); - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:86:46 - | -LL | fn lit1() { let _: impl Iterator = iter::empty(); } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:88:46 - | -LL | fn lit2() { let _: impl Iterator = iter::empty(); } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:90:49 - | -LL | fn lit3() { let _: impl Iterator = iter::empty(); } - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:93:35 + --> $DIR/duplicate.rs:72:35 | LL | type TAI1> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -312,7 +232,7 @@ LL | type TAI1> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:95:35 + --> $DIR/duplicate.rs:74:35 | LL | type TAI2> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -320,7 +240,7 @@ LL | type TAI2> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:97:38 + --> $DIR/duplicate.rs:76:38 | LL | type TAI3> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -328,7 +248,7 @@ LL | type TAI3> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:99:44 + --> $DIR/duplicate.rs:78:44 | LL | type TAW1 where T: Iterator = T; | ---------- ^^^^^^^^^^ re-bound here @@ -336,7 +256,7 @@ LL | type TAW1 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:101:44 + --> $DIR/duplicate.rs:80:44 | LL | type TAW2 where T: Iterator = T; | ---------- ^^^^^^^^^^ re-bound here @@ -344,7 +264,7 @@ LL | type TAW2 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:103:47 + --> $DIR/duplicate.rs:82:47 | LL | type TAW3 where T: Iterator = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -352,7 +272,7 @@ LL | type TAW3 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:106:36 + --> $DIR/duplicate.rs:85:36 | LL | type ETAI1> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -360,7 +280,7 @@ LL | type ETAI1> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:108:36 + --> $DIR/duplicate.rs:87:36 | LL | type ETAI2> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -368,7 +288,7 @@ LL | type ETAI2> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:110:39 + --> $DIR/duplicate.rs:89:39 | LL | type ETAI3> = impl Copy; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -376,7 +296,7 @@ LL | type ETAI3> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:112:40 + --> $DIR/duplicate.rs:91:40 | LL | type ETAI4 = impl Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -384,7 +304,7 @@ LL | type ETAI4 = impl Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:114:40 + --> $DIR/duplicate.rs:93:40 | LL | type ETAI5 = impl Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -392,7 +312,7 @@ LL | type ETAI5 = impl Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:116:43 + --> $DIR/duplicate.rs:95:43 | LL | type ETAI6 = impl Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -400,7 +320,7 @@ LL | type ETAI6 = impl Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:119:36 + --> $DIR/duplicate.rs:98:36 | LL | trait TRI1> {} | ---------- ^^^^^^^^^^ re-bound here @@ -408,7 +328,7 @@ LL | trait TRI1> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:121:36 + --> $DIR/duplicate.rs:100:36 | LL | trait TRI2> {} | ---------- ^^^^^^^^^^ re-bound here @@ -416,7 +336,7 @@ LL | trait TRI2> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:123:39 + --> $DIR/duplicate.rs:102:39 | LL | trait TRI3> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -424,7 +344,7 @@ LL | trait TRI3> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:125:34 + --> $DIR/duplicate.rs:104:34 | LL | trait TRS1: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -432,7 +352,7 @@ LL | trait TRS1: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:127:34 + --> $DIR/duplicate.rs:106:34 | LL | trait TRS2: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -440,7 +360,7 @@ LL | trait TRS2: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:129:37 + --> $DIR/duplicate.rs:108:37 | LL | trait TRS3: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -448,7 +368,7 @@ LL | trait TRS3: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:131:45 + --> $DIR/duplicate.rs:110:45 | LL | trait TRW1 where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -456,7 +376,7 @@ LL | trait TRW1 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:133:45 + --> $DIR/duplicate.rs:112:45 | LL | trait TRW2 where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -464,7 +384,7 @@ LL | trait TRW2 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:135:48 + --> $DIR/duplicate.rs:114:48 | LL | trait TRW3 where T: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -472,7 +392,7 @@ LL | trait TRW3 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:137:46 + --> $DIR/duplicate.rs:116:46 | LL | trait TRSW1 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -480,7 +400,7 @@ LL | trait TRSW1 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:137:46 + --> $DIR/duplicate.rs:116:46 | LL | trait TRSW1 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -488,7 +408,7 @@ LL | trait TRSW1 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:140:46 + --> $DIR/duplicate.rs:119:46 | LL | trait TRSW2 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -496,7 +416,7 @@ LL | trait TRSW2 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:140:46 + --> $DIR/duplicate.rs:119:46 | LL | trait TRSW2 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -504,7 +424,7 @@ LL | trait TRSW2 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:143:49 + --> $DIR/duplicate.rs:122:49 | LL | trait TRSW3 where Self: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -512,7 +432,7 @@ LL | trait TRSW3 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:143:49 + --> $DIR/duplicate.rs:122:49 | LL | trait TRSW3 where Self: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -520,7 +440,7 @@ LL | trait TRSW3 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:153:40 + --> $DIR/duplicate.rs:132:40 | LL | type TADyn1 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -528,7 +448,7 @@ LL | type TADyn1 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:155:44 + --> $DIR/duplicate.rs:134:44 | LL | type TADyn2 = Box>; | ---------- ^^^^^^^^^^ re-bound here @@ -536,7 +456,7 @@ LL | type TADyn2 = Box>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:157:43 + --> $DIR/duplicate.rs:136:43 | LL | type TADyn3 = dyn Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -544,7 +464,7 @@ LL | type TADyn3 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:146:43 + --> $DIR/duplicate.rs:125:43 | LL | trait TRA1 { type A: Iterator; } | ---------- ^^^^^^^^^^ re-bound here @@ -552,7 +472,7 @@ LL | trait TRA1 { type A: Iterator; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:148:43 + --> $DIR/duplicate.rs:127:43 | LL | trait TRA2 { type A: Iterator; } | ---------- ^^^^^^^^^^ re-bound here @@ -560,13 +480,13 @@ LL | trait TRA2 { type A: Iterator; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:150:46 + --> $DIR/duplicate.rs:129:46 | LL | trait TRA3 { type A: Iterator; } | ------------- ^^^^^^^^^^^^^ re-bound here | | | `Item` bound here first -error: aborting due to 69 previous errors; 2 warnings emitted +error: aborting due to 60 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr b/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr index 500e527a01..06bfac588d 100644 --- a/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.min_tait.stderr @@ -1,14 +1,5 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/duplicate.rs:6:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:11:36 + --> $DIR/duplicate.rs:10:36 | LL | struct SI1> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -16,7 +7,7 @@ LL | struct SI1> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:13:36 + --> $DIR/duplicate.rs:12:36 | LL | struct SI2> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -24,7 +15,7 @@ LL | struct SI2> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:15:39 + --> $DIR/duplicate.rs:14:39 | LL | struct SI3> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -32,7 +23,7 @@ LL | struct SI3> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:17:45 + --> $DIR/duplicate.rs:16:45 | LL | struct SW1 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -40,7 +31,7 @@ LL | struct SW1 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:19:45 + --> $DIR/duplicate.rs:18:45 | LL | struct SW2 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -48,7 +39,7 @@ LL | struct SW2 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:21:48 + --> $DIR/duplicate.rs:20:48 | LL | struct SW3 where T: Iterator { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -56,7 +47,7 @@ LL | struct SW3 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:24:34 + --> $DIR/duplicate.rs:23:34 | LL | enum EI1> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -64,7 +55,7 @@ LL | enum EI1> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:26:34 + --> $DIR/duplicate.rs:25:34 | LL | enum EI2> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -72,7 +63,7 @@ LL | enum EI2> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:28:37 + --> $DIR/duplicate.rs:27:37 | LL | enum EI3> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -80,7 +71,7 @@ LL | enum EI3> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:30:43 + --> $DIR/duplicate.rs:29:43 | LL | enum EW1 where T: Iterator { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -88,7 +79,7 @@ LL | enum EW1 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:32:43 + --> $DIR/duplicate.rs:31:43 | LL | enum EW2 where T: Iterator { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -96,7 +87,7 @@ LL | enum EW2 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:34:46 + --> $DIR/duplicate.rs:33:46 | LL | enum EW3 where T: Iterator { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -104,7 +95,7 @@ LL | enum EW3 where T: Iterator { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:37:35 + --> $DIR/duplicate.rs:36:35 | LL | union UI1> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -112,7 +103,7 @@ LL | union UI1> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:39:35 + --> $DIR/duplicate.rs:38:35 | LL | union UI2> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -120,7 +111,7 @@ LL | union UI2> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:41:38 + --> $DIR/duplicate.rs:40:38 | LL | union UI3> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -128,7 +119,7 @@ LL | union UI3> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:43:44 + --> $DIR/duplicate.rs:42:44 | LL | union UW1 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -136,7 +127,7 @@ LL | union UW1 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:45:44 + --> $DIR/duplicate.rs:44:44 | LL | union UW2 where T: Iterator { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -144,7 +135,7 @@ LL | union UW2 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:47:47 + --> $DIR/duplicate.rs:46:47 | LL | union UW3 where T: Iterator { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -152,7 +143,7 @@ LL | union UW3 where T: Iterator { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:50:32 + --> $DIR/duplicate.rs:49:32 | LL | fn FI1>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -160,7 +151,7 @@ LL | fn FI1>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:52:32 + --> $DIR/duplicate.rs:51:32 | LL | fn FI2>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -168,7 +159,7 @@ LL | fn FI2>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:54:35 + --> $DIR/duplicate.rs:53:35 | LL | fn FI3>() {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -176,7 +167,7 @@ LL | fn FI3>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:56:43 + --> $DIR/duplicate.rs:55:43 | LL | fn FW1() where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -184,7 +175,7 @@ LL | fn FW1() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:58:43 + --> $DIR/duplicate.rs:57:43 | LL | fn FW2() where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -192,7 +183,7 @@ LL | fn FW2() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:60:46 + --> $DIR/duplicate.rs:59:46 | LL | fn FW3() where T: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -200,7 +191,7 @@ LL | fn FW3() where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:66:40 + --> $DIR/duplicate.rs:65:40 | LL | fn FAPIT1(_: impl Iterator) {} | ---------- ^^^^^^^^^^ re-bound here @@ -208,7 +199,7 @@ LL | fn FAPIT1(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:68:40 + --> $DIR/duplicate.rs:67:40 | LL | fn FAPIT2(_: impl Iterator) {} | ---------- ^^^^^^^^^^ re-bound here @@ -216,7 +207,7 @@ LL | fn FAPIT2(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:70:43 + --> $DIR/duplicate.rs:69:43 | LL | fn FAPIT3(_: impl Iterator) {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -224,79 +215,7 @@ LL | fn FAPIT3(_: impl Iterator) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:73:39 - | -LL | const CIT1: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:75:39 - | -LL | const CIT2: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:77:42 - | -LL | const CIT3: impl Iterator = iter::empty(); - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:79:40 - | -LL | static SIT1: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:81:40 - | -LL | static SIT2: impl Iterator = iter::empty(); - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:83:43 - | -LL | static SIT3: impl Iterator = iter::empty(); - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:86:46 - | -LL | fn lit1() { let _: impl Iterator = iter::empty(); } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:88:46 - | -LL | fn lit2() { let _: impl Iterator = iter::empty(); } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:90:49 - | -LL | fn lit3() { let _: impl Iterator = iter::empty(); } - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:93:35 + --> $DIR/duplicate.rs:72:35 | LL | type TAI1> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -304,7 +223,7 @@ LL | type TAI1> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:95:35 + --> $DIR/duplicate.rs:74:35 | LL | type TAI2> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -312,7 +231,7 @@ LL | type TAI2> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:97:38 + --> $DIR/duplicate.rs:76:38 | LL | type TAI3> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -320,7 +239,7 @@ LL | type TAI3> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:99:44 + --> $DIR/duplicate.rs:78:44 | LL | type TAW1 where T: Iterator = T; | ---------- ^^^^^^^^^^ re-bound here @@ -328,7 +247,7 @@ LL | type TAW1 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:101:44 + --> $DIR/duplicate.rs:80:44 | LL | type TAW2 where T: Iterator = T; | ---------- ^^^^^^^^^^ re-bound here @@ -336,7 +255,7 @@ LL | type TAW2 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:103:47 + --> $DIR/duplicate.rs:82:47 | LL | type TAW3 where T: Iterator = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -344,7 +263,7 @@ LL | type TAW3 where T: Iterator = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:106:36 + --> $DIR/duplicate.rs:85:36 | LL | type ETAI1> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -352,7 +271,7 @@ LL | type ETAI1> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:108:36 + --> $DIR/duplicate.rs:87:36 | LL | type ETAI2> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -360,7 +279,7 @@ LL | type ETAI2> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:110:39 + --> $DIR/duplicate.rs:89:39 | LL | type ETAI3> = impl Copy; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -368,7 +287,7 @@ LL | type ETAI3> = impl Copy; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:112:40 + --> $DIR/duplicate.rs:91:40 | LL | type ETAI4 = impl Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -376,7 +295,7 @@ LL | type ETAI4 = impl Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:114:40 + --> $DIR/duplicate.rs:93:40 | LL | type ETAI5 = impl Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -384,7 +303,7 @@ LL | type ETAI5 = impl Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:116:43 + --> $DIR/duplicate.rs:95:43 | LL | type ETAI6 = impl Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -392,7 +311,7 @@ LL | type ETAI6 = impl Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:119:36 + --> $DIR/duplicate.rs:98:36 | LL | trait TRI1> {} | ---------- ^^^^^^^^^^ re-bound here @@ -400,7 +319,7 @@ LL | trait TRI1> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:121:36 + --> $DIR/duplicate.rs:100:36 | LL | trait TRI2> {} | ---------- ^^^^^^^^^^ re-bound here @@ -408,7 +327,7 @@ LL | trait TRI2> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:123:39 + --> $DIR/duplicate.rs:102:39 | LL | trait TRI3> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -416,7 +335,7 @@ LL | trait TRI3> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:125:34 + --> $DIR/duplicate.rs:104:34 | LL | trait TRS1: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -424,7 +343,7 @@ LL | trait TRS1: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:127:34 + --> $DIR/duplicate.rs:106:34 | LL | trait TRS2: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -432,7 +351,7 @@ LL | trait TRS2: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:129:37 + --> $DIR/duplicate.rs:108:37 | LL | trait TRS3: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -440,7 +359,7 @@ LL | trait TRS3: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:131:45 + --> $DIR/duplicate.rs:110:45 | LL | trait TRW1 where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -448,7 +367,7 @@ LL | trait TRW1 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:133:45 + --> $DIR/duplicate.rs:112:45 | LL | trait TRW2 where T: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -456,7 +375,7 @@ LL | trait TRW2 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:135:48 + --> $DIR/duplicate.rs:114:48 | LL | trait TRW3 where T: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -464,7 +383,7 @@ LL | trait TRW3 where T: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:137:46 + --> $DIR/duplicate.rs:116:46 | LL | trait TRSW1 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -472,7 +391,7 @@ LL | trait TRSW1 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:137:46 + --> $DIR/duplicate.rs:116:46 | LL | trait TRSW1 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -480,7 +399,7 @@ LL | trait TRSW1 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:140:46 + --> $DIR/duplicate.rs:119:46 | LL | trait TRSW2 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -488,7 +407,7 @@ LL | trait TRSW2 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:140:46 + --> $DIR/duplicate.rs:119:46 | LL | trait TRSW2 where Self: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -496,7 +415,7 @@ LL | trait TRSW2 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:143:49 + --> $DIR/duplicate.rs:122:49 | LL | trait TRSW3 where Self: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -504,7 +423,7 @@ LL | trait TRSW3 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:143:49 + --> $DIR/duplicate.rs:122:49 | LL | trait TRSW3 where Self: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -512,7 +431,7 @@ LL | trait TRSW3 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:153:40 + --> $DIR/duplicate.rs:132:40 | LL | type TADyn1 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -520,7 +439,7 @@ LL | type TADyn1 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:155:44 + --> $DIR/duplicate.rs:134:44 | LL | type TADyn2 = Box>; | ---------- ^^^^^^^^^^ re-bound here @@ -528,7 +447,7 @@ LL | type TADyn2 = Box>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:157:43 + --> $DIR/duplicate.rs:136:43 | LL | type TADyn3 = dyn Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -536,7 +455,7 @@ LL | type TADyn3 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:146:43 + --> $DIR/duplicate.rs:125:43 | LL | trait TRA1 { type A: Iterator; } | ---------- ^^^^^^^^^^ re-bound here @@ -544,7 +463,7 @@ LL | trait TRA1 { type A: Iterator; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:148:43 + --> $DIR/duplicate.rs:127:43 | LL | trait TRA2 { type A: Iterator; } | ---------- ^^^^^^^^^^ re-bound here @@ -552,13 +471,13 @@ LL | trait TRA2 { type A: Iterator; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:150:46 + --> $DIR/duplicate.rs:129:46 | LL | trait TRA3 { type A: Iterator; } | ------------- ^^^^^^^^^^^^^ re-bound here | | | `Item` bound here first -error: aborting due to 69 previous errors; 1 warning emitted +error: aborting due to 60 previous errors For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs index c3319a7050..0d7804ef1a 100644 --- a/src/test/ui/associated-type-bounds/duplicate.rs +++ b/src/test/ui/associated-type-bounds/duplicate.rs @@ -3,7 +3,6 @@ #![feature(min_type_alias_impl_trait)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -#![feature(impl_trait_in_bindings)] //~ WARN the feature `impl_trait_in_bindings` is incomplete #![feature(untagged_unions)] use std::iter; @@ -70,26 +69,6 @@ fn FAPIT2(_: impl Iterator) {} fn FAPIT3(_: impl Iterator) {} //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -const CIT1: impl Iterator = iter::empty(); -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -const CIT2: impl Iterator = iter::empty(); -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -const CIT3: impl Iterator = iter::empty(); -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -static SIT1: impl Iterator = iter::empty(); -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -static SIT2: impl Iterator = iter::empty(); -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -static SIT3: impl Iterator = iter::empty(); -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] - -fn lit1() { let _: impl Iterator = iter::empty(); } -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -fn lit2() { let _: impl Iterator = iter::empty(); } -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] -fn lit3() { let _: impl Iterator = iter::empty(); } -//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] - type TAI1> = T; //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] type TAI2> = T; diff --git a/src/test/ui/associated-type-bounds/dyn-lcsit.rs b/src/test/ui/associated-type-bounds/dyn-lcsit.rs deleted file mode 100644 index b7869e22b4..0000000000 --- a/src/test/ui/associated-type-bounds/dyn-lcsit.rs +++ /dev/null @@ -1,69 +0,0 @@ -// run-pass - -#![feature(associated_type_bounds)] -#![feature(impl_trait_in_bindings)] -//~^ WARNING `impl_trait_in_bindings` is incomplete -#![allow(non_upper_case_globals)] - -use std::ops::Add; - -trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } - -fn assert_copy(x: T) { let _x = x; let _x = x; } -fn assert_static(_: T) {} -fn assert_forall_tr2 Tr2<'a>>(_: T) {} - -#[derive(Copy, Clone)] -struct S1; -#[derive(Copy, Clone)] -struct S2; -impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } } - -const cdef_et1: &dyn Tr1 = &S1; -const sdef_et1: &dyn Tr1 = &S1; -pub fn use_et1() { assert_copy(cdef_et1.mk()); assert_copy(sdef_et1.mk()); } - -const cdef_et2: &(dyn Tr1 + Sync) = &S1; -static sdef_et2: &(dyn Tr1 + Sync) = &S1; -pub fn use_et2() { assert_static(cdef_et2.mk()); assert_static(sdef_et2.mk()); } - -const cdef_et3: &dyn Tr1>>> = { - struct A; - impl Tr1 for A { - type As1 = core::ops::Range; - fn mk(&self) -> Self::As1 { 0..10 } - } - &A -}; -pub fn use_et3() { - let _0 = cdef_et3.mk().clone(); - let mut s = 0u8; - for _1 in _0 { - let _2 = _1 + 1u8; - s += _2.into(); - } - assert_eq!(s, (0..10).map(|x| x + 1).sum()); -} - -const cdef_et4: &(dyn Tr1 Tr2<'a>> + Sync) = { - #[derive(Copy, Clone)] - struct A; - impl Tr1 for A { - type As1 = A; - fn mk(&self) -> A { A } - } - impl<'a> Tr2<'a> for A { - fn tr2(self) -> &'a Self { &A } - } - &A -}; -static sdef_et4: &(dyn Tr1 Tr2<'a>> + Sync) = cdef_et4; -pub fn use_et4() { assert_forall_tr2(cdef_et4.mk()); assert_forall_tr2(sdef_et4.mk()); } - -fn main() { - let _ = use_et1(); - let _ = use_et2(); - let _ = use_et3(); - let _ = use_et4(); -} diff --git a/src/test/ui/associated-type-bounds/dyn-lcsit.stderr b/src/test/ui/associated-type-bounds/dyn-lcsit.stderr deleted file mode 100644 index 3637f9558b..0000000000 --- a/src/test/ui/associated-type-bounds/dyn-lcsit.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/dyn-lcsit.rs:4:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/associated-type-bounds/lcsit.rs b/src/test/ui/associated-type-bounds/lcsit.rs deleted file mode 100644 index 5364f25f89..0000000000 --- a/src/test/ui/associated-type-bounds/lcsit.rs +++ /dev/null @@ -1,78 +0,0 @@ -// run-pass - -#![feature(associated_type_bounds)] -#![feature(impl_trait_in_bindings)] -//~^ WARNING `impl_trait_in_bindings` is incomplete -#![allow(non_upper_case_globals)] - -use std::ops::Add; - -trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } - -fn assert_copy(x: T) { let _x = x; let _x = x; } -fn assert_static(_: T) {} -fn assert_forall_tr2 Tr2<'a>>(_: T) {} - -#[derive(Copy, Clone)] -struct S1; -#[derive(Copy, Clone)] -struct S2; -impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } } - -const cdef_et1: impl Copy + Tr1 = { - let x: impl Copy + Tr1 = S1; - x -}; -static sdef_et1: impl Copy + Tr1 = cdef_et1; -pub fn use_et1() { assert_copy(cdef_et1.mk()); assert_copy(sdef_et1.mk()); } - -const cdef_et2: impl Tr1 = { - let x: impl Tr1 = S1; - x -}; -static sdef_et2: impl Tr1 = cdef_et2; -pub fn use_et2() { assert_static(cdef_et2.mk()); assert_static(sdef_et2.mk()); } - -const cdef_et3: impl Tr1>>> = { - struct A; - impl Tr1 for A { - type As1 = core::ops::Range; - fn mk(&self) -> Self::As1 { 0..10 } - } - let x: impl Tr1>>> = A; - x -}; -pub fn use_et3() { - let _0 = cdef_et3.mk().clone(); - let mut s = 0u8; - for _1 in _0 { - let _2 = _1 + 1u8; - s += _2.into(); - } - assert_eq!(s, (0..10).map(|x| x + 1).sum()); -} - -const cdef_et4: impl Copy + Tr1 Tr2<'a>> = { - #[derive(Copy, Clone)] - struct A; - impl Tr1 for A { - type As1 = A; - fn mk(&self) -> A { A } - } - impl<'a> Tr2<'a> for A { - fn tr2(self) -> &'a Self { &A } - } - let x: impl Copy + Tr1 Tr2<'a>> = A; - x -}; - -static sdef_et4: impl Copy + Tr1 Tr2<'a>> = cdef_et4; -pub fn use_et4() { assert_forall_tr2(cdef_et4.mk()); assert_forall_tr2(sdef_et4.mk()); } - -fn main() { - let _ = use_et1(); - let _ = use_et2(); - let _ = use_et3(); - let _ = use_et4(); -} diff --git a/src/test/ui/associated-type-bounds/lcsit.stderr b/src/test/ui/associated-type-bounds/lcsit.stderr deleted file mode 100644 index 11ff03db36..0000000000 --- a/src/test/ui/associated-type-bounds/lcsit.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/lcsit.rs:4:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr index ab8909d109..41e2d8ec31 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -1,12 +1,14 @@ error[E0277]: the trait bound `::R: ToInt` is not satisfied --> $DIR/associated-types-bound-failure.rs:19:19 | -LL | fn to_int(&self) -> isize; - | -------------------------- required by `ToInt::to_int` -... LL | ToInt::to_int(&g.get()) | ^^^^^^^^ the trait `ToInt` is not implemented for `::R` | +note: required by `ToInt::to_int` + --> $DIR/associated-types-bound-failure.rs:6:5 + | +LL | fn to_int(&self) -> isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider further restricting the associated type | LL | where G : GetToInt, ::R: ToInt diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 6d7289bd07..25e80159b0 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:5 + --> $DIR/associated-types-for-unimpl-trait.rs:10:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr index 0b5dee611e..19500f58aa 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `T: Get` is not satisfied - --> $DIR/associated-types-no-suitable-bound.rs:11:5 + --> $DIR/associated-types-no-suitable-bound.rs:11:21 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(foo: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index dfe62aa5d6..0e978f20a6 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5 + --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index f0f2451a1e..1ec3c05983 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:17:5 + --> $DIR/associated-types-no-suitable-supertrait.rs:17:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | @@ -10,10 +13,13 @@ LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Ge | ^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(T, U): Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:22:5 + --> $DIR/associated-types-no-suitable-supertrait.rs:22:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 4528f03c54..b6ee1ed733 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 | +LL | trait Get { + | --------- required by this bound in `Get` +... LL | fn okay(&self, foo: U, bar: ::Value); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 9d084203e3..5f4b65bd13 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -1,13 +1,15 @@ error[E0283]: type annotations needed --> $DIR/associated-types-unconstrained.rs:14:20 | -LL | fn bar() -> isize; - | ------------------ required by `Foo::bar` -... LL | let x: isize = Foo::bar(); | ^^^^^^^^ cannot infer type | = note: cannot satisfy `_: Foo` +note: required by `Foo::bar` + --> $DIR/associated-types-unconstrained.rs:5:5 + | +LL | fn bar() -> isize; + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr index d4fa5be742..73ef567ffa 100644 --- a/src/test/ui/associated-types/defaults-wf.stderr +++ b/src/test/ui/associated-types/defaults-wf.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/defaults-wf.rs:7:5 + --> $DIR/defaults-wf.rs:7:15 | LL | type Ty = Vec<[u8]>; - | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^ doesn't have a size known at compile-time | ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.rs b/src/test/ui/associated-types/hr-associated-type-projection-1.rs index 1270cd6706..bad736b64c 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.rs +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.rs @@ -11,7 +11,7 @@ where } impl UnsafeCopy<'_, T> for T { - //~^ ERROR the trait bound `>::Item: Deref` is not satisfied + //~^ ERROR the trait bound `for<'b> >::Item: Deref` is not satisfied type Item = T; //~^ ERROR the trait bound `for<'b> >::Item: Deref } diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr index cf4ec0babf..49fad4e1b1 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr @@ -14,16 +14,16 @@ LL | type Item = T; <&T as Deref> <&mut T as Deref> -error[E0277]: the trait bound `>::Item: Deref` is not satisfied +error[E0277]: the trait bound `for<'b> >::Item: Deref` is not satisfied --> $DIR/hr-associated-type-projection-1.rs:13:33 | LL | impl UnsafeCopy<'_, T> for T { - | ^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `>::Item` + | ^^^^^^^^^^^^^^^^^ the trait `for<'b> Deref` is not implemented for `>::Item` | help: consider further restricting the associated type | -LL | impl UnsafeCopy<'_, T> for T where >::Item: Deref { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl UnsafeCopy<'_, T> for T where for<'b> >::Item: Deref { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-20005.rs b/src/test/ui/associated-types/issue-20005.rs similarity index 100% rename from src/test/ui/issues/issue-20005.rs rename to src/test/ui/associated-types/issue-20005.rs diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/associated-types/issue-20005.stderr similarity index 100% rename from src/test/ui/issues/issue-20005.stderr rename to src/test/ui/associated-types/issue-20005.stderr diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr index b7db5d3858..7bf36d5e91 100644 --- a/src/test/ui/associated-types/issue-44153.stderr +++ b/src/test/ui/associated-types/issue-44153.stderr @@ -1,9 +1,6 @@ error[E0271]: type mismatch resolving `<() as Array>::Element == &()` --> $DIR/issue-44153.rs:18:5 | -LL | fn visit() {} - | ---------- required by `Visit::visit` -... LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ expected `&()`, found `()` | @@ -12,6 +9,11 @@ note: required because of the requirements on the impl of `Visit` for `()` | LL | impl<'a> Visit for () where | ^^^^^ ^^ +note: required by `Visit::visit` + --> $DIR/issue-44153.rs:6:5 + | +LL | fn visit() {} + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/normalization-debruijn-1.rs b/src/test/ui/associated-types/normalization-debruijn-1.rs new file mode 100644 index 0000000000..a5abf1ba99 --- /dev/null +++ b/src/test/ui/associated-types/normalization-debruijn-1.rs @@ -0,0 +1,36 @@ +// build-pass +// edition:2018 + +// Regression test to ensure we handle debruijn indices correctly in projection +// normalization under binders. Found in crater run for #85499 + +use std::future::Future; +use std::pin::Pin; +pub enum Outcome { + Success((S, E)), +} +pub struct Request<'r> { + _marker: std::marker::PhantomData<&'r ()>, +} +pub trait FromRequest<'r>: Sized { + type Error; + fn from_request<'life0>( + request: &'r Request<'life0>, + ) -> Pin>>>; +} +impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option { + type Error = (); + fn from_request<'life0>( + request: &'r Request<'life0>, + ) -> Pin>>> { + Box::pin(async move { + let request = request; + match T::from_request(request).await { + _ => todo!(), + } + }); + todo!() + } +} + +fn main() {} diff --git a/src/test/ui/associated-types/normalization-debruijn-2.rs b/src/test/ui/associated-types/normalization-debruijn-2.rs new file mode 100644 index 0000000000..abe248e16a --- /dev/null +++ b/src/test/ui/associated-types/normalization-debruijn-2.rs @@ -0,0 +1,31 @@ +// build-pass +// edition:2018 + +// Regression test to ensure we handle debruijn indices correctly in projection +// normalization under binders. Found in crater run for #85499 + +use std::future::Future; +use std::pin::Pin; +pub enum Outcome { + Success(S), + Failure(E), +} +pub struct Request<'r> { + _marker: std::marker::PhantomData<&'r ()>, +} +pub trait FromRequest<'r>: Sized { + type Error; + fn from_request<'life0>( + request: &'r Request<'life0>, + ) -> Pin>>>; +} +pub struct S { + _marker: std::marker::PhantomData, +} +impl<'r, T: FromRequest<'r>> S { + pub async fn from_request(request: &'r Request<'_>) { + let _ = T::from_request(request).await; + } +} + +fn main() {} diff --git a/src/test/ui/associated-types/normalization-debruijn-3.rs b/src/test/ui/associated-types/normalization-debruijn-3.rs new file mode 100644 index 0000000000..2bea78cf7b --- /dev/null +++ b/src/test/ui/associated-types/normalization-debruijn-3.rs @@ -0,0 +1,41 @@ +// build-pass +// edition:2018 + +// Regression test to ensure we handle debruijn indices correctly in projection +// normalization under binders. Found in crater run for #85499 + +use std::future::{Future, Ready}; +async fn read() { + let _ = connect(&()).await; +} +async fn connect(addr: A) { + let _ = addr.to_socket_addr().await; +} +pub trait ToSocketAddr { + type Future: Future; + fn to_socket_addr(&self) -> Self::Future; +} +impl ToSocketAddr for &() { + type Future = Ready<()>; + fn to_socket_addr(&self) -> Self::Future { + unimplemented!() + } +} +struct Server; +impl Server { + fn and_then(self, _fun: F) -> AndThen { + unimplemented!() + } +} +struct AndThen { + _marker: std::marker::PhantomData, +} +pub async fn run(_: F) { +} +fn main() { + let _ = async { + let server = Server; + let verification_route = server.and_then(read); + run(verification_route).await; + }; +} diff --git a/src/test/ui/associated-types/normalization-generality.rs b/src/test/ui/associated-types/normalization-generality.rs new file mode 100644 index 0000000000..f8e3f5b58d --- /dev/null +++ b/src/test/ui/associated-types/normalization-generality.rs @@ -0,0 +1,36 @@ +// build-pass + +// Ensures that we don't regress on "implementation is not general enough" when +// normalizating under binders. + +#![feature(no_core)] + +pub trait Yokeable<'a> { + type Output: 'a; +} + +pub struct Yoke Yokeable<'a>> { + _yokeable: Y, +} + +impl Yokeable<'a>> Yoke { + pub fn project<'this, P>( + &'this self, + _f: for<'a> fn(>::Output, &'a ()) ->

>::Output, + ) -> Yoke

+ where + P: for<'a> Yokeable<'a>, + { + unimplemented!() + } +} + +pub fn slice(y: Yoke<&'static ()>) -> Yoke<&'static ()> { + y.project(move |yk, _| yk) +} + +impl<'a, T> Yokeable<'a> for &'static T { + type Output = &'a T; +} + +fn main() {} diff --git a/src/test/ui/async-await/async-fn-path-elision.stderr b/src/test/ui/async-await/async-fn-path-elision.stderr index 9694742200..36fb73a8dd 100644 --- a/src/test/ui/async-await/async-fn-path-elision.stderr +++ b/src/test/ui/async-await/async-fn-path-elision.stderr @@ -3,6 +3,8 @@ error[E0726]: implicit elided lifetime not allowed here | LL | async fn error(lt: HasLifetime) { | ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>` + | + = note: assuming a `'static` lifetime... error: aborting due to previous error diff --git a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs index a3a20cb97e..50c1639996 100644 --- a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs +++ b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs @@ -3,36 +3,36 @@ mod outer_mod { pub mod await { //~ ERROR `await` is a keyword in the 2018 edition - //~^ WARN this was previously accepted by the compiler + //~^ WARN this is accepted in the current edition pub struct await; //~ ERROR `await` is a keyword in the 2018 edition - //~^ WARN this was previously accepted by the compiler + //~^ WARN this is accepted in the current edition } } use outer_mod::await::await; //~ ERROR `await` is a keyword in the 2018 edition //~^ ERROR `await` is a keyword in the 2018 edition -//~^^ WARN this was previously accepted by the compiler -//~^^^ WARN this was previously accepted by the compiler +//~^^ WARN this is accepted in the current edition +//~^^^ WARN this is accepted in the current edition struct Foo { await: () } //~^ ERROR `await` is a keyword in the 2018 edition -//~^^ WARN this was previously accepted by the compiler +//~^^ WARN this is accepted in the current edition impl Foo { fn await() {} } //~^ ERROR `await` is a keyword in the 2018 edition -//~^^ WARN this was previously accepted by the compiler +//~^^ WARN this is accepted in the current edition macro_rules! await { //~^ ERROR `await` is a keyword in the 2018 edition -//~^^ WARN this was previously accepted by the compiler +//~^^ WARN this is accepted in the current edition () => {} } fn main() { await!(); //~ ERROR `await` is a keyword in the 2018 edition - //~^ WARN this was previously accepted by the compiler + //~^ WARN this is accepted in the current edition match await { await => {} } //~ ERROR `await` is a keyword in the 2018 edition //~^ ERROR `await` is a keyword in the 2018 edition - //~^^ WARN this was previously accepted by the compiler - //~^^^ WARN this was previously accepted by the compiler + //~^^ WARN this is accepted in the current edition + //~^^^ WARN this is accepted in the current edition } 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 474c09d79d..50a82c08c3 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 @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -18,7 +18,7 @@ error: `await` is a keyword in the 2018 edition LL | pub struct await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -27,7 +27,7 @@ error: `await` is a keyword in the 2018 edition LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -36,7 +36,7 @@ error: `await` is a keyword in the 2018 edition LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -45,7 +45,7 @@ error: `await` is a keyword in the 2018 edition LL | struct Foo { await: () } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -54,7 +54,7 @@ error: `await` is a keyword in the 2018 edition LL | impl Foo { fn await() {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -63,7 +63,7 @@ error: `await` is a keyword in the 2018 edition LL | macro_rules! await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -72,7 +72,7 @@ error: `await` is a keyword in the 2018 edition LL | await!(); | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -81,7 +81,7 @@ error: `await` is a keyword in the 2018 edition LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -90,7 +90,7 @@ error: `await` is a keyword in the 2018 edition LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 10 previous errors diff --git a/src/test/ui/async-await/await-keyword/2015-edition-warning.fixed b/src/test/ui/async-await/await-keyword/2015-edition-warning.fixed index c58496c91f..117495e130 100644 --- a/src/test/ui/async-await/await-keyword/2015-edition-warning.fixed +++ b/src/test/ui/async-await/await-keyword/2015-edition-warning.fixed @@ -6,22 +6,22 @@ mod outer_mod { pub mod r#await { //~^ ERROR `await` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition pub struct r#await; //~^ ERROR `await` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition } } use outer_mod::r#await::r#await; //~^ ERROR `await` is a keyword //~| ERROR `await` is a keyword -//~| WARN was previously accepted -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition fn main() { match r#await { r#await => {} } //~^ ERROR `await` is a keyword //~| ERROR `await` is a keyword -//~| WARN was previously accepted -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition } diff --git a/src/test/ui/async-await/await-keyword/2015-edition-warning.rs b/src/test/ui/async-await/await-keyword/2015-edition-warning.rs index a7543a1432..b3c64895c6 100644 --- a/src/test/ui/async-await/await-keyword/2015-edition-warning.rs +++ b/src/test/ui/async-await/await-keyword/2015-edition-warning.rs @@ -6,22 +6,22 @@ mod outer_mod { pub mod await { //~^ ERROR `await` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition pub struct await; //~^ ERROR `await` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition } } use outer_mod::await::await; //~^ ERROR `await` is a keyword //~| ERROR `await` is a keyword -//~| WARN was previously accepted -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition fn main() { match await { await => {} } //~^ ERROR `await` is a keyword //~| ERROR `await` is a keyword -//~| WARN was previously accepted -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition } 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 0c558eb12f..1c4c19ea45 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 @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -18,7 +18,7 @@ error: `await` is a keyword in the 2018 edition LL | pub struct await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -27,7 +27,7 @@ error: `await` is a keyword in the 2018 edition LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -36,7 +36,7 @@ error: `await` is a keyword in the 2018 edition LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -45,7 +45,7 @@ error: `await` is a keyword in the 2018 edition LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `await` is a keyword in the 2018 edition @@ -54,7 +54,7 @@ error: `await` is a keyword in the 2018 edition LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 6 previous errors diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index ad661fb283..ba97e13579 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -5,7 +5,11 @@ LL | foo()?; | ^^^^^^ the `?` operator cannot be applied to type `impl Future` | = help: the trait `Try` is not implemented for `impl Future` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `await`ing on the `Future` | LL | foo().await?; @@ -18,7 +22,11 @@ LL | t?; | ^^ the `?` operator cannot be applied to type `T` | = help: the trait `Try` is not implemented for `T` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `await`ing on the `Future` | LL | t.await?; diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index e97d088cf3..62a1f451a1 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -41,14 +41,14 @@ LL | require_send(send_fut); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36 {}]>` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]` + = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` = note: required because it appears within the type `impl Future` = note: required because it appears within the type `impl Future` = note: required because it appears within the type `impl Future` = note: required because it appears within the type `{ResumeTy, impl Future, (), i32, Ready}` - = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6 {ResumeTy, impl Future, (), i32, Ready}]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6 {ResumeTy, impl Future, (), i32, Ready}]>` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]` + = note: required because it appears within the type `from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>` = note: required because it appears within the type `impl Future` error: aborting due to 3 previous errors diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr index fb1f8e4ffd..e20e2e8f6b 100644 --- a/src/test/ui/async-await/issue-70594.stderr +++ b/src/test/ui/async-await/issue-70594.stderr @@ -25,7 +25,11 @@ LL | [1; ().await]; | ^^^^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` - = note: required by `poll` +note: required by `poll` + --> $SRC_DIR/core/src/future/future.rs:LL:COL + | +LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issue-84841.rs b/src/test/ui/async-await/issue-84841.rs new file mode 100644 index 0000000000..ba3a1617b9 --- /dev/null +++ b/src/test/ui/async-await/issue-84841.rs @@ -0,0 +1,16 @@ +// edition:2018 + +fn main() { + +} + +async fn foo() { + // Adding an .await here avoids the ICE + test()?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~| ERROR the `?` operator can only be used in an async function that returns +} + +// Removing the const generic parameter here avoids the ICE +async fn test() { +} diff --git a/src/test/ui/async-await/issue-84841.stderr b/src/test/ui/async-await/issue-84841.stderr new file mode 100644 index 0000000000..e28ba74eb6 --- /dev/null +++ b/src/test/ui/async-await/issue-84841.stderr @@ -0,0 +1,36 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-84841.rs:9:5 + | +LL | test()?; + | ^^^^^^^ the `?` operator cannot be applied to type `impl Future` + | + = help: the trait `Try` is not implemented for `impl Future` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/issue-84841.rs:9:11 + | +LL | async fn foo() { + | ________________- +LL | | // Adding an .await here avoids the ICE +LL | | test()?; + | | ^ cannot use the `?` operator in an async function that returns `()` +LL | | +LL | | +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual<_>` is not implemented for `()` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-86507.rs b/src/test/ui/async-await/issue-86507.rs new file mode 100644 index 0000000000..317f031766 --- /dev/null +++ b/src/test/ui/async-await/issue-86507.rs @@ -0,0 +1,25 @@ +// edition:2018 + +use ::core::pin::Pin; +use ::core::future::Future; +use ::core::marker::Send; + +trait Foo { + fn bar<'me, 'async_trait, T: Send>(x: &'me T) + -> Pin + Send + 'async_trait>> + where 'me: 'async_trait; +} + +impl Foo for () { + fn bar<'me, 'async_trait, T: Send>(x: &'me T) + -> Pin + Send + 'async_trait>> + where 'me:'async_trait { + Box::pin( //~ ERROR future cannot be sent between threads safely + async move { + let x = x; + } + ) + } +} + +fn main() { } diff --git a/src/test/ui/async-await/issue-86507.stderr b/src/test/ui/async-await/issue-86507.stderr new file mode 100644 index 0000000000..51e8f61085 --- /dev/null +++ b/src/test/ui/async-await/issue-86507.stderr @@ -0,0 +1,23 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-86507.rs:17:13 + | +LL | / Box::pin( +LL | | async move { +LL | | let x = x; +LL | | } +LL | | ) + | |_____________^ future created by async block is not `Send` + | +note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` + --> $DIR/issue-86507.rs:19:29 + | +LL | let x = x; + | ^ has type `&T` which is not `Send`, because `T` is not `Sync` + = note: required for the cast to the object type `dyn Future + Send` +help: consider further restricting type parameter `T` + | +LL | where 'me:'async_trait, T: std::marker::Sync { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index c879a65bc7..946b8d19e6 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -34,7 +34,11 @@ LL | (|_| 2333).await; | ^^^^^^^^^^^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future | = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` - = note: required by `poll` +note: required by `poll` + --> $SRC_DIR/core/src/future/future.rs:LL:COL + | +LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/issues/issue-67893.stderr b/src/test/ui/async-await/issues/issue-67893.stderr index aee2ae0e2e..ea5c90a81d 100644 --- a/src/test/ui/async-await/issues/issue-67893.stderr +++ b/src/test/ui/async-await/issues/issue-67893.stderr @@ -14,8 +14,8 @@ LL | pub async fn run() { | = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc>, &'r Mutex<()>, Result, PoisonError>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}` - = note: required because it appears within the type `[static generator@run::{closure#0} for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc>, &'r Mutex<()>, Result, PoisonError>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}]` - = note: required because it appears within the type `from_generator::GenFuture<[static generator@run::{closure#0} for<'r, 's, 't0, 't1, 't2, 't3> {ResumeTy, Arc>, &'r Mutex<()>, Result, PoisonError>>, &'t1 MutexGuard<'t2, ()>, MutexGuard<'t3, ()>, (), impl Future}]>` + = note: required because it appears within the type `[static generator@run::{closure#0}]` + = note: required because it appears within the type `from_generator::GenFuture<[static generator@run::{closure#0}]>` = note: required because it appears within the type `impl Future` = note: required because it appears within the type `impl Future` diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr index eed90772d2..b6841da1f0 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr @@ -1,15 +1,11 @@ error: lifetime may not live long enough - --> $DIR/ret-impl-trait-one.rs:10:80 + --> $DIR/ret-impl-trait-one.rs:10:65 | -LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ________________________________--__--__________________________________________^ - | | | | - | | | lifetime `'b` defined here - | | lifetime `'a` defined here -LL | | -LL | | (a, b) -LL | | } - | |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | -- -- ^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a` + | | | + | | lifetime `'b` defined here + | lifetime `'a` defined here | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/async-await/pin-needed-to-poll-2.stderr b/src/test/ui/async-await/pin-needed-to-poll-2.stderr index c4d21de8aa..8c581ff222 100644 --- a/src/test/ui/async-await/pin-needed-to-poll-2.stderr +++ b/src/test/ui/async-await/pin-needed-to-poll-2.stderr @@ -10,7 +10,11 @@ note: required because it appears within the type `Sleep` | LL | struct Sleep(std::marker::PhantomPinned); | ^^^^^ - = note: required by `Pin::

::new` +note: required by `Pin::

::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + | +LL | pub const fn new(pointer: P) -> Pin

{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr index a3f122a466..e8bb4aca9a 100644 --- a/src/test/ui/async-await/try-on-option-in-async.stderr +++ b/src/test/ui/async-await/try-on-option-in-async.stderr @@ -11,7 +11,11 @@ LL | | } | |_____- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `{integer}` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-in-async.rs:17:10 @@ -26,7 +30,11 @@ LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `u32` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-in-async.rs:26:6 @@ -41,7 +49,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `u32` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/attributes/nonterminal-expansion.rs b/src/test/ui/attributes/nonterminal-expansion.rs index b4f523936a..97bf225f0c 100644 --- a/src/test/ui/attributes/nonterminal-expansion.rs +++ b/src/test/ui/attributes/nonterminal-expansion.rs @@ -2,8 +2,9 @@ macro_rules! pass_nonterminal { ($n:expr) => { - #[repr(align($n))] //~ ERROR expected unsuffixed literal or identifier, found `n!()` - //~| ERROR unrecognized representation hint + #[repr(align($n))] + //~^ ERROR expected unsuffixed literal or identifier, found `n!()` + //~| ERROR incorrect `repr(align)` attribute format struct S; }; } diff --git a/src/test/ui/attributes/nonterminal-expansion.stderr b/src/test/ui/attributes/nonterminal-expansion.stderr index e6a36b68d4..9bf36f3c58 100644 --- a/src/test/ui/attributes/nonterminal-expansion.stderr +++ b/src/test/ui/attributes/nonterminal-expansion.stderr @@ -9,7 +9,7 @@ LL | pass_nonterminal!(n!()); | = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0552]: unrecognized representation hint +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses --> $DIR/nonterminal-expansion.rs:5:16 | LL | #[repr(align($n))] @@ -22,4 +22,4 @@ LL | pass_nonterminal!(n!()); error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0552`. +For more information about this error, try `rustc --explain E0693`. diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/bastion-of-the-turbofish.rs index d9ca7ddc7c..233ddbbe11 100644 --- a/src/test/ui/bastion-of-the-turbofish.rs +++ b/src/test/ui/bastion-of-the-turbofish.rs @@ -25,9 +25,12 @@ // // My heart aches in sorrow, for I know I am defeated. Let this be a warning // to all those who come after. Here stands the bastion of the Turbofish. +// +// RIP Anna Harren, Guardian Angel of the Hallowed Turbofish. <3 // See https://github.com/rust-lang/rust/pull/53562 // and https://github.com/rust-lang/rfcs/pull/2527 +// and https://twitter.com/garblefart/status/1393236602856611843 // for context. fn main() { diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index fa967ccb9d..ed71b99da0 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -14,11 +14,6 @@ error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug` | LL | assert_eq!(foo, y); | ^^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - ::: $SRC_DIR/core/src/panicking.rs:LL:COL - | -LL | T: fmt::Debug + ?Sized, - | ---------- required by this bound in `core::panicking::assert_failed` | = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr index d8ccf36852..0475df4474 100644 --- a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr +++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference +error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5 | LL | fn a(s: &S) { @@ -6,7 +6,7 @@ LL | fn a(s: &S) { LL | *s.pointer += 1; | ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference +error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5 | LL | fn c(s: & &mut S) { diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr index 1fdeb812bf..0866f54b9f 100644 --- a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `**t1` which is behind a `&` reference +error[E0594]: cannot assign to `**t1`, which is behind a `&` reference --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5 | LL | let t1 = t0; diff --git a/src/test/ui/borrowck/borrowck-issue-14498.stderr b/src/test/ui/borrowck/borrowck-issue-14498.stderr index ae9167757a..4c0e46d453 100644 --- a/src/test/ui/borrowck/borrowck-issue-14498.stderr +++ b/src/test/ui/borrowck/borrowck-issue-14498.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `***p` which is behind a `&` reference +error[E0594]: cannot assign to `***p`, which is behind a `&` reference --> $DIR/borrowck-issue-14498.rs:16:5 | LL | let p = &y; diff --git a/src/test/ui/fsu-moves-and-copies.rs b/src/test/ui/borrowck/fsu-moves-and-copies.rs similarity index 100% rename from src/test/ui/fsu-moves-and-copies.rs rename to src/test/ui/borrowck/fsu-moves-and-copies.rs diff --git a/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr index d2865ffd19..369a8c61d2 100644 --- a/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr +++ b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*item` which is behind a `&` reference +error[E0594]: cannot assign to `*item`, which is behind a `&` reference --> $DIR/issue-69789-iterator-mut-suggestion.rs:7:9 | LL | for item in &mut std::iter::empty::<&'static ()>() { diff --git a/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs b/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs index 6da88bed2c..d301e7b352 100644 --- a/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs +++ b/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs @@ -9,7 +9,7 @@ fn main() { for v in Query.iter_mut() { //~^ NOTE this iterator yields `&` references *v -= 1; - //~^ ERROR cannot assign to `*v` which is behind a `&` reference + //~^ ERROR cannot assign to `*v`, which is behind a `&` reference //~| NOTE `v` is a `&` reference, so the data it refers to cannot be written } } diff --git a/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr b/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr index 143b74c39b..26ce007dd3 100644 --- a/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr +++ b/src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*v` which is behind a `&` reference +error[E0594]: cannot assign to `*v`, which is behind a `&` reference --> $DIR/issue-83309-ice-immut-in-for-loop.rs:11:9 | LL | for v in Query.iter_mut() { diff --git a/src/test/ui/borrowck/issue-83760.rs b/src/test/ui/borrowck/issue-83760.rs new file mode 100644 index 0000000000..e25b4f7278 --- /dev/null +++ b/src/test/ui/borrowck/issue-83760.rs @@ -0,0 +1,40 @@ +struct Struct; + +fn test1() { + let mut val = Some(Struct); + while let Some(foo) = val { //~ ERROR use of moved value + if true { + val = None; + } else { + + } + } +} + +fn test2() { + let mut foo = Some(Struct); + let _x = foo.unwrap(); + if true { + foo = Some(Struct); + } else { + } + let _y = foo; //~ ERROR use of moved value: `foo` +} + +fn test3() { + let mut foo = Some(Struct); + let _x = foo.unwrap(); + if true { + foo = Some(Struct); + } else if true { + foo = Some(Struct); + } else if true { + foo = Some(Struct); + } else if true { + foo = Some(Struct); + } else { + } + let _y = foo; //~ ERROR use of moved value: `foo` +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-83760.stderr b/src/test/ui/borrowck/issue-83760.stderr new file mode 100644 index 0000000000..beeda5685d --- /dev/null +++ b/src/test/ui/borrowck/issue-83760.stderr @@ -0,0 +1,62 @@ +error[E0382]: use of moved value + --> $DIR/issue-83760.rs:5:20 + | +LL | while let Some(foo) = val { + | ^^^ value moved here, in previous iteration of loop +LL | if true { +LL | val = None; + | ---------- this reinitialization might get skipped + | + = note: move occurs because value has type `Struct`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `foo` + --> $DIR/issue-83760.rs:21:14 + | +LL | let mut foo = Some(Struct); + | ------- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait +LL | let _x = foo.unwrap(); + | -------- `foo` moved due to this method call +LL | if true { +LL | foo = Some(Struct); + | ------------------ this reinitialization might get skipped +... +LL | let _y = foo; + | ^^^ value used here after move + | +note: this function takes ownership of the receiver `self`, which moves `foo` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub const fn unwrap(self) -> T { + | ^^^^ + +error[E0382]: use of moved value: `foo` + --> $DIR/issue-83760.rs:37:14 + | +LL | let mut foo = Some(Struct); + | ------- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait +LL | let _x = foo.unwrap(); + | -------- `foo` moved due to this method call +... +LL | let _y = foo; + | ^^^ value used here after move + | +note: these 3 reinitializations and 1 other might get skipped + --> $DIR/issue-83760.rs:30:9 + | +LL | foo = Some(Struct); + | ^^^^^^^^^^^^^^^^^^ +LL | } else if true { +LL | foo = Some(Struct); + | ^^^^^^^^^^^^^^^^^^ +LL | } else if true { +LL | foo = Some(Struct); + | ^^^^^^^^^^^^^^^^^^ +note: this function takes ownership of the receiver `self`, which moves `foo` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub const fn unwrap(self) -> T { + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/issue-85581.rs b/src/test/ui/borrowck/issue-85581.rs new file mode 100644 index 0000000000..ccc120c542 --- /dev/null +++ b/src/test/ui/borrowck/issue-85581.rs @@ -0,0 +1,15 @@ +// Regression test of #85581. +// Checks not to suggest to add `;` when the second mutable borrow +// is in the first's scope. + +use std::collections::BinaryHeap; + +fn foo(heap: &mut BinaryHeap) { + match heap.peek_mut() { + Some(_) => { heap.pop(); }, + //~^ ERROR: cannot borrow `*heap` as mutable more than once at a time + None => (), + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-85581.stderr b/src/test/ui/borrowck/issue-85581.stderr new file mode 100644 index 0000000000..29c0429f2a --- /dev/null +++ b/src/test/ui/borrowck/issue-85581.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `*heap` as mutable more than once at a time + --> $DIR/issue-85581.rs:9:22 + | +LL | match heap.peek_mut() { + | --------------- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +LL | Some(_) => { heap.pop(); }, + | ^^^^ second mutable borrow occurs here +... +LL | } + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/issue-85765.rs b/src/test/ui/borrowck/issue-85765.rs index b82e029815..1a5f7434fe 100644 --- a/src/test/ui/borrowck/issue-85765.rs +++ b/src/test/ui/borrowck/issue-85765.rs @@ -5,4 +5,11 @@ fn main() { rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable + + let mut mutvar = 42; + let r = &mutvar; + //~^ HELP consider changing this to be a mutable reference + *r = 0; + //~^ ERROR cannot assign to `*r`, which is behind a `&` reference + //~| NOTE `r` is a `&` reference, so the data it refers to cannot be written } diff --git a/src/test/ui/borrowck/issue-85765.stderr b/src/test/ui/borrowck/issue-85765.stderr index 863c2e8ecc..4da4c8f594 100644 --- a/src/test/ui/borrowck/issue-85765.stderr +++ b/src/test/ui/borrowck/issue-85765.stderr @@ -7,6 +7,16 @@ LL | LL | rofl.push(Vec::new()); | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable -error: aborting due to previous error +error[E0594]: cannot assign to `*r`, which is behind a `&` reference + --> $DIR/issue-85765.rs:12:5 + | +LL | let r = &mutvar; + | ------- help: consider changing this to be a mutable reference: `&mut mutvar` +LL | +LL | *r = 0; + | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0596`. +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr index 5361ebe391..edab22569b 100644 --- a/src/test/ui/borrowck/mutability-errors.stderr +++ b/src/test/ui/borrowck/mutability-errors.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*x` which is behind a `&` reference +error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/mutability-errors.rs:9:5 | LL | fn named_ref(x: &(i32,)) { @@ -6,7 +6,7 @@ LL | fn named_ref(x: &(i32,)) { LL | *x = (1,); | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `x.0` which is behind a `&` reference +error[E0594]: cannot assign to `x.0`, which is behind a `&` reference --> $DIR/mutability-errors.rs:10:5 | LL | fn named_ref(x: &(i32,)) { @@ -57,7 +57,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | &mut f().0; | ^^^^^^^^^^ cannot borrow as mutable -error[E0594]: cannot assign to `*x` which is behind a `*const` pointer +error[E0594]: cannot assign to `*x`, which is behind a `*const` pointer --> $DIR/mutability-errors.rs:23:5 | LL | unsafe fn named_ptr(x: *const (i32,)) { @@ -65,7 +65,7 @@ LL | unsafe fn named_ptr(x: *const (i32,)) { LL | *x = (1,); | ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written -error[E0594]: cannot assign to `x.0` which is behind a `*const` pointer +error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer --> $DIR/mutability-errors.rs:24:5 | LL | unsafe fn named_ptr(x: *const (i32,)) { diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs index f7392bfeaa..50248a5583 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference.rs @@ -1,8 +1,8 @@ // revisions: nll_target -// The following revisions are disabled due to missing support from two-phase beyond autorefs +// The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs //[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-beyond-autoref -//[nll_beyond] should-fail +//[nll_beyond]should-fail //[nll_target]compile-flags: -Z borrowck=mir diff --git a/src/test/ui/bound-suggestions.stderr b/src/test/ui/bound-suggestions.stderr index a317790316..78f6259296 100644 --- a/src/test/ui/bound-suggestions.stderr +++ b/src/test/ui/bound-suggestions.stderr @@ -4,7 +4,6 @@ error[E0277]: `impl Sized` doesn't implement `Debug` LL | println!("{:?}", t); | ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting this bound | @@ -17,7 +16,6 @@ error[E0277]: `T` doesn't implement `Debug` LL | println!("{:?}", t); | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -30,7 +28,6 @@ error[E0277]: `T` doesn't implement `Debug` LL | println!("{:?}", t); | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting this bound | @@ -43,7 +40,6 @@ error[E0277]: `Y` doesn't implement `Debug` LL | println!("{:?} {:?}", x, y); | ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `Y` | @@ -56,7 +52,6 @@ error[E0277]: `X` doesn't implement `Debug` LL | println!("{:?}", x); | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting this bound | @@ -69,7 +64,6 @@ error[E0277]: `X` doesn't implement `Debug` LL | println!("{:?}", x); | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `X` | diff --git a/src/test/ui/box/into-boxed-slice-fail.stderr b/src/test/ui/box/into-boxed-slice-fail.stderr index 7a5ba16461..5e3b43a47e 100644 --- a/src/test/ui/box/into-boxed-slice-fail.stderr +++ b/src/test/ui/box/into-boxed-slice-fail.stderr @@ -5,7 +5,11 @@ LL | let _ = Box::into_boxed_slice(boxed_slice); | ^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: required by `Box::::into_boxed_slice` +note: required by `Box::::into_boxed_slice` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + | +LL | pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/into-boxed-slice-fail.rs:7:13 @@ -23,7 +27,11 @@ LL | let _ = Box::into_boxed_slice(boxed_trait); | ^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Debug` - = note: required by `Box::::into_boxed_slice` +note: required by `Box::::into_boxed_slice` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + | +LL | pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time --> $DIR/into-boxed-slice-fail.rs:11:13 diff --git a/src/test/ui/c-variadic/issue-86053-1.rs b/src/test/ui/c-variadic/issue-86053-1.rs new file mode 100644 index 0000000000..b30548e19f --- /dev/null +++ b/src/test/ui/c-variadic/issue-86053-1.rs @@ -0,0 +1,12 @@ +// Regression test for the ICE described in issue #86053. +// error-pattern:unexpected `self` parameter in function +// error-pattern:`...` must be the last argument of a C-variadic function +// error-pattern:cannot find type `F` in this scope +// error-pattern:in type `&'a &'b usize`, reference has a longer lifetime than the data it references + +#![feature(c_variadic)] +#![crate_type="lib"] + +fn ordering4 < 'a , 'b > ( a : , self , self , self , + self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { +} diff --git a/src/test/ui/c-variadic/issue-86053-1.stderr b/src/test/ui/c-variadic/issue-86053-1.stderr new file mode 100644 index 0000000000..ec7ee74aef --- /dev/null +++ b/src/test/ui/c-variadic/issue-86053-1.stderr @@ -0,0 +1,101 @@ +error: expected type, found `,` + --> $DIR/issue-86053-1.rs:10:47 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^ expected type + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:10:51 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:10:58 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:10:67 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:11:5 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:11:20 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:11:29 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function + +error: `...` must be the last argument of a C-variadic function + --> $DIR/issue-86053-1.rs:11:12 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/issue-86053-1.rs:11:12 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/issue-86053-1.rs:11:36 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ + +error[E0412]: cannot find type `F` in this scope + --> $DIR/issue-86053-1.rs:11:48 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^ + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn: FnMut { + | ------------------------------- similarly named trait `Fn` defined here + | +help: a trait with a similar name exists + | +LL | self , ... , self , self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) { + | ^^ +help: you might be missing a type parameter + | +LL | fn ordering4 < 'a , 'b, F > ( a : , self , self , self , + | ^^^ + +error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references + --> $DIR/issue-86053-1.rs:11:52 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined on the function body at 10:16 + --> $DIR/issue-86053-1.rs:10:16 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 10:21 + --> $DIR/issue-86053-1.rs:10:21 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0412, E0491. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/c-variadic/issue-86053-2.rs b/src/test/ui/c-variadic/issue-86053-2.rs new file mode 100644 index 0000000000..c545831f71 --- /dev/null +++ b/src/test/ui/c-variadic/issue-86053-2.rs @@ -0,0 +1,11 @@ +// Regression test for the ICE caused by the example in +// https://github.com/rust-lang/rust/issues/86053#issuecomment-855672258 + +#![feature(c_variadic)] + +trait H {} + +unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} +//~^ ERROR: in type `&'static &'a ()`, reference has a longer lifetime than the data it references [E0491] + +fn main() {} diff --git a/src/test/ui/c-variadic/issue-86053-2.stderr b/src/test/ui/c-variadic/issue-86053-2.stderr new file mode 100644 index 0000000000..4fc5e6315e --- /dev/null +++ b/src/test/ui/c-variadic/issue-86053-2.stderr @@ -0,0 +1,16 @@ +error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/issue-86053-2.rs:8:39 + | +LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 8:32 + --> $DIR/issue-86053-2.rs:8:32 + | +LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/src/test/ui/c-variadic/variadic-ffi-1.rs b/src/test/ui/c-variadic/variadic-ffi-1.rs index 2c02a0d308..a76efd9a20 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.rs +++ b/src/test/ui/c-variadic/variadic-ffi-1.rs @@ -1,6 +1,9 @@ -// ignore-arm stdcall isn't supported -// ignore-aarch64 stdcall isn't supported -// ignore-riscv64 stdcall isn't supported +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } extern "stdcall" { fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr index 6f2a6c359b..5b4e656d9d 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr @@ -1,11 +1,11 @@ error[E0045]: C-variadic function must have C or cdecl calling convention - --> $DIR/variadic-ffi-1.rs:6:5 + --> $DIR/variadic-ffi-1.rs:9:5 | LL | fn printf(_: *const u8, ...); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied - --> $DIR/variadic-ffi-1.rs:17:9 + --> $DIR/variadic-ffi-1.rs:20:9 | LL | foo(); | ^^^-- supplied 0 arguments @@ -13,13 +13,13 @@ LL | foo(); | expected at least 2 arguments | note: function defined here - --> $DIR/variadic-ffi-1.rs:10:8 + --> $DIR/variadic-ffi-1.rs:13:8 | LL | fn foo(f: isize, x: u8, ...); | ^^^ error[E0060]: this function takes at least 2 arguments but 1 argument was supplied - --> $DIR/variadic-ffi-1.rs:18:9 + --> $DIR/variadic-ffi-1.rs:21:9 | LL | foo(1); | ^^^ - supplied 1 argument @@ -27,13 +27,13 @@ LL | foo(1); | expected at least 2 arguments | note: function defined here - --> $DIR/variadic-ffi-1.rs:10:8 + --> $DIR/variadic-ffi-1.rs:13:8 | LL | fn foo(f: isize, x: u8, ...); | ^^^ error[E0308]: mismatched types - --> $DIR/variadic-ffi-1.rs:20:56 + --> $DIR/variadic-ffi-1.rs:23:56 | LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; | ------------------------------------- ^^^ expected non-variadic fn, found variadic function @@ -44,7 +44,7 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; found fn item `unsafe extern "C" fn(_, _, ...) {foo}` error[E0308]: mismatched types - --> $DIR/variadic-ffi-1.rs:21:54 + --> $DIR/variadic-ffi-1.rs:24:54 | LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; | ----------------------------------- ^^^ expected variadic fn, found non-variadic function @@ -55,37 +55,37 @@ LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; found fn item `extern "C" fn(_, _) {bar}` error[E0617]: can't pass `f32` to variadic function - --> $DIR/variadic-ffi-1.rs:23:19 + --> $DIR/variadic-ffi-1.rs:26:19 | LL | foo(1, 2, 3f32); | ^^^^ help: cast the value to `c_double`: `3f32 as c_double` error[E0617]: can't pass `bool` to variadic function - --> $DIR/variadic-ffi-1.rs:24:19 + --> $DIR/variadic-ffi-1.rs:27:19 | LL | foo(1, 2, true); | ^^^^ help: cast the value to `c_int`: `true as c_int` error[E0617]: can't pass `i8` to variadic function - --> $DIR/variadic-ffi-1.rs:25:19 + --> $DIR/variadic-ffi-1.rs:28:19 | LL | foo(1, 2, 1i8); | ^^^ help: cast the value to `c_int`: `1i8 as c_int` error[E0617]: can't pass `u8` to variadic function - --> $DIR/variadic-ffi-1.rs:26:19 + --> $DIR/variadic-ffi-1.rs:29:19 | LL | foo(1, 2, 1u8); | ^^^ help: cast the value to `c_uint`: `1u8 as c_uint` error[E0617]: can't pass `i16` to variadic function - --> $DIR/variadic-ffi-1.rs:27:19 + --> $DIR/variadic-ffi-1.rs:30:19 | LL | foo(1, 2, 1i16); | ^^^^ help: cast the value to `c_int`: `1i16 as c_int` error[E0617]: can't pass `u16` to variadic function - --> $DIR/variadic-ffi-1.rs:28:19 + --> $DIR/variadic-ffi-1.rs:31:19 | LL | foo(1, 2, 1u16); | ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint` diff --git a/src/test/ui/cast/cast-ptr-to-int-const.mir.stderr b/src/test/ui/cast/cast-ptr-to-int-const.mir.stderr deleted file mode 100644 index dcc9a243f0..0000000000 --- a/src/test/ui/cast/cast-ptr-to-int-const.mir.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block - --> $DIR/cast-ptr-to-int-const.rs:10:9 - | -LL | &Y as *const u32 as usize - | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int - | - = note: casting pointers to integers in constants - -error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block - --> $DIR/cast-ptr-to-int-const.rs:17:5 - | -LL | &0 as *const i32 as usize - | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int - | - = note: casting pointers to integers in constants - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs deleted file mode 100644 index 01ea627679..0000000000 --- a/src/test/ui/cast/cast-ptr-to-int-const.rs +++ /dev/null @@ -1,19 +0,0 @@ -// revisions: mir thir -// [thir]compile-flags: -Z thir-unsafeck - -#![feature(const_raw_ptr_to_usize_cast)] - -fn main() { - const Y: u32 = 0; - // Cast in `const` without `unsafe` block - const SAFE: usize = { - &Y as *const u32 as usize - //~^ ERROR cast of pointer to int is unsafe and requires unsafe - }; -} - -// Cast in `const fn` without `unsafe` block -const fn test() -> usize { - &0 as *const i32 as usize - //~^ ERROR cast of pointer to int is unsafe and requires unsafe -} diff --git a/src/test/ui/cast/cast-ptr-to-int-const.thir.stderr b/src/test/ui/cast/cast-ptr-to-int-const.thir.stderr deleted file mode 100644 index dcc9a243f0..0000000000 --- a/src/test/ui/cast/cast-ptr-to-int-const.thir.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block - --> $DIR/cast-ptr-to-int-const.rs:10:9 - | -LL | &Y as *const u32 as usize - | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int - | - = note: casting pointers to integers in constants - -error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block - --> $DIR/cast-ptr-to-int-const.rs:17:5 - | -LL | &0 as *const i32 as usize - | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int - | - = note: casting pointers to integers in constants - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/cast/fat-ptr-cast-rpass.rs b/src/test/ui/cast/fat-ptr-cast-rpass.rs index 9fa2255e1b..f5747eb8b9 100644 --- a/src/test/ui/cast/fat-ptr-cast-rpass.rs +++ b/src/test/ui/cast/fat-ptr-cast-rpass.rs @@ -1,12 +1,6 @@ // run-pass -// Remove this file when `std::raw` is removed. -// The replacement pointer metadata APIs are tested in library/core/tests/ptr.rs -#![allow(deprecated)] -#![feature(raw)] - -use std::mem; -use std::raw; +#![feature(ptr_metadata)] trait Foo { fn foo(&self) {} @@ -31,13 +25,10 @@ fn main() { // And conversion to a void pointer/address for trait objects too. let a: *mut dyn Foo = &mut Bar; - let b = a as *mut (); + let b = a as *mut () as usize; let c = a as *const () as usize; - let d = unsafe { - let r: raw::TraitObject = mem::transmute(a); - r.data - }; + let d = a.to_raw_parts().0 as usize; assert_eq!(b, d); - assert_eq!(c, d as usize); + assert_eq!(c, d); } diff --git a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs b/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs deleted file mode 100644 index 03e99eb752..0000000000 --- a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn main() { - const X: usize = unsafe { - main as usize //~ ERROR casting pointers to integers in constants is unstable - }; - const Y: u32 = 0; - const Z: usize = unsafe { - &Y as *const u32 as usize //~ ERROR is unstable - }; -} - -const fn test() -> usize { - &0 as *const i32 as usize //~ ERROR is unstable -} diff --git a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr b/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr deleted file mode 100644 index 4a0b424e18..0000000000 --- a/src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:3:9 - | -LL | main as usize - | ^^^^^^^^^^^^^ - | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable - -error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:7:9 - | -LL | &Y as *const u32 as usize - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable - -error[E0658]: casting pointers to integers in constant functions is unstable - --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:12:5 - | -LL | &0 as *const i32 as usize - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` 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/cfg/cfg-target-abi.rs b/src/test/ui/cfg/cfg-target-abi.rs new file mode 100644 index 0000000000..acc570fc84 --- /dev/null +++ b/src/test/ui/cfg/cfg-target-abi.rs @@ -0,0 +1,10 @@ +// run-pass +#![feature(cfg_target_abi)] + +#[cfg(target_abi = "eabihf")] +pub fn main() { +} + +#[cfg(not(target_abi = "eabihf"))] +pub fn main() { +} diff --git a/src/test/ui/chalkify/type_wf.stderr b/src/test/ui/chalkify/type_wf.stderr index 3cd6036945..ebd885a7d3 100644 --- a/src/test/ui/chalkify/type_wf.stderr +++ b/src/test/ui/chalkify/type_wf.stderr @@ -1,15 +1,17 @@ error[E0277]: the trait bound `{float}: Foo` is not satisfied --> $DIR/type_wf.rs:18:13 | -LL | struct S { - | ---------------- required by `S` -... LL | let s = S { | ^ the trait `Foo` is not implemented for `{float}` | = help: the following implementations were found: as Foo> +note: required by `S` + --> $DIR/type_wf.rs:6:1 + | +LL | struct S { + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs index 131af6a10c..7a4b21f022 100644 --- a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs +++ b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 #![feature(rustc_attrs)] // Ensure that capture analysis results in arrays being completely captured. diff --git a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr index 2a350f3033..69ec53447b 100644 --- a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr +++ b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/arrays-completely-captured.rs:11:17 + --> $DIR/arrays-completely-captured.rs:8:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let mut c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/arrays-completely-captured.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/arrays-completely-captured.rs:14:5 + --> $DIR/arrays-completely-captured.rs:11:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing m[] -> MutBorrow - --> $DIR/arrays-completely-captured.rs:17:9 + --> $DIR/arrays-completely-captured.rs:14:9 | LL | m[0] += 10; | ^ error: Min Capture analysis includes: - --> $DIR/arrays-completely-captured.rs:14:5 + --> $DIR/arrays-completely-captured.rs:11:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture m[] -> MutBorrow - --> $DIR/arrays-completely-captured.rs:17:9 + --> $DIR/arrays-completely-captured.rs:14:9 | LL | m[0] += 10; | ^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/by_value.rs b/src/test/ui/closures/2229_closure_analysis/by_value.rs index 27c8fb1363..d8d3bbee20 100644 --- a/src/test/ui/closures/2229_closure_analysis/by_value.rs +++ b/src/test/ui/closures/2229_closure_analysis/by_value.rs @@ -1,11 +1,7 @@ +// edition:2021 + // Test that we handle derferences properly when only some of the captures are being moved with // `capture_disjoint_fields` enabled. - - -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] #[derive(Debug, Default)] @@ -26,8 +22,7 @@ fn big_box() { //~^ First Pass analysis includes: //~| Min Capture analysis includes: let p = t.0.0; - //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Capturing t[(0, 0)] -> ByValue + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue //~| NOTE: Min Capture t[(0, 0)] -> ByValue println!("{} {:?}", t.1, p); //~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow diff --git a/src/test/ui/closures/2229_closure_analysis/by_value.stderr b/src/test/ui/closures/2229_closure_analysis/by_value.stderr index 944e4c40a7..097462253a 100644 --- a/src/test/ui/closures/2229_closure_analysis/by_value.stderr +++ b/src/test/ui/closures/2229_closure_analysis/by_value.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/by_value.rs:22:13 + --> $DIR/by_value.rs:18:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/by_value.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/by_value.rs:25:5 + --> $DIR/by_value.rs:21:5 | LL | / || { LL | | @@ -28,24 +19,19 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/by_value.rs:28:17 - | -LL | let p = t.0.0; - | ^^^^^ -note: Capturing t[(0, 0)] -> ByValue - --> $DIR/by_value.rs:28:17 +note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue + --> $DIR/by_value.rs:24:17 | LL | let p = t.0.0; | ^^^^^ note: Capturing t[(1, 0)] -> ImmBorrow - --> $DIR/by_value.rs:32:29 + --> $DIR/by_value.rs:27:29 | LL | println!("{} {:?}", t.1, p); | ^^^ error: Min Capture analysis includes: - --> $DIR/by_value.rs:25:5 + --> $DIR/by_value.rs:21:5 | LL | / || { LL | | @@ -57,16 +43,16 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/by_value.rs:28:17 + --> $DIR/by_value.rs:24:17 | LL | let p = t.0.0; | ^^^^^ note: Min Capture t[(1, 0)] -> ImmBorrow - --> $DIR/by_value.rs:32:29 + --> $DIR/by_value.rs:27:29 | LL | println!("{} {:?}", t.1, p); | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs index 4368c830e1..dc53b31768 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr index 09255343af..fceafb9c84 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-1.rs:17:13 + --> $DIR/capture-analysis-1.rs:15:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-1.rs:20:5 + --> $DIR/capture-analysis-1.rs:18:5 | LL | / || { LL | | @@ -29,28 +20,28 @@ LL | | }; | |_____^ | note: Capturing p[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:23:26 + --> $DIR/capture-analysis-1.rs:21:26 | LL | println!("{:?}", p); | ^ note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:26:26 + --> $DIR/capture-analysis-1.rs:24:26 | LL | println!("{:?}", p.x); | ^^^ note: Capturing q[(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:29:26 + --> $DIR/capture-analysis-1.rs:27:26 | LL | println!("{:?}", q.x); | ^^^ note: Capturing q[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:31:26 + --> $DIR/capture-analysis-1.rs:29:26 | LL | println!("{:?}", q); | ^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-1.rs:20:5 + --> $DIR/capture-analysis-1.rs:18:5 | LL | / || { LL | | @@ -62,16 +53,16 @@ LL | | }; | |_____^ | note: Min Capture p[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:23:26 + --> $DIR/capture-analysis-1.rs:21:26 | LL | println!("{:?}", p); | ^ note: Min Capture q[] -> ImmBorrow - --> $DIR/capture-analysis-1.rs:31:26 + --> $DIR/capture-analysis-1.rs:29:26 | LL | println!("{:?}", q); | ^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs index ab7fce6a43..99d12f8d8f 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr index 0e48d6b300..cb44ca2665 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-2.rs:16:13 + --> $DIR/capture-analysis-2.rs:14:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-2.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-2.rs:19:5 + --> $DIR/capture-analysis-2.rs:17:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ByValue - --> $DIR/capture-analysis-2.rs:22:18 + --> $DIR/capture-analysis-2.rs:20:18 | LL | let _x = p.x; | ^^^ note: Capturing p[] -> ImmBorrow - --> $DIR/capture-analysis-2.rs:25:26 + --> $DIR/capture-analysis-2.rs:23:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-2.rs:19:5 + --> $DIR/capture-analysis-2.rs:17:5 | LL | / || { LL | | @@ -52,7 +43,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> ByValue - --> $DIR/capture-analysis-2.rs:22:18 + --> $DIR/capture-analysis-2.rs:20:18 | LL | let _x = p.x; | ^^^ p[] captured as ByValue here @@ -60,6 +51,6 @@ LL | let _x = p.x; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs index 817ade899e..3f337097db 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr index 263e9ca56e..71e7bdc354 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-3.rs:21:13 + --> $DIR/capture-analysis-3.rs:19:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-3.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-3.rs:24:5 + --> $DIR/capture-analysis-3.rs:22:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing a[(0, 0),(0, 0)] -> ByValue - --> $DIR/capture-analysis-3.rs:27:18 + --> $DIR/capture-analysis-3.rs:25:18 | LL | let _x = a.b.c; | ^^^^^ note: Capturing a[(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-3.rs:30:26 + --> $DIR/capture-analysis-3.rs:28:26 | LL | println!("{:?}", a.b); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-3.rs:24:5 + --> $DIR/capture-analysis-3.rs:22:5 | LL | / || { LL | | @@ -52,7 +43,7 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-3.rs:27:18 + --> $DIR/capture-analysis-3.rs:25:18 | LL | let _x = a.b.c; | ^^^^^ a[(0, 0)] captured as ByValue here @@ -60,6 +51,6 @@ LL | let _x = a.b.c; LL | println!("{:?}", a.b); | ^^^ a[(0, 0)] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs index e8401299b3..bc46ec9973 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr index f4605c1d51..7e6e625bc7 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-4.rs:21:13 + --> $DIR/capture-analysis-4.rs:19:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-analysis-4.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/capture-analysis-4.rs:24:5 + --> $DIR/capture-analysis-4.rs:22:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-4.rs:27:18 + --> $DIR/capture-analysis-4.rs:25:18 | LL | let _x = a.b; | ^^^ note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/capture-analysis-4.rs:30:26 + --> $DIR/capture-analysis-4.rs:28:26 | LL | println!("{:?}", a.b.c); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-4.rs:24:5 + --> $DIR/capture-analysis-4.rs:22:5 | LL | / || { LL | | @@ -52,11 +43,11 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-4.rs:27:18 + --> $DIR/capture-analysis-4.rs:25:18 | LL | let _x = a.b; | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs index ba49550853..6fd1515533 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr index 5fac6963af..0f64ecf3a0 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-disjoint-field-struct.rs:17:13 + --> $DIR/capture-disjoint-field-struct.rs:13:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-struct.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/capture-disjoint-field-struct.rs:20:5 + --> $DIR/capture-disjoint-field-struct.rs:16:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-struct.rs:23:24 + --> $DIR/capture-disjoint-field-struct.rs:19:24 | LL | println!("{}", p.x); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-disjoint-field-struct.rs:20:5 + --> $DIR/capture-disjoint-field-struct.rs:16:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-struct.rs:23:24 + --> $DIR/capture-disjoint-field-struct.rs:19:24 | LL | println!("{}", p.x); | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs index c1693fbad7..8d3bb3262f 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr index 1bfd63f2ac..a8ca9622a6 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-disjoint-field-tuple.rs:12:13 + --> $DIR/capture-disjoint-field-tuple.rs:8:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-tuple.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/capture-disjoint-field-tuple.rs:15:5 + --> $DIR/capture-disjoint-field-tuple.rs:11:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-tuple.rs:18:24 + --> $DIR/capture-disjoint-field-tuple.rs:14:24 | LL | println!("{}", t.0); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-disjoint-field-tuple.rs:15:5 + --> $DIR/capture-disjoint-field-tuple.rs:11:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ImmBorrow - --> $DIR/capture-disjoint-field-tuple.rs:18:24 + --> $DIR/capture-disjoint-field-tuple.rs:14:24 | LL | println!("{}", t.0); | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/capture-enums.rs b/src/test/ui/closures/2229_closure_analysis/capture-enums.rs index 8fb2f7f16d..322ae99b86 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-enums.rs +++ b/src/test/ui/closures/2229_closure_analysis/capture-enums.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] enum Info { diff --git a/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr b/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr index ebe1dcb988..8a6ba8444a 100644 --- a/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr +++ b/src/test/ui/closures/2229_closure_analysis/capture-enums.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:18:13 + --> $DIR/capture-enums.rs:16:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:49:13 + --> $DIR/capture-enums.rs:47:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,17 +16,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-enums.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/capture-enums.rs:21:5 + --> $DIR/capture-enums.rs:19:5 | LL | / || { LL | | @@ -38,28 +29,28 @@ LL | | }; | |_____^ | note: Capturing point[] -> ImmBorrow - --> $DIR/capture-enums.rs:24:41 + --> $DIR/capture-enums.rs:22:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:24:41 + --> $DIR/capture-enums.rs:22:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Capturing meta[] -> ImmBorrow - --> $DIR/capture-enums.rs:31:35 + --> $DIR/capture-enums.rs:29:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ note: Capturing meta[(1, 1)] -> ByValue - --> $DIR/capture-enums.rs:31:35 + --> $DIR/capture-enums.rs:29:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:21:5 + --> $DIR/capture-enums.rs:19:5 | LL | / || { LL | | @@ -71,18 +62,18 @@ LL | | }; | |_____^ | note: Min Capture point[] -> ByValue - --> $DIR/capture-enums.rs:24:41 + --> $DIR/capture-enums.rs:22:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Min Capture meta[] -> ByValue - --> $DIR/capture-enums.rs:31:35 + --> $DIR/capture-enums.rs:29:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ error: First Pass analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:50:5 | LL | / || { LL | | @@ -94,13 +85,13 @@ LL | | }; | |_____^ | note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:53:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:50:5 | LL | / || { LL | | @@ -112,11 +103,11 @@ LL | | }; | |_____^ | note: Min Capture point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:53:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs index f81866bb7e..3341166e22 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr index 863f100913..29e1af0431 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/deep-multilevel-struct.rs:36:13 + --> $DIR/deep-multilevel-struct.rs:34:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/deep-multilevel-struct.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/deep-multilevel-struct.rs:39:5 + --> $DIR/deep-multilevel-struct.rs:37:5 | LL | / || { LL | | @@ -29,23 +20,23 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/deep-multilevel-struct.rs:42:18 + --> $DIR/deep-multilevel-struct.rs:40:18 | LL | let x = &p.a.p.x; | ^^^^^^^ note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow - --> $DIR/deep-multilevel-struct.rs:44:9 + --> $DIR/deep-multilevel-struct.rs:42:9 | LL | p.b.q.y = 9; | ^^^^^^^ note: Capturing p[] -> ImmBorrow - --> $DIR/deep-multilevel-struct.rs:47:26 + --> $DIR/deep-multilevel-struct.rs:45:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/deep-multilevel-struct.rs:39:5 + --> $DIR/deep-multilevel-struct.rs:37:5 | LL | / || { LL | | @@ -57,7 +48,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> MutBorrow - --> $DIR/deep-multilevel-struct.rs:44:9 + --> $DIR/deep-multilevel-struct.rs:42:9 | LL | p.b.q.y = 9; | ^^^^^^^ p[] captured as MutBorrow here @@ -65,6 +56,6 @@ LL | p.b.q.y = 9; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs index fb03a02efa..34b0132f3c 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr index 252db44473..e917516765 100644 --- a/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr +++ b/src/test/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/deep-multilevel-tuple.rs:11:13 + --> $DIR/deep-multilevel-tuple.rs:8:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/deep-multilevel-tuple.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/deep-multilevel-tuple.rs:14:5 + --> $DIR/deep-multilevel-tuple.rs:11:5 | LL | / || { LL | | @@ -29,23 +20,23 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/deep-multilevel-tuple.rs:17:18 + --> $DIR/deep-multilevel-tuple.rs:14:18 | LL | let x = &t.0.0.0; | ^^^^^^^ note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow - --> $DIR/deep-multilevel-tuple.rs:19:9 + --> $DIR/deep-multilevel-tuple.rs:16:9 | LL | t.1.1.1 = 9; | ^^^^^^^ note: Capturing t[] -> ImmBorrow - --> $DIR/deep-multilevel-tuple.rs:22:26 + --> $DIR/deep-multilevel-tuple.rs:19:26 | LL | println!("{:?}", t); | ^ error: Min Capture analysis includes: - --> $DIR/deep-multilevel-tuple.rs:14:5 + --> $DIR/deep-multilevel-tuple.rs:11:5 | LL | / || { LL | | @@ -57,7 +48,7 @@ LL | | }; | |_____^ | note: Min Capture t[] -> MutBorrow - --> $DIR/deep-multilevel-tuple.rs:19:9 + --> $DIR/deep-multilevel-tuple.rs:16:9 | LL | t.1.1.1 = 9; | ^^^^^^^ t[] captured as MutBorrow here @@ -65,6 +56,6 @@ LL | t.1.1.1 = 9; LL | println!("{:?}", t); | ^ t[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs index 080ca0405b..9918802334 100644 --- a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs +++ b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] // Test to ensure Index projections are handled properly during capture analysis diff --git a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr index 06ccc2d7a8..b53adb5248 100644 --- a/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr +++ b/src/test/ui/closures/2229_closure_analysis/destructure_patterns.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:12:13 + --> $DIR/destructure_patterns.rs:10:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:38:13 + --> $DIR/destructure_patterns.rs:36:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:58:13 + --> $DIR/destructure_patterns.rs:56:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,17 +25,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/destructure_patterns.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:15:5 + --> $DIR/destructure_patterns.rs:13:5 | LL | / || { LL | | @@ -47,13 +38,13 @@ LL | | }; | |_____^ | note: Capturing arr[Index] -> ByValue - --> $DIR/destructure_patterns.rs:18:29 + --> $DIR/destructure_patterns.rs:16:29 | LL | let [a, b, .., e] = arr; | ^^^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:15:5 + --> $DIR/destructure_patterns.rs:13:5 | LL | / || { LL | | @@ -65,13 +56,13 @@ LL | | }; | |_____^ | note: Min Capture arr[] -> ByValue - --> $DIR/destructure_patterns.rs:18:29 + --> $DIR/destructure_patterns.rs:16:29 | LL | let [a, b, .., e] = arr; | ^^^ error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:41:5 + --> $DIR/destructure_patterns.rs:39:5 | LL | / || { LL | | @@ -83,18 +74,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ note: Capturing p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:41:5 + --> $DIR/destructure_patterns.rs:39:5 | LL | / || { LL | | @@ -106,18 +97,18 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ note: Min Capture p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:44:58 + --> $DIR/destructure_patterns.rs:42:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:61:5 + --> $DIR/destructure_patterns.rs:59:5 | LL | / || { LL | | @@ -129,23 +120,23 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Capturing t[(1, 0)] -> ImmBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Capturing t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:61:5 + --> $DIR/destructure_patterns.rs:59:5 | LL | / || { LL | | @@ -157,21 +148,21 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> MutBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Min Capture t[(1, 0)] -> ImmBorrow - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Min Capture t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:64:54 + --> $DIR/destructure_patterns.rs:62:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs index 0b94317fd7..93131b2ac4 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs @@ -1,7 +1,6 @@ -// Test that arrays are completely captured by closures by relying on the borrow check diagnostics +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// Test that arrays are completely captured by closures by relying on the borrow check diagnostics fn arrays_1() { let mut arr = [1, 2, 3, 4, 5]; diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr index 77e3e71bc6..a3f2f25e44 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/arrays.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0503]: cannot use `arr` because it was mutably borrowed - --> $DIR/arrays.rs:15:5 + --> $DIR/arrays.rs:14:5 | LL | let mut c = || { | -- borrow of `arr` occurs here @@ -22,7 +13,7 @@ LL | c(); | - borrow later used here error[E0503]: cannot use `arr[_]` because it was mutably borrowed - --> $DIR/arrays.rs:15:5 + --> $DIR/arrays.rs:14:5 | LL | let mut c = || { | -- borrow of `arr` occurs here @@ -36,7 +27,7 @@ LL | c(); | - borrow later used here error[E0506]: cannot assign to `arr[_]` because it is borrowed - --> $DIR/arrays.rs:30:5 + --> $DIR/arrays.rs:29:5 | LL | let c = || { | -- borrow of `arr[_]` occurs here @@ -50,7 +41,7 @@ LL | c(); | - borrow later used here error[E0506]: cannot assign to `arr[_]` because it is borrowed - --> $DIR/arrays.rs:44:5 + --> $DIR/arrays.rs:43:5 | LL | let c = || { | -- borrow of `arr[_]` occurs here @@ -64,7 +55,7 @@ LL | c(); | - borrow later used here error[E0503]: cannot use `arr` because it was mutably borrowed - --> $DIR/arrays.rs:58:20 + --> $DIR/arrays.rs:57:20 | LL | let mut c = || { | -- borrow of `arr` occurs here @@ -78,7 +69,7 @@ LL | c(); | - borrow later used here error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable - --> $DIR/arrays.rs:58:20 + --> $DIR/arrays.rs:57:20 | LL | let mut c = || { | -- mutable borrow occurs here @@ -92,7 +83,7 @@ LL | c(); | - mutable borrow later used here error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable - --> $DIR/arrays.rs:74:24 + --> $DIR/arrays.rs:73:24 | LL | let mut c = || { | -- mutable borrow occurs here @@ -105,7 +96,7 @@ LL | println!("{:#?}", &arr[3..2]); LL | c(); | - mutable borrow later used here -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 7 previous errors Some errors have detailed explanations: E0502, E0503, E0506. For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs index 2f3358dcd8..3664d76c20 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr index e15067b264..341d2bc656 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0499]: cannot borrow `p` as mutable more than once at a time - --> $DIR/borrowck-1.rs:13:17 + --> $DIR/borrowck-1.rs:12:17 | LL | let y = &mut p.y; | -------- first mutable borrow occurs here @@ -23,6 +14,6 @@ LL | println!("{:?}", p); LL | *y+=1; | ----- first borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs index 06c6a87eb1..ae416bab65 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr index a195b981ea..584bb862b2 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-2.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-2.rs:13:17 + --> $DIR/borrowck-2.rs:12:17 | LL | let y = &p.y; | ---- immutable borrow occurs here @@ -23,6 +14,6 @@ LL | let x = &mut p.x; LL | println!("{}", y); | - immutable borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs index ba998f78c8..bdd6cb79b6 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr index b54c729a30..dab1809a38 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-3.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0597]: `p` does not live long enough - --> $DIR/borrowck-3.rs:14:29 + --> $DIR/borrowck-3.rs:13:29 | LL | let mut c = { | ----- borrow later stored here @@ -22,6 +13,6 @@ LL | println!("{:?}", p); LL | }; | - `p` dropped here while still borrowed -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs index 4fab0189c2..a2290d8502 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr index 905fa3475e..29bd4b27d6 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-4.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0373]: closure may outlive the current function, but it borrows `p`, which is owned by the current function - --> $DIR/borrowck-4.rs:11:17 + --> $DIR/borrowck-4.rs:10:17 | LL | let mut c = || { | ^^ may outlive borrowed value `p` @@ -17,7 +8,7 @@ LL | println!("{:?}", p); | - `p` is borrowed here | note: closure is returned here - --> $DIR/borrowck-4.rs:9:14 + --> $DIR/borrowck-4.rs:8:14 | LL | fn foo () -> impl FnMut()->() { | ^^^^^^^^^^^^^^^^ @@ -26,6 +17,6 @@ help: to force the closure to take ownership of `p` (and any other referenced va LL | let mut c = move || { | ^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs index b23947ad5d..6a8c966405 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs @@ -1,8 +1,8 @@ +// edition:2021 + // Tests that two closures cannot simultaneously have mutable // and immutable access to the variable. Issue #6801. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![feature(box_syntax)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr index 58975c6f46..5f1dae2972 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrowck-closures-mut-and-imm.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable --> $DIR/borrowck-closures-mut-and-imm.rs:17:14 | @@ -25,6 +16,6 @@ LL | }; LL | drop(c2); | -- immutable borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs index 15be1d8c72..a110fa4e2c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs @@ -1,7 +1,6 @@ -// Test borrow checker when we precise capture when using boxes +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// Test borrow checker when we precise capture when using boxes struct MetaData { x: String, name: String } struct Data { m: MetaData } diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr index 174faa33c4..2badf05141 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/box.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed - --> $DIR/box.rs:22:5 + --> $DIR/box.rs:21:5 | LL | let mut c = || { | -- borrow of `e.0.0.m.x` occurs here @@ -22,7 +13,7 @@ LL | c(); | - borrow later used here error[E0502]: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable - --> $DIR/box.rs:39:20 + --> $DIR/box.rs:38:20 | LL | let mut c = || { | -- mutable borrow occurs here @@ -36,7 +27,7 @@ LL | c(); | - mutable borrow later used here error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed - --> $DIR/box.rs:56:5 + --> $DIR/box.rs:55:5 | LL | let c = || { | -- borrow of `e.0.0.m.x` occurs here @@ -49,7 +40,7 @@ LL | LL | c(); | - borrow later used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0502, E0506. For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs index 1ea38e260b..77effcb006 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs @@ -1,18 +1,17 @@ +// edition:2021 + // Test that if we deref an immutable borrow to access a Place, // then we can't mutate the final place. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - fn main() { let mut x = (format!(""), format!("X2")); let mut y = (&x, "Y"); let z = (&mut y, "Z"); - // `x.0` is mutable but we access `x` via `z.0.0`, which is an immutable reference and + // `x.0` is mutable but we access `x` via `*z.0.0`, which is an immutable reference and // therefore can't be mutated. let mut c = || { - //~^ ERROR: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference + //~^ ERROR: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference z.0.0.0 = format!("X1"); }; diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr index 39a11fb332..38c530b809 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr @@ -1,21 +1,12 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cant-mutate-imm-borrow.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -error[E0596]: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference - --> $DIR/cant-mutate-imm-borrow.rs:14:17 +error[E0596]: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference + --> $DIR/cant-mutate-imm-borrow.rs:13:17 | LL | let mut c = || { | ^^ cannot borrow as mutable LL | LL | z.0.0.0 = format!("X1"); - | ------- mutable borrow occurs due to use of `z.0.0.0` in closure + | ------- mutable borrow occurs due to use of `*z.0.0` in closure -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs index 928c866726..25ee9a1490 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs @@ -1,5 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 // Ensure that diagnostics for mutability error (because the root variable // isn't mutable) work with `capture_disjoint_fields` enabled. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr index 9fb8dd4a1c..98414fa8a3 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cant-mutate-imm.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0594]: cannot assign to `z.0.0.0`, as it is not declared as mutable - --> $DIR/cant-mutate-imm.rs:13:9 + --> $DIR/cant-mutate-imm.rs:12:9 | LL | let z = (y, 10); | - help: consider changing this to be mutable: `mut z` @@ -17,7 +8,7 @@ LL | z.0.0.0 = 20; | ^^^^^^^^^^^^ cannot assign error[E0594]: cannot assign to `*bx.0`, as it is not declared as mutable - --> $DIR/cant-mutate-imm.rs:25:9 + --> $DIR/cant-mutate-imm.rs:24:9 | LL | let bx = Box::new(x); | -- help: consider changing this to be mutable: `mut bx` @@ -25,6 +16,6 @@ LL | let bx = Box::new(x); LL | bx.0 = 20; | ^^^^^^^^^ cannot assign -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs index cd7c25620a..f3be542e40 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 // Test that array access is not stored as part of closure kind origin diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr index bd9428771f..bcde35983f 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-array-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/closure-origin-array-diagnostics.rs:12:13 + --> $DIR/closure-origin-array-diagnostics.rs:9:13 | LL | let c = || { | ^^ this closure implements `FnOnce`, not `Fn` @@ -18,6 +9,6 @@ LL | }; LL | expect_fn(c); | --------- the requirement to implement `Fn` derives from here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0525`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs index 2916d8c794..aa85b55b15 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs @@ -1,11 +1,7 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 // Check that precise paths are being reported back in the error message. - enum MultiVariant { Point(i32, i32), Meta(i32) diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr index de0bfe3bd7..066c000c83 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-multi-variant-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0382]: use of moved value: `c` - --> $DIR/closure-origin-multi-variant-diagnostics.rs:30:13 + --> $DIR/closure-origin-multi-variant-diagnostics.rs:26:13 | LL | let a = c; | - value moved here @@ -16,11 +7,11 @@ LL | let b = c; | ^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment - --> $DIR/closure-origin-multi-variant-diagnostics.rs:20:52 + --> $DIR/closure-origin-multi-variant-diagnostics.rs:16:52 | LL | if let MultiVariant::Point(ref mut x, _) = point { | ^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs index 2ed0149b9d..bedb103cc4 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs @@ -1,9 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 -// Check that precise paths are being reported back in the error message. enum SingleVariant { Point(i32, i32), diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr index 402f5e4f33..2a6e00850f 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-single-variant-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0382]: use of moved value: `c` - --> $DIR/closure-origin-single-variant-diagnostics.rs:21:13 + --> $DIR/closure-origin-single-variant-diagnostics.rs:17:13 | LL | let b = c; | - value moved here @@ -16,11 +7,11 @@ LL | let a = c; | ^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment - --> $DIR/closure-origin-single-variant-diagnostics.rs:16:50 + --> $DIR/closure-origin-single-variant-diagnostics.rs:12:50 | LL | let SingleVariant::Point(ref mut x, _) = point; | ^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs index 103890f1f3..3277a83c4e 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 // Check that precise paths are being reported back in the error message. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr index 474d77b7cd..d7fc51c55e 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-struct-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0382]: use of moved value: `hello` - --> $DIR/closure-origin-struct-diagnostics.rs:24:13 + --> $DIR/closure-origin-struct-diagnostics.rs:21:13 | LL | let b = hello; | ----- value moved here @@ -16,11 +7,11 @@ LL | let c = hello; | ^^^^^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment - --> $DIR/closure-origin-struct-diagnostics.rs:20:9 + --> $DIR/closure-origin-struct-diagnostics.rs:17:9 | LL | x.y.a += 1; | ^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs index 6b078d2329..dc3a57ae79 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 // Check that precise paths are being reported back in the error message. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr index 716728e96e..63e2d300eb 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-tuple-diagnostics-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0382]: use of moved value: `hello` - --> $DIR/closure-origin-tuple-diagnostics-1.rs:15:13 + --> $DIR/closure-origin-tuple-diagnostics-1.rs:12:13 | LL | let b = hello; | ----- value moved here @@ -16,11 +7,11 @@ LL | let c = hello; | ^^^^^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment - --> $DIR/closure-origin-tuple-diagnostics-1.rs:11:9 + --> $DIR/closure-origin-tuple-diagnostics-1.rs:8:9 | LL | x.0 += 1; | ^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs index 0638db6076..fa1328013d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 + struct S(String, String); fn expect_fn(_f: F) {} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr index 77eb2a94ff..df33c4f1fd 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closure-origin-tuple-diagnostics.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/closure-origin-tuple-diagnostics.rs:11:13 + --> $DIR/closure-origin-tuple-diagnostics.rs:9:13 | LL | let c = || { | ^^ this closure implements `FnOnce`, not `Fn` @@ -18,6 +9,6 @@ LL | }; LL | expect_fn(c); | --------- the requirement to implement `Fn` derives from here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0525`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs index 09491f296f..1cc22fac35 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs @@ -1,6 +1,6 @@ +// edition:2021 + // check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![allow(unreachable_code)] #![warn(unused)] 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 81bbc4e1dc..4eac5a2d28 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/liveness.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - warning: value captured by `a` is never read --> $DIR/liveness.rs:23:9 | @@ -75,5 +66,5 @@ LL | b = Some("e1"); | = help: did you mean to capture by reference instead? -warning: 8 warnings emitted +warning: 7 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs index e2035464df..10a7d07a1d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs @@ -1,6 +1,6 @@ +// edition:2021 + // check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![warn(unused)] #[derive(Debug)] 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 35b0c22fc4..f74303e3dd 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/liveness_unintentional_copy.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - warning: value assigned to `a` is never read --> $DIR/liveness_unintentional_copy.rs:19:9 | @@ -43,5 +34,5 @@ LL | a += x; | = help: did you mean to capture by reference instead? -warning: 4 warnings emitted +warning: 3 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs index 39b04c833e..fa73ff23f9 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs @@ -1,8 +1,8 @@ +// edition:2021 + // Test that when a borrow checker diagnostics are emitted, it's as precise // as the capture by the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![allow(unused)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr index a3d1f55055..ac4c9c9376 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr @@ -1,12 +1,3 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0499]: cannot borrow `w.p.x` as mutable more than once at a time --> $DIR/multilevel-path.rs:23:14 | @@ -21,6 +12,6 @@ LL | LL | c(); | - first borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs index 676fde558d..3d5a31e8b8 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs @@ -1,9 +1,8 @@ +// edition:2021 + // Test that we can't mutate a place if we need to deref an imm-borrow // to reach it. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - fn imm_mut_ref() { let mut x = String::new(); let y = String::new(); diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr index 831e486db8..dbf8523a3b 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/mut_ref.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference - --> $DIR/mut_ref.rs:13:13 + --> $DIR/mut_ref.rs:12:13 | LL | let ref_mref_x = &mref_x; | ------- help: consider changing this to be a mutable reference: `&mut mref_x` @@ -20,7 +11,7 @@ LL | **ref_mref_x = y; | ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference - --> $DIR/mut_ref.rs:27:13 + --> $DIR/mut_ref.rs:26:13 | LL | let c = || { | ^^ cannot borrow as mutable @@ -28,6 +19,6 @@ LL | LL | **mref_ref_x = y; | ------------ mutable borrow occurs due to use of `**mref_ref_x` in closure -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs index 82ec60a2e7..4799f488d7 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs @@ -1,7 +1,6 @@ -// check-pass +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// check-pass // Given how the closure desugaring is implemented (at least at the time of writing this test), // we don't need to truncate the captured path to a reference into a packed-struct if the field 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 e8cc164be8..d2466681a0 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 @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/repr_packed.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - warning: reference to packed field is unaligned - --> $DIR/repr_packed.rs:25:24 + --> $DIR/repr_packed.rs:24:24 | LL | println!("{}", foo.x); | ^^^^^ @@ -18,5 +9,5 @@ LL | println!("{}", foo.x); = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs index e78d8715e4..ed2d9a3de0 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs @@ -1,9 +1,8 @@ +// edition:2021 + // Test that borrow checker error is accurate and that min capture pass of the // closure analysis is working as expected. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - #[derive(Debug)] struct Point { x: i32, diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr index f1748fda15..32705af3d0 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/simple-struct-min-capture.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable - --> $DIR/simple-struct-min-capture.rs:23:22 + --> $DIR/simple-struct-min-capture.rs:22:22 | LL | let mut c = || { | -- mutable borrow occurs here @@ -23,6 +14,6 @@ LL | LL | c(); | - mutable borrow later used here -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs index a3222635b6..269cf76e67 100644 --- a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs +++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr index a031360ed3..b936c5ee35 100644 --- a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr +++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/feature-gate-capture_disjoint_fields.rs:10:13 + --> $DIR/feature-gate-capture_disjoint_fields.rs:8:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/feature-gate-capture_disjoint_fields.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/feature-gate-capture_disjoint_fields.rs:13:5 + --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing s[] -> ImmBorrow - --> $DIR/feature-gate-capture_disjoint_fields.rs:16:69 + --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69 | LL | println!("This uses new capture analyysis to capture s={}", s); | ^ error: Min Capture analysis includes: - --> $DIR/feature-gate-capture_disjoint_fields.rs:13:5 + --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture s[] -> ImmBorrow - --> $DIR/feature-gate-capture_disjoint_fields.rs:16:69 + --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69 | LL | println!("This uses new capture analyysis to capture s={}", s); | ^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs index 9466e10389..bfa3ebcd6d 100644 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs +++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] struct Filter { diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr index e9420fe5a0..10e0d076b4 100644 --- a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr +++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr @@ -1,35 +1,26 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/filter-on-struct-member.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/filter-on-struct-member.rs:28:13 + --> $DIR/filter-on-struct-member.rs:24:13 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: Capturing self[Deref,(0, 0)] -> ImmBorrow - --> $DIR/filter-on-struct-member.rs:28:17 + --> $DIR/filter-on-struct-member.rs:24:17 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/filter-on-struct-member.rs:28:13 + --> $DIR/filter-on-struct-member.rs:24:13 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: Min Capture self[Deref,(0, 0)] -> ImmBorrow - --> $DIR/filter-on-struct-member.rs:28:17 + --> $DIR/filter-on-struct-member.rs:24:17 | LL | |v| self.filter.allowed(*v), | ^^^^^^^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/issue-87097.rs new file mode 100644 index 0000000000..241ddcb83e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-87097.rs @@ -0,0 +1,35 @@ +// run-pass +// edition:2021 + +enum Variant { + A, + B, //~ WARNING: variant is never constructed: `B` +} + +struct A { + field: Variant, +} + +fn discriminant_is_a_ref() { + let here = A { field: Variant::A }; + let out_ref = &here.field; + + || match out_ref { //~ WARNING: unused closure that must be used + Variant::A => (), + Variant::B => (), + }; +} + +fn discriminant_is_a_field() { + let here = A { field: Variant::A }; + + || match here.field { //~ WARNING: unused closure that must be used + Variant::A => (), + Variant::B => (), + }; +} + +fn main() { + discriminant_is_a_ref(); + discriminant_is_a_field(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr new file mode 100644 index 0000000000..38f2929a05 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr @@ -0,0 +1,33 @@ +warning: variant is never constructed: `B` + --> $DIR/issue-87097.rs:6:5 + | +LL | B, + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: unused closure that must be used + --> $DIR/issue-87097.rs:17:5 + | +LL | / || match out_ref { +LL | | Variant::A => (), +LL | | Variant::B => (), +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: closures are lazy and do nothing unless called + +warning: unused closure that must be used + --> $DIR/issue-87097.rs:26:5 + | +LL | / || match here.field { +LL | | Variant::A => (), +LL | | Variant::B => (), +LL | | }; + | |______^ + | + = note: closures are lazy and do nothing unless called + +warning: 3 warnings emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed index 93e6cf0340..e2b7b8f027 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed @@ -1,25 +1,29 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here use std::thread; /* Test Send Trait Migration */ -struct SendPointer (*mut i32); +struct SendPointer(*mut i32); unsafe impl Send for SendPointer {} fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0` } }); } /* Test Sync Trait Migration */ -struct CustomInt (*mut i32); -struct SyncPointer (CustomInt); +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); unsafe impl Sync for SyncPointer {} unsafe impl Send for CustomInt {} @@ -28,9 +32,12 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0` } }); } @@ -38,7 +45,7 @@ fn test_sync_trait() { struct S(String); struct T(i32); -struct U(S,T); +struct U(S, T); impl Clone for U { fn clone(&self) -> Self { @@ -49,9 +56,12 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { let _ = &f; - //~^ ERROR: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1` println!("{:?}", f_1.0); }; @@ -59,6 +69,7 @@ fn test_clone_trait() { c_clone(); } +//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure fn main() { test_send_trait(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs index 2c0dbd0175..6c56ca2747 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs @@ -1,25 +1,29 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here use std::thread; /* Test Send Trait Migration */ -struct SendPointer (*mut i32); +struct SendPointer(*mut i32); unsafe impl Send for SendPointer {} fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || unsafe { - //~^ ERROR: `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0` }); } /* Test Sync Trait Migration */ -struct CustomInt (*mut i32); -struct SyncPointer (CustomInt); +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); unsafe impl Sync for SyncPointer {} unsafe impl Send for CustomInt {} @@ -28,9 +32,12 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0` }); } @@ -38,7 +45,7 @@ fn test_sync_trait() { struct S(String); struct T(i32); -struct U(S,T); +struct U(S, T); impl Clone for U { fn clone(&self) -> Self { @@ -49,9 +56,12 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1` println!("{:?}", f_1.0); }; @@ -59,6 +69,7 @@ fn test_clone_trait() { c_clone(); } +//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure fn main() { test_send_trait(); 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 6e3723b8bd..9c954b1465 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -1,69 +1,70 @@ -error: `Send` trait implementation affected for closure because of `capture_disjoint_fields` - --> $DIR/auto_traits.rs:13:19 +error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure + --> $DIR/auto_traits.rs:14:19 | -LL | thread::spawn(move || unsafe { - | ___________________^ -LL | | -LL | | -LL | | *fptr.0 = 20; -LL | | }); - | |_____^ +LL | thread::spawn(move || unsafe { + | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send` +... +LL | *fptr.0 = 20; + | ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0` | note: the lint level is defined here --> $DIR/auto_traits.rs:2:9 | -LL | #![deny(disjoint_capture_migration)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see help: add a dummy let to cause `fptr` to be fully captured | LL | thread::spawn(move || { let _ = &fptr; unsafe { LL | LL | +LL | +LL | LL | *fptr.0 = 20; -LL | } }); - | + ... -error: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields` - --> $DIR/auto_traits.rs:30:19 +error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure + --> $DIR/auto_traits.rs:34:19 | -LL | thread::spawn(move || unsafe { - | ___________________^ -LL | | -LL | | -LL | | *fptr.0.0 = 20; -LL | | }); - | |_____^ +LL | thread::spawn(move || unsafe { + | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` +... +LL | *fptr.0.0 = 20; + | --------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0` | + = note: for more information, see help: add a dummy let to cause `fptr` to be fully captured | LL | thread::spawn(move || { let _ = &fptr; unsafe { LL | LL | +LL | +LL | LL | *fptr.0.0 = 20; -LL | } }); - | + ... -error: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/auto_traits.rs:51:13 +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order + --> $DIR/auto_traits.rs:58:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let f_1 = f.1; -LL | | println!("{:?}", f_1.0); -LL | | }; - | |_____^ +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone` +... +LL | let f_1 = f.1; + | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1` +... +LL | } + | - in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `f` to be fully captured | LL | let c = || { let _ = &f; LL | LL | +LL | +LL | LL | let f_1 = f.1; -LL | println!("{:?}", f_1.0); -LL | }; - | + ... error: aborting due to 3 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed index 3770e93239..e836f27cd7 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here // Test cases for types that implement a insignificant drop (stlib defined) @@ -13,16 +13,23 @@ fn test1_all_need_migration() { let t2 = (String::new(), String::new()); let c = || { let _ = (&t, &t1, &t2); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -32,15 +39,20 @@ fn test2_only_precise_paths_need_migration() { let t2 = (String::new(), String::new()); let c = || { let _ = (&t, &t1); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -48,14 +60,17 @@ fn test3_only_by_value_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{}", t1.1); }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Copy types get copied into the closure instead of move. Therefore we don't need to // migrate then as their drop order isn't tied to the closure. @@ -66,14 +81,17 @@ fn test4_only_non_copy_types_need_migration() { let t1 = (0i32, 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn test5_only_drop_types_need_migration() { struct S(i32, i32); @@ -84,14 +102,17 @@ fn test5_only_drop_types_need_migration() { let s = S(0i32, 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _s = s.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -99,13 +120,18 @@ fn test6_move_closures_non_copy_types_might_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = move || { let _ = (&t1, &t); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{} {}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -114,13 +140,16 @@ fn test7_drop_non_drop_aggregate_need_migration() { let t = (String::new(), String::new(), 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { test1_all_need_migration(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs index 2015ab7e9b..fbf9b983f0 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs @@ -1,6 +1,6 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here // Test cases for types that implement a insignificant drop (stlib defined) @@ -13,16 +13,23 @@ fn test1_all_need_migration() { let t2 = (String::new(), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -32,15 +39,20 @@ fn test2_only_precise_paths_need_migration() { let t2 = (String::new(), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -48,14 +60,17 @@ fn test3_only_by_value_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{}", t1.1); }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Copy types get copied into the closure instead of move. Therefore we don't need to // migrate then as their drop order isn't tied to the closure. @@ -66,14 +81,17 @@ fn test4_only_non_copy_types_need_migration() { let t1 = (0i32, 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn test5_only_drop_types_need_migration() { struct S(i32, i32); @@ -84,14 +102,17 @@ fn test5_only_drop_types_need_migration() { let s = S(0i32, 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _s = s.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -99,13 +120,18 @@ fn test6_move_closures_non_copy_types_might_need_migration() { let t = (String::new(), String::new()); let t1 = (String::new(), String::new()); let c = move || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{} {}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -114,13 +140,16 @@ fn test7_drop_non_drop_aggregate_need_migration() { let t = (String::new(), String::new(), 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { test1_all_need_migration(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr index 69a99f7a53..e9e4794cff 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr @@ -1,159 +1,189 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/insignificant_drop.rs:15:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -... | -LL | | let _t2 = t2.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +LL | +LL | let _t2 = t2.0; + | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure + | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/insignificant_drop.rs:3:9 | -LL | #![deny(disjoint_capture_migration)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured | LL | let c = || { let _ = (&t, &t1, &t2); LL | LL | +LL | LL | LL | let _t = t.0; -LL | let _t1 = t1.0; ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:34:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; -LL | | let _t2 = t2; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:41:13 | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `t`, `t1` to be fully captured | LL | let c = || { let _ = (&t, &t1); LL | LL | +LL | LL | let _t = t.0; -LL | let _t1 = t1.0; -LL | let _t2 = t2; +LL | ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:50:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | println!("{}", t1.1); -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:62:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | println!("{}", t1.1); -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:68:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:83:13 | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | let _t1 = t1.0; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:86:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _s = s.0; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:104:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | let _s = s.0; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:101:13 - | -LL | let c = move || { - | _____________^ -LL | | -LL | | -LL | | println!("{} {}", t1.1, t.1); -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:122:13 | +LL | let c = move || { + | ^^^^^^^ +... +LL | println!("{} {}", t1.1, t.1); + | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + | | + | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` +... +LL | } + | - + | | + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `t1`, `t` to be fully captured | LL | let c = move || { let _ = (&t1, &t); LL | LL | +LL | LL | println!("{} {}", t1.1, t.1); -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop.rs:116:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:142:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | }; - | +LL | + ... error: aborting due to 7 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed index e89cc2c8fb..4626c04e9b 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed @@ -1,8 +1,7 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here - #![feature(rustc_attrs)] #![allow(unused)] @@ -36,13 +35,16 @@ fn significant_drop_needs_migration() { let t = (SigDrop {}, SigDrop {}); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Even if a type implements an insignificant drop, if it's // elements have a significant drop then the overall type is @@ -53,13 +55,16 @@ fn generic_struct_with_significant_drop_needs_migration() { // move is used to force i32 to be copied instead of being a ref let c = move || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure fn main() { significant_drop_needs_migration(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs index e16cd9d52b..ebcf1551ba 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs @@ -1,8 +1,7 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here - #![feature(rustc_attrs)] #![allow(unused)] @@ -36,13 +35,16 @@ fn significant_drop_needs_migration() { let t = (SigDrop {}, SigDrop {}); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Even if a type implements an insignificant drop, if it's // elements have a significant drop then the overall type is @@ -53,13 +55,16 @@ fn generic_struct_with_significant_drop_needs_migration() { // move is used to force i32 to be copied instead of being a ref let c = move || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure fn main() { significant_drop_needs_migration(); 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 2b141656be..1e97ca34d1 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 @@ -1,47 +1,53 @@ -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop_attr_migrations.rs:38:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop_attr_migrations.rs:37:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/insignificant_drop_attr_migrations.rs:3:9 | -LL | #![deny(disjoint_capture_migration)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/insignificant_drop_attr_migrations.rs:55:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop_attr_migrations.rs:57:13 | -LL | let c = move || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.1; -LL | | }; - | |_____^ +LL | let c = move || { + | ^^^^^^^ +... +LL | let _t = t.1; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = move || { let _ = &t; LL | LL | +LL | LL | let _t = t.1; -LL | }; - | +LL | + ... error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs index a00377456a..a527bf42e5 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs @@ -1,6 +1,6 @@ // run-pass -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs index ee3138ea69..ff5d284614 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.rs @@ -1,10 +1,10 @@ // run-pass -#![warn(disjoint_capture_migration)] +#![warn(rust_2021_incompatible_closure_captures)] fn main() { if let a = "" { - //~^ WARNING: irrefutable `if let` pattern + //~^ WARNING: irrefutable `if let` pattern drop(|_: ()| drop(a)); } } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs b/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs new file mode 100644 index 0000000000..fce9cac627 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/issue-86753.rs @@ -0,0 +1,34 @@ +// edition:2018 +// check-pass + +#![warn(rust_2021_compatibility)] + +use std::future::Future; + +struct Runtime; + +impl Runtime { + pub fn block_on(&self, _future: F) -> F::Output { + unimplemented!() + } +} + +pub fn http(_func: F) +where + F: Fn() -> Fut, + Fut: Future, +{ + let rt = Runtime {}; + let srv = rt.block_on(async move { serve(move || async move { unimplemented!() }) }); + let _ = || rt.block_on(async { srv }); +} + +pub struct Server { + _marker: std::marker::PhantomData, +} + +pub fn serve(_new_service: S) -> Server { + unimplemented!() +} + +fn main() { } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed index 979c023fc5..f3c15a2e6b 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here // Test the two possible cases for automated migartion using rustfix @@ -17,22 +17,28 @@ impl Drop for Foo { fn closure_contains_block() { let t = (Foo(0), Foo(0)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn closure_doesnt_contain_block() { let t = (Foo(0), Foo(0)); let c = || { let _ = &t; t.0 }; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { closure_contains_block(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs index c2a700bd9c..50936d1530 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs @@ -1,5 +1,5 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here // Test the two possible cases for automated migartion using rustfix @@ -17,22 +17,28 @@ impl Drop for Foo { fn closure_contains_block() { let t = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn closure_doesnt_contain_block() { let t = (Foo(0), Foo(0)); let c = || t.0; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` + //~^ ERROR: drop order + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { closure_contains_block(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr index a968d3a093..f8f72d1580 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 @@ -1,34 +1,43 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/migrations_rustfix.rs:19:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/migrations_rustfix.rs:2:9 | -LL | #![deny(disjoint_capture_migration)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/migrations_rustfix.rs:30:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/migrations_rustfix.rs:33:13 | LL | let c = || t.0; - | ^^^^^^ - | + | ^^^--- + | | + | in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; t.0 }; 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 95463a6218..f24804018c 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 @@ -1,21 +1,29 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![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)] use std::panic; -fn foo_diverges() -> ! { panic!() } +fn foo_diverges() -> ! { + panic!() +} -fn assert_panics(f: F) where F: FnOnce() { +fn assert_panics(f: F) +where + F: FnOnce(), +{ let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { let _ = &f; - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0` }); if let Ok(..) = result { panic!("diverging function returned"); @@ -23,7 +31,8 @@ fn assert_panics(f: F) where F: FnOnce() { } fn test_fn_ptr_panic(mut t: T) - where T: Fn() -> ! +where + T: Fn() -> !, { let as_fn = >::call; assert_panics(|| as_fn(&t, ())); 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 fae7fc87c0..6a6a51c513 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 @@ -1,21 +1,29 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![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)] use std::panic; -fn foo_diverges() -> ! { panic!() } +fn foo_diverges() -> ! { + panic!() +} -fn assert_panics(f: F) where F: FnOnce() { +fn assert_panics(f: F) +where + F: FnOnce(), +{ let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation affected for closure because of `capture_disjoint_fields` + //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0` }); if let Ok(..) = result { panic!("diverging function returned"); @@ -23,7 +31,8 @@ fn assert_panics(f: F) where F: FnOnce() { } fn test_fn_ptr_panic(mut t: T) - where T: Fn() -> ! +where + T: Fn() -> !, { let as_fn = >::call; assert_panics(|| as_fn(&t, ())); 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 bbc8eb9a9c..6ee0d0d252 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,27 +1,27 @@ -error: `UnwindSafe`, `RefUnwindSafe` trait implementation affected for closure because of `capture_disjoint_fields` - --> $DIR/mir_calls_to_shims.rs:15:38 +error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure + --> $DIR/mir_calls_to_shims.rs:20:38 | -LL | let result = panic::catch_unwind(move || { - | ______________________________________^ -LL | | -LL | | -LL | | f.0() -LL | | }); - | |_____^ +LL | let result = panic::catch_unwind(move || { + | ^^^^^^^ in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` +... +LL | f.0() + | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0` | note: the lint level is defined here --> $DIR/mir_calls_to_shims.rs:3:9 | -LL | #![deny(disjoint_capture_migration)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see help: add a dummy let to cause `f` to be fully captured | LL | let result = panic::catch_unwind(move || { let _ = &f; LL | LL | +LL | +LL | LL | f.0() -LL | }); - | + ... error: aborting due to previous error diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed new file mode 100644 index 0000000000..98f578abc4 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed @@ -0,0 +1,138 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +struct S(String); + +#[derive(Clone)] +struct T(i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(String::from("Hello World")), T(0)) + } +} + +fn test_multi_issues() { + let f1 = U(S(String::from("foo")), T(0)); + let f2 = U(S(String::from("bar")), T(0)); + let c = || { let _ = (&f1, &f2); + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f2.1; + //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure + +fn test_capturing_all_disjoint_fields_individually() { + let f1 = U(S(String::from("foo")), T(0)); + let c = || { let _ = &f1; + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.1; + }; + + let c_clone = c.clone(); + + c_clone(); +} + +struct U1(S, T, S); + +impl Clone for U1 { + fn clone(&self) -> Self { + U1(S(String::from("foo")), T(0), S(String::from("bar"))) + } +} + +fn test_capturing_several_disjoint_fields_individually_1() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { let _ = &f1; + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.2; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2` + }; + + let c_clone = c.clone(); + + c_clone(); +} + +fn test_capturing_several_disjoint_fields_individually_2() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { let _ = &f1; + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_1 = f1.1; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure + +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_multi_traits_issues() { + let mut f1 = 10; + let f1 = CustomInt(&mut f1 as *mut i32); + let fptr1 = SyncPointer(f1); + + let mut f2 = 10; + let fptr2 = SendPointer(&mut f2 as *mut i32); + thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + *fptr1.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0` + *fptr2.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0` + } }); +} + +fn main() { + test_multi_issues(); + test_capturing_all_disjoint_fields_individually(); + test_capturing_several_disjoint_fields_individually_1(); + test_capturing_several_disjoint_fields_individually_2(); + test_multi_traits_issues(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs new file mode 100644 index 0000000000..1577b91c96 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs @@ -0,0 +1,138 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +struct S(String); + +#[derive(Clone)] +struct T(i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(String::from("Hello World")), T(0)) + } +} + +fn test_multi_issues() { + let f1 = U(S(String::from("foo")), T(0)); + let f2 = U(S(String::from("bar")), T(0)); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f2.1; + //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure + +fn test_capturing_all_disjoint_fields_individually() { + let f1 = U(S(String::from("foo")), T(0)); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.1; + }; + + let c_clone = c.clone(); + + c_clone(); +} + +struct U1(S, T, S); + +impl Clone for U1 { + fn clone(&self) -> Self { + U1(S(String::from("foo")), T(0), S(String::from("bar"))) + } +} + +fn test_capturing_several_disjoint_fields_individually_1() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.2; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2` + }; + + let c_clone = c.clone(); + + c_clone(); +} + +fn test_capturing_several_disjoint_fields_individually_2() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_1 = f1.1; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure + +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_multi_traits_issues() { + let mut f1 = 10; + let f1 = CustomInt(&mut f1 as *mut i32); + let fptr1 = SyncPointer(f1); + + let mut f2 = 10; + let fptr2 = SendPointer(&mut f2 as *mut i32); + thread::spawn(move || unsafe { + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + *fptr1.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0` + *fptr2.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0` + }); +} + +fn main() { + test_multi_issues(); + test_capturing_all_disjoint_fields_individually(); + test_capturing_several_disjoint_fields_individually_1(); + test_capturing_several_disjoint_fields_individually_2(); + test_multi_traits_issues(); +} 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 new file mode 100644 index 0000000000..8a42683c1d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -0,0 +1,134 @@ +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order + --> $DIR/multi_diagnostics.rs:23:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` +... +LL | let _f_1 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` +LL | +LL | let _f_2 = f2.1; + | ---- in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1` +... +LL | } + | - in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure + | +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 +help: add a dummy let to cause `f1`, `f2` to be fully captured + | +LL | let c = || { let _ = (&f1, &f2); +LL | +LL | +LL | +LL | +LL | let _f_1 = f1.0; + ... + +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure + --> $DIR/multi_diagnostics.rs:42:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` +... +LL | let _f_1 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + | + = note: for more information, see +help: add a dummy let to cause `f1` to be fully captured + | +LL | let c = || { let _ = &f1; +LL | +LL | +LL | +LL | +LL | let _f_1 = f1.0; + ... + +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure + --> $DIR/multi_diagnostics.rs:67:13 + | +LL | let c = || { + | ^^ + | | + | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone` +... +LL | let _f_0 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` +LL | +LL | let _f_2 = f1.2; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2` + | + = note: for more information, see +help: add a dummy let to cause `f1` to be fully captured + | +LL | let c = || { let _ = &f1; +LL | +LL | +LL | +LL | +LL | + ... + +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order + --> $DIR/multi_diagnostics.rs:86:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` +... +LL | let _f_0 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` +LL | +LL | let _f_1 = f1.1; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1` +... +LL | } + | - + | | + | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure + | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure + | + = note: for more information, see +help: add a dummy let to cause `f1` to be fully captured + | +LL | let c = || { let _ = &f1; +LL | +LL | +LL | +LL | +LL | let _f_0 = f1.0; + ... + +error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure + --> $DIR/multi_diagnostics.rs:119:19 + | +LL | thread::spawn(move || unsafe { + | ^^^^^^^^^^^^^^ + | | + | in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` + | in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send` +... +LL | *fptr1.0.0 = 20; + | ---------- in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0` +LL | +LL | *fptr2.0 = 20; + | -------- in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0` + | + = note: for more information, see +help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + | +LL | thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { +LL | +LL | +LL | +LL | +LL | + ... + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/no_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/no_migrations.rs index 420d66fba5..8b75e226ab 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/no_migrations.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/no_migrations.rs @@ -2,8 +2,7 @@ // Set of test cases that don't need migrations -#![deny(disjoint_capture_migration)] - +#![deny(rust_2021_incompatible_closure_captures)] // Copy types as copied by the closure instead of being moved into the closure // Therefore their drop order isn't tied to the closure and won't be requiring any @@ -53,7 +52,6 @@ fn test4_insignificant_drop_non_drop_aggregate() { c(); } - struct Foo(i32); impl Drop for Foo { fn drop(&mut self) { @@ -80,5 +78,4 @@ fn main() { test3_only_copy_types_move_closure(); test4_insignificant_drop_non_drop_aggregate(); test5_significant_drop_non_drop_aggregate(); - } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/old_name.rs b/src/test/ui/closures/2229_closure_analysis/migrations/old_name.rs new file mode 100644 index 0000000000..16e3cca7b7 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/old_name.rs @@ -0,0 +1,9 @@ +// check-pass + +// Ensure that the old name for `rust_2021_incompatible_closure_captures` is still +// accepted by the compiler + +#![allow(disjoint_capture_migration)] +//~^ WARN lint `disjoint_capture_migration` has been renamed + +fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/old_name.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/old_name.stderr new file mode 100644 index 0000000000..47cb689fa0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/old_name.stderr @@ -0,0 +1,10 @@ +warning: lint `disjoint_capture_migration` has been renamed to `rust_2021_incompatible_closure_captures` + --> $DIR/old_name.rs:6:10 + | +LL | #![allow(disjoint_capture_migration)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rust_2021_incompatible_closure_captures` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed index 5c93fce925..226172fb93 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed @@ -1,6 +1,7 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here #[derive(Debug)] struct Foo(i32); @@ -17,19 +18,21 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() { let t = ConstainsDropField(Foo(10), Foo(20)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t = &t.1; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure struct S; impl Drop for S { - fn drop(&mut self) { - } + fn drop(&mut self) {} } struct T(S, S); @@ -40,15 +43,23 @@ fn test_precise_analysis_long_path_missing() { let u = U(T(S, S), T(S, S)); let c = || { let _ = &u; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `u` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `u` to be fully captured let _x = u.0.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0` let _x = u.0.1; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1` let _x = u.1.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0` }; c(); } +//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure + fn main() { test_precise_analysis_drop_paths_not_captured_by_move(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs index fb4af00aa0..7035abe6de 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs @@ -1,6 +1,7 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here #[derive(Debug)] struct Foo(i32); @@ -17,19 +18,21 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() { let t = ConstainsDropField(Foo(10), Foo(20)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t = &t.1; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure struct S; impl Drop for S { - fn drop(&mut self) { - } + fn drop(&mut self) {} } struct T(S, S); @@ -40,15 +43,23 @@ fn test_precise_analysis_long_path_missing() { let u = U(T(S, S), T(S, S)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `u` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `u` to be fully captured let _x = u.0.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0` let _x = u.0.1; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1` let _x = u.1.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0` }; c(); } +//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure + fn main() { test_precise_analysis_drop_paths_not_captured_by_move(); 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 0cd191e2c9..5bf73ccc55 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr @@ -1,51 +1,62 @@ -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/precise.rs:19:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/precise.rs:20:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t = &t.1; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/precise.rs:3:9 | -LL | #![deny(disjoint_capture_migration)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | let _t = &t.1; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/precise.rs:42:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _x = u.0.0; -LL | | let _x = u.0.1; -LL | | let _x = u.1.0; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/precise.rs:45:13 | +LL | let c = || { + | ^^ +... +LL | let _x = u.0.0; + | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0` +LL | +LL | let _x = u.0.1; + | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1` +LL | +LL | let _x = u.1.0; + | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0` +... +LL | } + | - + | | + | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure + | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure + | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `u` to be fully captured | LL | let c = || { let _ = &u; LL | LL | +LL | LL | let _x = u.0.0; -LL | let _x = u.0.1; -LL | let _x = u.1.0; +LL | ... error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs index e3a7220bf0..587d71c40f 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs @@ -1,6 +1,6 @@ // run-pass -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] #[derive(Debug)] struct Foo(i32); @@ -73,8 +73,7 @@ fn test_precise_analysis_parent_captured_2() { struct S; impl Drop for S { - fn drop(&mut self) { - } + fn drop(&mut self) {} } struct T(S, S); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed index 1fa0fb3db2..236fdb9e26 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here // Test cases for types that implement a significant drop (user defined) @@ -23,15 +23,22 @@ fn test1_all_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { let _ = (&t, &t1, &t2); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -41,15 +48,20 @@ fn test2_only_precise_paths_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { let _ = (&t, &t1); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -57,14 +69,17 @@ fn test3_only_by_value_need_migration() { let t = (Foo(0), Foo(0)); let t1 = (Foo(0), Foo(0)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{:?}", t1.1); }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // The root variable might not implement drop themselves but some path starting // at the root variable might implement Drop. @@ -74,13 +89,16 @@ fn test4_type_contains_drop_need_migration() { let t = ConstainsDropField(Foo(0), Foo(0)); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -89,26 +107,32 @@ fn test5_drop_non_drop_aggregate_need_migration() { let t = (Foo(0), Foo(0), 0i32); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Significant and Insignificant Drop aggregates. fn test6_significant_insignificant_drop_aggregate_need_migration() { let t = (Foo(0), String::new()); let c = || { let _ = &t; - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -117,13 +141,57 @@ fn test7_move_closures_non_copy_types_might_need_migration() { let t1 = (Foo(0), Foo(0), Foo(0)); let c = move || { let _ = (&t1, &t); - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{:?} {:?}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + + +fn test8_drop_order_and_blocks() { + { + let tuple = + (String::from("foo"), String::from("bar")); + { + let c = || { let _ = &tuple; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + } + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + } +} + +fn test9_drop_order_and_nested_closures() { + let tuple = + (String::from("foo"), String::from("bar")); + let b = || { + let c = || { let _ = &tuple; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + }; + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + + b(); +} fn main() { test1_all_need_migration(); @@ -133,4 +201,6 @@ fn main() { test5_drop_non_drop_aggregate_need_migration(); test6_significant_insignificant_drop_aggregate_need_migration(); test7_move_closures_non_copy_types_might_need_migration(); + test8_drop_order_and_blocks(); + test9_drop_order_and_nested_closures(); } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs index 1f0efbe1eb..a57f7aa565 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs @@ -1,5 +1,5 @@ // run-rustfix -#![deny(disjoint_capture_migration)] +#![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here // Test cases for types that implement a significant drop (user defined) @@ -23,15 +23,22 @@ fn test1_all_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -41,15 +48,20 @@ fn test2_only_precise_paths_need_migration() { let t2 = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -57,14 +69,17 @@ fn test3_only_by_value_need_migration() { let t = (Foo(0), Foo(0)); let t1 = (Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{:?}", t1.1); }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // The root variable might not implement drop themselves but some path starting // at the root variable might implement Drop. @@ -74,13 +89,16 @@ fn test4_type_contains_drop_need_migration() { let t = ConstainsDropField(Foo(0), Foo(0)); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -89,26 +107,32 @@ fn test5_drop_non_drop_aggregate_need_migration() { let t = (Foo(0), Foo(0), 0i32); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Significant and Insignificant Drop aggregates. fn test6_significant_insignificant_drop_aggregate_need_migration() { let t = (Foo(0), String::new()); let c = || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -117,13 +141,57 @@ fn test7_move_closures_non_copy_types_might_need_migration() { let t1 = (Foo(0), Foo(0), Foo(0)); let c = move || { - //~^ ERROR: drop order affected for closure because of `capture_disjoint_fields` - //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{:?} {:?}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + + +fn test8_drop_order_and_blocks() { + { + let tuple = + (String::from("foo"), String::from("bar")); + { + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + } + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + } +} + +fn test9_drop_order_and_nested_closures() { + let tuple = + (String::from("foo"), String::from("bar")); + let b = || { + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + }; + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + + b(); +} fn main() { test1_all_need_migration(); @@ -133,4 +201,6 @@ fn main() { test5_drop_non_drop_aggregate_need_migration(); test6_significant_insignificant_drop_aggregate_need_migration(); test7_move_closures_non_copy_types_might_need_migration(); + test8_drop_order_and_blocks(); + test9_drop_order_and_nested_closures(); } 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 91e75ffb81..b2b9ae8fd1 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr @@ -1,155 +1,235 @@ -error: drop order affected for closure because of `capture_disjoint_fields` +error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/significant_drop.rs:25:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; -LL | | let _t2 = t2.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +LL | +LL | let _t2 = t2.0; + | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure + | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/significant_drop.rs:2:9 | -LL | #![deny(disjoint_capture_migration)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured | LL | let c = || { let _ = (&t, &t1, &t2); LL | LL | +LL | LL | let _t = t.0; -LL | let _t1 = t1.0; -LL | let _t2 = t2.0; +LL | ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:43:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; -LL | | let _t2 = t2; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:50:13 | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `t`, `t1` to be fully captured | LL | let c = || { let _ = (&t, &t1); LL | LL | +LL | LL | let _t = t.0; -LL | let _t1 = t1.0; -LL | let _t2 = t2; +LL | ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:59:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | println!("{:?}", t1.1); -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:71:13 | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | println!("{:?}", t1.1); -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:76:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:91:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:91:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:109:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:104:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:125:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.1; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.1; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure | + = note: for more information, see help: add a dummy let to cause `t` to be fully captured | LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.1; -LL | }; - | +LL | + ... -error: drop order affected for closure because of `capture_disjoint_fields` - --> $DIR/significant_drop.rs:119:13 - | -LL | let c = move || { - | _____________^ -LL | | -LL | | -LL | | println!("{:?} {:?}", t1.1, t.1); -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:143:13 | +LL | let c = move || { + | ^^^^^^^ +... +LL | println!("{:?} {:?}", t1.1, t.1); + | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + | | + | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` +... +LL | } + | - + | | + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure + | + = note: for more information, see help: add a dummy let to cause `t1`, `t` to be fully captured | LL | let c = move || { let _ = (&t1, &t); LL | LL | +LL | LL | println!("{:?} {:?}", t1.1, t.1); +LL | + ... + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:163:21 + | +LL | let c = || { + | ^^ +... +LL | tuple.0; + | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` +... +LL | } + | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + | + = note: for more information, see +help: add a dummy let to cause `tuple` to be fully captured + | +LL | let c = || { let _ = &tuple; +LL | +LL | +LL | +LL | tuple.0; +LL | + ... + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:181:17 + | +LL | let c = || { + | ^^ +... +LL | tuple.0; + | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` +... LL | }; + | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + | + = note: for more information, see +help: add a dummy let to cause `tuple` to be fully captured | +LL | let c = || { let _ = &tuple; +LL | +LL | +LL | +LL | tuple.0; +LL | + ... -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs b/src/test/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs new file mode 100644 index 0000000000..39cf82053f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs @@ -0,0 +1,13 @@ +//run-pass +#![deny(rust_2021_incompatible_closure_captures)] +#![allow(unused_must_use)] + +fn filter_try_fold( + predicate: &mut impl FnMut() -> bool, +) -> impl FnMut() -> bool + '_ { + move || predicate() +} + +fn main() { + filter_try_fold(&mut || true); +} diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/move_closure.rs index 1c574da5f4..0e7abf64fa 100644 --- a/src/test/ui/closures/2229_closure_analysis/move_closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/move_closure.rs @@ -1,9 +1,7 @@ +// edition:2021 + // Test that move closures drop derefs with `capture_disjoint_fields` enabled. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] fn simple_move_closure() { @@ -18,7 +16,7 @@ fn simple_move_closure() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: t.0.0 = "new S".into(); - //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> ByValue + //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue }; c(); @@ -81,7 +79,7 @@ fn struct_contains_ref_to_another_struct_2() { //~| ERROR: Min Capture analysis includes: let _t = t.0.0; //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(0, 0),Deref] -> ImmBorrow }; c(); @@ -102,8 +100,7 @@ fn struct_contains_ref_to_another_struct_3() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let _t = t.0.0; - //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - //~| NOTE: Capturing t[(0, 0)] -> ByValue + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue //~| NOTE: Min Capture t[(0, 0)] -> ByValue }; @@ -114,8 +111,9 @@ fn struct_contains_ref_to_another_struct_3() { fn truncate_box_derefs() { struct S(i32); - let b = Box::new(S(10)); + // Content within the box is moved within the closure + let b = Box::new(S(10)); let c = #[rustc_capture_analysis] //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 @@ -123,12 +121,93 @@ fn truncate_box_derefs() { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: let _t = b.0; - //~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue - //~| NOTE: Capturing b[] -> ByValue + //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow //~| NOTE: Min Capture b[] -> ByValue }; c(); + + // Content within the box is used by a shared ref and the box is the root variable + let b = Box::new(S(10)); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", b.0); + //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture b[] -> ByValue + }; + + c(); + + // Content within the box is used by a shared ref and the box is not the root variable + let b = Box::new(S(10)); + let t = (0, b); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", t.1.0); + //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(1, 0)] -> ByValue + }; +} + +struct Foo { x: i32 } + +// Ensure that even in move closures, if the data is not owned by the root variable +// then we don't truncate the derefs or a ByValue capture, rather do a reborrow +fn box_mut_1() { + let mut foo = Foo { x: 0 } ; + + let p_foo = &mut foo; + let box_p_foo = Box::new(p_foo); + + let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| First Pass analysis includes: + //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow + //~| Min Capture analysis includes: + //~| NOTE: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow +} + +// Ensure that even in move closures, if the data is not owned by the root variable +// then we don't truncate the derefs or a ByValue capture, rather do a reborrow +fn box_mut_2() { + let foo = Foo { x: 0 } ; + + let mut box_foo = Box::new(foo); + let p_foo = &mut box_foo; + + let c = #[rustc_capture_analysis] move || p_foo.x += 10; + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| First Pass analysis includes: + //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow + //~| Min Capture analysis includes: + //~| NOTE: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow +} + +// Test that move closures can take ownership of Copy type +fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { + let x = 10; + + let c = #[rustc_capture_analysis] move || x; + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| First Pass analysis includes: + //~| NOTE: Capturing x[] -> ImmBorrow + //~| Min Capture analysis includes: + //~| NOTE: Min Capture x[] -> ByValue + + c } fn main() { @@ -138,4 +217,6 @@ fn main() { struct_contains_ref_to_another_struct_2(); struct_contains_ref_to_another_struct_3(); truncate_box_derefs(); + box_mut_2(); + box_mut_1(); } diff --git a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr index b91ef4dd85..82ed99f944 100644 --- a/src/test/ui/closures/2229_closure_analysis/move_closure.stderr +++ b/src/test/ui/closures/2229_closure_analysis/move_closure.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:14:17 + --> $DIR/move_closure.rs:12:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:32:17 + --> $DIR/move_closure.rs:30:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:53:17 + --> $DIR/move_closure.rs:51:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:76:17 + --> $DIR/move_closure.rs:74:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:98:17 + --> $DIR/move_closure.rs:96:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:119:13 + --> $DIR/move_closure.rs:117:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,17 +52,77 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/move_closure.rs:3:12 +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:133:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:150:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:172:13 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:189:13 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:202:13 | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | let c = #[rustc_capture_analysis] move || x; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:202:39 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^^^^^^^^^ + | +note: Capturing x[] -> ImmBorrow + --> $DIR/move_closure.rs:202:47 | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information +LL | let c = #[rustc_capture_analysis] move || x; + | ^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:202:39 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^^^^^^^^^ + | +note: Min Capture x[] -> ByValue + --> $DIR/move_closure.rs:202:47 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:17:5 + --> $DIR/move_closure.rs:15:5 | LL | / move || { LL | | @@ -73,14 +133,14 @@ LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),(0, 0)] -> ByValue - --> $DIR/move_closure.rs:20:9 +note: Capturing t[(0, 0),(0, 0)] -> MutBorrow + --> $DIR/move_closure.rs:18:9 | LL | t.0.0 = "new S".into(); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:17:5 + --> $DIR/move_closure.rs:15:5 | LL | / move || { LL | | @@ -92,13 +152,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0),(0, 0)] -> ByValue - --> $DIR/move_closure.rs:20:9 + --> $DIR/move_closure.rs:18:9 | LL | t.0.0 = "new S".into(); | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:35:5 + --> $DIR/move_closure.rs:33:5 | LL | / move || { LL | | @@ -110,13 +170,13 @@ LL | | }; | |_____^ | note: Capturing ref_s[Deref] -> UniqueImmBorrow - --> $DIR/move_closure.rs:38:9 + --> $DIR/move_closure.rs:36:9 | LL | *ref_s += 10; | ^^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:35:5 + --> $DIR/move_closure.rs:33:5 | LL | / move || { LL | | @@ -128,13 +188,13 @@ LL | | }; | |_____^ | note: Min Capture ref_s[Deref] -> UniqueImmBorrow - --> $DIR/move_closure.rs:38:9 + --> $DIR/move_closure.rs:36:9 | LL | *ref_s += 10; | ^^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:56:5 + --> $DIR/move_closure.rs:54:5 | LL | / move || { LL | | @@ -146,13 +206,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow - --> $DIR/move_closure.rs:59:9 + --> $DIR/move_closure.rs:57:9 | LL | t.0.0 = "new s".into(); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:56:5 + --> $DIR/move_closure.rs:54:5 | LL | / move || { LL | | @@ -164,13 +224,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0),Deref,(0, 0)] -> UniqueImmBorrow - --> $DIR/move_closure.rs:59:9 + --> $DIR/move_closure.rs:57:9 | LL | t.0.0 = "new s".into(); | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:79:5 + --> $DIR/move_closure.rs:77:5 | LL | / move || { LL | | @@ -182,13 +242,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/move_closure.rs:82:18 + --> $DIR/move_closure.rs:80:18 | LL | let _t = t.0.0; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:79:5 + --> $DIR/move_closure.rs:77:5 | LL | / move || { LL | | @@ -199,94 +259,204 @@ LL | | LL | | }; | |_____^ | -note: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/move_closure.rs:82:18 +note: Min Capture t[(0, 0),Deref] -> ImmBorrow + --> $DIR/move_closure.rs:80:18 | LL | let _t = t.0.0; | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:101:5 + --> $DIR/move_closure.rs:99:5 | LL | / move || { LL | | LL | | LL | | let _t = t.0.0; -... | +LL | | LL | | LL | | }; | |_____^ | -note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/move_closure.rs:104:18 - | -LL | let _t = t.0.0; - | ^^^^^ -note: Capturing t[(0, 0)] -> ByValue - --> $DIR/move_closure.rs:104:18 +note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue + --> $DIR/move_closure.rs:102:18 | LL | let _t = t.0.0; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:101:5 + --> $DIR/move_closure.rs:99:5 | LL | / move || { LL | | LL | | LL | | let _t = t.0.0; -... | +LL | | LL | | LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/move_closure.rs:104:18 + --> $DIR/move_closure.rs:102:18 | LL | let _t = t.0.0; | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:122:5 + --> $DIR/move_closure.rs:120:5 | LL | / move || { LL | | LL | | LL | | let _t = b.0; -... | +LL | | LL | | LL | | }; | |_____^ | -note: Capturing b[Deref,(0, 0)] -> ByValue - --> $DIR/move_closure.rs:125:18 - | -LL | let _t = b.0; - | ^^^ -note: Capturing b[] -> ByValue - --> $DIR/move_closure.rs:125:18 +note: Capturing b[Deref,(0, 0)] -> ImmBorrow + --> $DIR/move_closure.rs:123:18 | LL | let _t = b.0; | ^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:122:5 + --> $DIR/move_closure.rs:120:5 | LL | / move || { LL | | LL | | LL | | let _t = b.0; -... | +LL | | LL | | LL | | }; | |_____^ | note: Min Capture b[] -> ByValue - --> $DIR/move_closure.rs:125:18 + --> $DIR/move_closure.rs:123:18 | LL | let _t = b.0; | ^^^ -error: aborting due to 18 previous errors; 1 warning emitted +error: First Pass analysis includes: + --> $DIR/move_closure.rs:136:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", b.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing b[Deref,(0, 0)] -> ImmBorrow + --> $DIR/move_closure.rs:139:24 + | +LL | println!("{}", b.0); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:136:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", b.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture b[] -> ByValue + --> $DIR/move_closure.rs:139:24 + | +LL | println!("{}", b.0); + | ^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:153:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", t.1.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow + --> $DIR/move_closure.rs:156:24 + | +LL | println!("{}", t.1.0); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:153:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", t.1.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(1, 0)] -> ByValue + --> $DIR/move_closure.rs:156:24 + | +LL | println!("{}", t.1.0); + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:172:39 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow + --> $DIR/move_closure.rs:172:47 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:172:39 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow + --> $DIR/move_closure.rs:172:47 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:189:39 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow + --> $DIR/move_closure.rs:189:47 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:189:39 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow + --> $DIR/move_closure.rs:189:47 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^ + +error: aborting due to 33 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs index 7d2d4c104d..a8a2acfa78 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr index 1c8db7952a..29ad1c5919 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/multilevel-path-1.rs:24:13 + --> $DIR/multilevel-path-1.rs:22:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-1.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/multilevel-path-1.rs:27:5 + --> $DIR/multilevel-path-1.rs:25:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing w[(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-1.rs:30:19 + --> $DIR/multilevel-path-1.rs:28:19 | LL | let wp = &w.p; | ^^^ error: Min Capture analysis includes: - --> $DIR/multilevel-path-1.rs:27:5 + --> $DIR/multilevel-path-1.rs:25:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture w[(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-1.rs:30:19 + --> $DIR/multilevel-path-1.rs:28:19 | LL | let wp = &w.p; | ^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs index 540e70138e..e21fe318cd 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] #![allow(unused)] diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr index 37287f6b3b..929cba1131 100644 --- a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr +++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/multilevel-path-2.rs:21:13 + --> $DIR/multilevel-path-2.rs:17:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-2.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/multilevel-path-2.rs:24:5 + --> $DIR/multilevel-path-2.rs:20:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing w[(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-2.rs:27:24 + --> $DIR/multilevel-path-2.rs:23:24 | LL | println!("{}", w.p.x); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/multilevel-path-2.rs:24:5 + --> $DIR/multilevel-path-2.rs:20:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow - --> $DIR/multilevel-path-2.rs:27:24 + --> $DIR/multilevel-path-2.rs:23:24 | LL | println!("{}", w.p.x); | ^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/nested-closure.rs b/src/test/ui/closures/2229_closure_analysis/nested-closure.rs index 88620550f2..f6775b3a3a 100644 --- a/src/test/ui/closures/2229_closure_analysis/nested-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/nested-closure.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr b/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr index 21147be3f1..013bc74e67 100644 --- a/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr +++ b/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/nested-closure.rs:23:18 + --> $DIR/nested-closure.rs:19:18 | LL | let mut c1 = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let mut c1 = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/nested-closure.rs:33:22 + --> $DIR/nested-closure.rs:29:22 | LL | let mut c2 = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,51 +16,42 @@ LL | let mut c2 = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/nested-closure.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/nested-closure.rs:36:9 + --> $DIR/nested-closure.rs:32:9 | LL | || p.y += incr; | ^^^^^^^^^^^^^^ | note: Capturing p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ note: Capturing incr[] -> ImmBorrow - --> $DIR/nested-closure.rs:36:19 + --> $DIR/nested-closure.rs:32:19 | LL | || p.y += incr; | ^^^^ error: Min Capture analysis includes: - --> $DIR/nested-closure.rs:36:9 + --> $DIR/nested-closure.rs:32:9 | LL | || p.y += incr; | ^^^^^^^^^^^^^^ | note: Min Capture p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ note: Min Capture incr[] -> ImmBorrow - --> $DIR/nested-closure.rs:36:19 + --> $DIR/nested-closure.rs:32:19 | LL | || p.y += incr; | ^^^^ error: First Pass analysis includes: - --> $DIR/nested-closure.rs:26:5 + --> $DIR/nested-closure.rs:22:5 | LL | / || { LL | | @@ -72,18 +63,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/nested-closure.rs:29:24 + --> $DIR/nested-closure.rs:25:24 | LL | println!("{}", p.x); | ^^^ note: Capturing p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ error: Min Capture analysis includes: - --> $DIR/nested-closure.rs:26:5 + --> $DIR/nested-closure.rs:22:5 | LL | / || { LL | | @@ -95,16 +86,16 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> ImmBorrow - --> $DIR/nested-closure.rs:29:24 + --> $DIR/nested-closure.rs:25:24 | LL | println!("{}", p.x); | ^^^ note: Min Capture p[(1, 0)] -> MutBorrow - --> $DIR/nested-closure.rs:36:12 + --> $DIR/nested-closure.rs:32:12 | LL | || p.y += incr; | ^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs new file mode 100644 index 0000000000..e7edc0bbce --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.rs @@ -0,0 +1,34 @@ +// edition:2021 + +#![feature(rustc_attrs)] +#![allow(unused)] +#![allow(dead_code)] + +struct Int(i32); +struct B<'a>(&'a i32); + +const I : Int = Int(0); +const REF_I : &'static Int = &I; + + +struct MyStruct<'a> { + a: &'static Int, + b: B<'a>, +} + +fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { + let c = #[rustc_capture_analysis] || drop(&m.a.0); + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow + c +} + +fn main() { + let t = 0; + let s = MyStruct { a: REF_I, b: B(&t) }; + let _ = foo(&s); +} diff --git a/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr new file mode 100644 index 0000000000..87d5d5bee0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case.stderr @@ -0,0 +1,36 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/edge_case.rs:20:13 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/edge_case.rs:20:39 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^^^^^^^^^^^ + | +note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow + --> $DIR/edge_case.rs:20:48 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/edge_case.rs:20:39 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^^^^^^^^^^^ + | +note: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow + --> $DIR/edge_case.rs:20:48 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs new file mode 100644 index 0000000000..033fd6f177 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs @@ -0,0 +1,27 @@ +// edition:2021 +// run-pass + +#![allow(unused)] +#![allow(dead_code)] + +struct Int(i32); +struct B<'a>(&'a i32); + +const I : Int = Int(0); +const REF_I : &'static Int = &I; + +struct MyStruct<'a> { + a: &'static Int, + b: B<'a>, +} + +fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { + let c = || drop(&m.a.0); + c +} + +fn main() { + let t = 0; + let s = MyStruct { a: REF_I, b: B(&t) }; + let _ = foo(&s); +} diff --git a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs index 16acd2f320..0c10319314 100644 --- a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs +++ b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr index 3c8d07ed9b..124b7bf6fe 100644 --- a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr +++ b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/path-with-array-access.rs:25:13 + --> $DIR/path-with-array-access.rs:23:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/path-with-array-access.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/path-with-array-access.rs:28:5 + --> $DIR/path-with-array-access.rs:26:5 | LL | / || { LL | | @@ -29,13 +20,13 @@ LL | | }; | |_____^ | note: Capturing pent[(0, 0)] -> ImmBorrow - --> $DIR/path-with-array-access.rs:31:24 + --> $DIR/path-with-array-access.rs:29:24 | LL | println!("{}", pent.points[5].x); | ^^^^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/path-with-array-access.rs:28:5 + --> $DIR/path-with-array-access.rs:26:5 | LL | / || { LL | | @@ -47,11 +38,11 @@ LL | | }; | |_____^ | note: Min Capture pent[(0, 0)] -> ImmBorrow - --> $DIR/path-with-array-access.rs:31:24 + --> $DIR/path-with-array-access.rs:29:24 | LL | println!("{}", pent.points[5].x); | ^^^^^^^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs index 609a11a578..0f288ffa95 100644 --- a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs +++ b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 + #![feature(never_type)] // Should fake read the discriminant and throw an error diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr index c225abb58b..45641ea3de 100644 --- a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr +++ b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr @@ -1,14 +1,5 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/pattern-matching-should-fail.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/pattern-matching-should-fail.rs:72:23 + --> $DIR/pattern-matching-should-fail.rs:70:23 | LL | let c1 = || match x { }; | ^ @@ -17,13 +8,13 @@ LL | let c1 = || match x { }; = note: the matched value is of type `u8` error[E0381]: use of possibly-uninitialized variable: `x` - --> $DIR/pattern-matching-should-fail.rs:10:23 + --> $DIR/pattern-matching-should-fail.rs:8:23 | LL | let c1 = || match x { }; | ^ use of possibly-uninitialized `x` error[E0381]: borrow of possibly-uninitialized variable: `x` - --> $DIR/pattern-matching-should-fail.rs:17:14 + --> $DIR/pattern-matching-should-fail.rs:15:14 | LL | let c2 = || match x { _ => () }; | ^^ - borrow occurs due to use in closure @@ -31,7 +22,7 @@ LL | let c2 = || match x { _ => () }; | use of possibly-uninitialized `x` error[E0381]: borrow of possibly-uninitialized variable: `variant` - --> $DIR/pattern-matching-should-fail.rs:29:13 + --> $DIR/pattern-matching-should-fail.rs:27:13 | LL | let c = || { | ^^ use of possibly-uninitialized `variant` @@ -40,7 +31,7 @@ LL | match variant { | ------- borrow occurs due to use in closure error[E0381]: borrow of possibly-uninitialized variable: `variant` - --> $DIR/pattern-matching-should-fail.rs:41:13 + --> $DIR/pattern-matching-should-fail.rs:39:13 | LL | let c = || { | ^^ use of possibly-uninitialized `variant` @@ -49,24 +40,24 @@ LL | match variant { | ------- borrow occurs due to use in closure error[E0381]: use of possibly-uninitialized variable: `g` - --> $DIR/pattern-matching-should-fail.rs:57:15 + --> $DIR/pattern-matching-should-fail.rs:55:15 | LL | match g { }; | ^ use of possibly-uninitialized `g` error[E0381]: use of possibly-uninitialized variable: `t` - --> $DIR/pattern-matching-should-fail.rs:60:19 + --> $DIR/pattern-matching-should-fail.rs:58:19 | LL | match t { }; | ^ use of possibly-uninitialized `t` error[E0381]: use of possibly-uninitialized variable: `x` - --> $DIR/pattern-matching-should-fail.rs:72:23 + --> $DIR/pattern-matching-should-fail.rs:70:23 | LL | let c1 = || match x { }; | ^ use of possibly-uninitialized `x` -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 8 previous errors Some errors have detailed explanations: E0004, E0381. For more information about an error, try `rustc --explain E0004`. diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs index 0a877dd366..56f5ac44db 100644 --- a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs +++ b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] // Should capture the discriminant since a variant of a multivariant enum is diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr index ad3e96a575..4608133339 100644 --- a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr +++ b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:12:14 + --> $DIR/patterns-capture-analysis.rs:10:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:33:14 + --> $DIR/patterns-capture-analysis.rs:31:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:54:14 + --> $DIR/patterns-capture-analysis.rs:52:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:70:14 + --> $DIR/patterns-capture-analysis.rs:68:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:92:14 + --> $DIR/patterns-capture-analysis.rs:90:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:116:14 + --> $DIR/patterns-capture-analysis.rs:114:14 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,17 +52,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/patterns-capture-analysis.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:16:5 + --> $DIR/patterns-capture-analysis.rs:14:5 | LL | / || { LL | | @@ -74,13 +65,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:19:15 + --> $DIR/patterns-capture-analysis.rs:17:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:16:5 + --> $DIR/patterns-capture-analysis.rs:14:5 | LL | / || { LL | | @@ -92,13 +83,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:19:15 + --> $DIR/patterns-capture-analysis.rs:17:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:36:5 + --> $DIR/patterns-capture-analysis.rs:34:5 | LL | / || { LL | | @@ -109,7 +100,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:57:5 + --> $DIR/patterns-capture-analysis.rs:55:5 | LL | / || { LL | | @@ -120,7 +111,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:73:5 + --> $DIR/patterns-capture-analysis.rs:71:5 | LL | / || { LL | | @@ -132,18 +123,18 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:76:15 + --> $DIR/patterns-capture-analysis.rs:74:15 | LL | match variant { | ^^^^^^^ note: Capturing variant[(0, 0)] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:76:15 + --> $DIR/patterns-capture-analysis.rs:74:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:73:5 + --> $DIR/patterns-capture-analysis.rs:71:5 | LL | / || { LL | | @@ -155,13 +146,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:76:15 + --> $DIR/patterns-capture-analysis.rs:74:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:95:5 + --> $DIR/patterns-capture-analysis.rs:93:5 | LL | / || { LL | | @@ -172,7 +163,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:119:5 + --> $DIR/patterns-capture-analysis.rs:117:5 | LL | / || { LL | | @@ -184,13 +175,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:122:15 + --> $DIR/patterns-capture-analysis.rs:120:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:119:5 + --> $DIR/patterns-capture-analysis.rs:117:5 | LL | / || { LL | | @@ -202,11 +193,11 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:122:15 + --> $DIR/patterns-capture-analysis.rs:120:15 | LL | match variant { | ^^^^^^^ -error: aborting due to 15 previous errors; 1 warning emitted +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/repr_packed.rs b/src/test/ui/closures/2229_closure_analysis/repr_packed.rs index 2b9ef2a76b..7d472ad020 100644 --- a/src/test/ui/closures/2229_closure_analysis/repr_packed.rs +++ b/src/test/ui/closures/2229_closure_analysis/repr_packed.rs @@ -1,7 +1,4 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 +// edition:2021 #![feature(rustc_attrs)] diff --git a/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr index 0517dd04b6..405f66210a 100644 --- a/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr +++ b/src/test/ui/closures/2229_closure_analysis/repr_packed.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:16:17 + --> $DIR/repr_packed.rs:13:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:47:17 + --> $DIR/repr_packed.rs:44:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let mut c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:81:13 + --> $DIR/repr_packed.rs:78:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,17 +25,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/repr_packed.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/repr_packed.rs:19:5 + --> $DIR/repr_packed.rs:16:5 | LL | / || { LL | | @@ -47,18 +38,18 @@ LL | | }; | |_____^ | note: Capturing foo[(0, 0)] -> ImmBorrow - --> $DIR/repr_packed.rs:22:24 + --> $DIR/repr_packed.rs:19:24 | LL | let z1: &u8 = &foo.x; | ^^^^^ note: Capturing foo[(1, 0)] -> MutBorrow - --> $DIR/repr_packed.rs:25:32 + --> $DIR/repr_packed.rs:22:32 | LL | let z2: &mut u8 = &mut foo.y; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:19:5 + --> $DIR/repr_packed.rs:16:5 | LL | / || { LL | | @@ -70,18 +61,18 @@ LL | | }; | |_____^ | note: Min Capture foo[(0, 0)] -> ImmBorrow - --> $DIR/repr_packed.rs:22:24 + --> $DIR/repr_packed.rs:19:24 | LL | let z1: &u8 = &foo.x; | ^^^^^ note: Min Capture foo[(1, 0)] -> MutBorrow - --> $DIR/repr_packed.rs:25:32 + --> $DIR/repr_packed.rs:22:32 | LL | let z2: &mut u8 = &mut foo.y; | ^^^^^ error: First Pass analysis includes: - --> $DIR/repr_packed.rs:50:5 + --> $DIR/repr_packed.rs:47:5 | LL | / || { LL | | @@ -93,13 +84,13 @@ LL | | }; | |_____^ | note: Capturing foo[] -> MutBorrow - --> $DIR/repr_packed.rs:54:33 + --> $DIR/repr_packed.rs:51:33 | LL | let z2: &mut u16 = &mut foo.y; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:50:5 + --> $DIR/repr_packed.rs:47:5 | LL | / || { LL | | @@ -111,13 +102,13 @@ LL | | }; | |_____^ | note: Min Capture foo[] -> MutBorrow - --> $DIR/repr_packed.rs:54:33 + --> $DIR/repr_packed.rs:51:33 | LL | let z2: &mut u16 = &mut foo.y; | ^^^^^ error: First Pass analysis includes: - --> $DIR/repr_packed.rs:84:5 + --> $DIR/repr_packed.rs:81:5 | LL | / || { LL | | @@ -129,18 +120,18 @@ LL | | }; | |_____^ | note: Capturing foo[] -> ImmBorrow - --> $DIR/repr_packed.rs:87:24 + --> $DIR/repr_packed.rs:84:24 | LL | println!("{}", foo.x); | ^^^^^ note: Capturing foo[(0, 0)] -> ByValue - --> $DIR/repr_packed.rs:91:18 + --> $DIR/repr_packed.rs:88:18 | LL | let _z = foo.x; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:84:5 + --> $DIR/repr_packed.rs:81:5 | LL | / || { LL | | @@ -152,7 +143,7 @@ LL | | }; | |_____^ | note: Min Capture foo[] -> ByValue - --> $DIR/repr_packed.rs:87:24 + --> $DIR/repr_packed.rs:84:24 | LL | println!("{}", foo.x); | ^^^^^ foo[] used here @@ -160,6 +151,6 @@ LL | println!("{}", foo.x); LL | let _z = foo.x; | ^^^^^ foo[] captured as ByValue here -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs index 3a66399d02..73aca288fa 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/box.rs @@ -1,13 +1,8 @@ +// edition:2021 // run-pass // Test precise capture when using boxes -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 - - struct MetaData { x: String, name: String } struct Data { m: MetaData } struct BoxedData(Box); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr deleted file mode 100644 index 9883c01b94..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/box.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/box.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs index 9a93e6cf1e..2c828aed52 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.rs @@ -1,11 +1,9 @@ +// edition:2021 // run-pass // Test that ByValue captures compile sucessefully especially when the captures are // derefenced within the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - #[derive(Debug, Default)] struct SomeLargeType; struct MuchLargerType([SomeLargeType; 32]); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr deleted file mode 100644 index 98715c6b94..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/by_value.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/by_value.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs index 2c359519b7..3cb1eb3295 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs @@ -1,13 +1,9 @@ +// edition:2021 // run-pass // Test that we can immutably borrow field of an instance of a structure from within a closure, // while having a mutable borrow to another field of the same instance outside the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 - struct Point { x: i32, y: i32, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr deleted file mode 100644 index 9b0dea770f..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-struct.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs index 2c6679feab..0f79b7ae7b 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs @@ -1,12 +1,9 @@ +// edition:2021 // run-pass // Test that we can mutate an element of a tuple from within a closure // while immutably borrowing another element of the same tuple outside the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr deleted file mode 100644 index 28d0915395..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-tuple-mut.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs index 52f5cef9f0..81f0328b9b 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs @@ -1,12 +1,9 @@ +// edition:2021 // run-pass // Test that we can immutably borrow an element of a tuple from within a closure, // while having a mutable borrow to another element of the same tuple outside the closure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr deleted file mode 100644 index 4fb37f85f8..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture-disjoint-field-tuple.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs index eaea0dbfb5..cea02fbe15 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete fn test1() { let foo : [Vec; 3] = ["String".into(), "String".into(), "String".into()]; diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr deleted file mode 100644 index 2c17a189af..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/capture_with_wildcard_match.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs index 3ad083a92d..5c278bff90 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs @@ -1,6 +1,5 @@ -//check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 +// check-pass #![warn(unused)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr index c4abf93412..40274c8831 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr @@ -1,30 +1,21 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/destructure-pattern-closure-within-closure.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - warning: unused variable: `t2` - --> $DIR/destructure-pattern-closure-within-closure.rs:14:21 + --> $DIR/destructure-pattern-closure-within-closure.rs:13:21 | LL | let (_, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t2` | note: the lint level is defined here - --> $DIR/destructure-pattern-closure-within-closure.rs:4:9 + --> $DIR/destructure-pattern-closure-within-closure.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` warning: unused variable: `g2` - --> $DIR/destructure-pattern-closure-within-closure.rs:11:17 + --> $DIR/destructure-pattern-closure-within-closure.rs:10:17 | LL | let (_, g2) = g; | ^^ help: if this is intentional, prefix it with an underscore: `_g2` -warning: 3 warnings emitted +warning: 2 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs index 65527648b2..07adbee03f 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs @@ -1,6 +1,5 @@ -//check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 +// check-pass #![warn(unused)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr index fcfe9ee95f..6523f2b34d 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr @@ -1,66 +1,57 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/destructure_patterns.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - warning: unused variable: `t1` - --> $DIR/destructure_patterns.rs:15:14 + --> $DIR/destructure_patterns.rs:14:14 | LL | let (t1, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t1` | note: the lint level is defined here - --> $DIR/destructure_patterns.rs:4:9 + --> $DIR/destructure_patterns.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` warning: unused variable: `t2` - --> $DIR/destructure_patterns.rs:15:18 + --> $DIR/destructure_patterns.rs:14:18 | LL | let (t1, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t2` warning: unused variable: `t1` - --> $DIR/destructure_patterns.rs:27:14 + --> $DIR/destructure_patterns.rs:26:14 | LL | let (t1, _) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t1` warning: unused variable: `t2` - --> $DIR/destructure_patterns.rs:38:17 + --> $DIR/destructure_patterns.rs:37:17 | LL | let (_, t2) = t; | ^^ help: if this is intentional, prefix it with an underscore: `_t2` warning: unused variable: `t` - --> $DIR/destructure_patterns.rs:46:9 + --> $DIR/destructure_patterns.rs:45:9 | LL | let t = (String::from("Hello"), String::from("World")); | ^ help: if this is intentional, prefix it with an underscore: `_t` warning: unused variable: `x` - --> $DIR/destructure_patterns.rs:92:21 + --> $DIR/destructure_patterns.rs:91:21 | LL | let Point { x, y } = p; | ^ help: try ignoring the field: `x: _` warning: unused variable: `x` - --> $DIR/destructure_patterns.rs:84:9 + --> $DIR/destructure_patterns.rs:83:9 | LL | let x = 0; | ^ help: if this is intentional, prefix it with an underscore: `_x` warning: unused variable: `tup` - --> $DIR/destructure_patterns.rs:86:9 + --> $DIR/destructure_patterns.rs:85:9 | LL | let tup = (1, 2); | ^^^ help: if this is intentional, prefix it with an underscore: `_tup` -warning: 9 warnings emitted +warning: 8 warnings emitted diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs index 3f8e197b78..88a9816a05 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs @@ -1,10 +1,6 @@ +// edition:2021 // run-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 - // Tests that if a closure uses indivual fields of the same object // then that case is handled properly. diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr deleted file mode 100644 index bba90f8917..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/disjoint-capture-in-same-closure.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs index dae50854d8..477fdd613f 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs @@ -1,6 +1,5 @@ -//check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +// edition:2021 +// check-pass #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr deleted file mode 100644 index 7f811875d1..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/drop_then_use_fake_reads.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs new file mode 100644 index 0000000000..20bbe1d89e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs @@ -0,0 +1,23 @@ +// edition:2021 +// run-pass + +// Test that edition 2021 enables disjoint capture by default. + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 10 }; + + let c = || { + println!("{}", p.x); + }; + + // `c` should only capture `p.x`, therefore mutating `p.y` is allowed. + let py = &mut p.y; + + c(); + *py = 20; +} diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs index 8c12593430..e19f5ff1ba 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs @@ -1,12 +1,8 @@ +// edition:2021 // run-pass // Test disjoint capture within an impl block -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 - struct Filter { div: i32, } diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr deleted file mode 100644 index 6930e18992..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/filter-on-struct-member.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs index e89cf4550c..1286613cb1 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs @@ -1,13 +1,9 @@ +// edition:2021 // run-pass // Test that functional record update/struct update syntax works inside // a closure when the feature `capture_disjoint_fields` is enabled. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 - #[derive(Clone)] struct S { a: String, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr deleted file mode 100644 index 7ed73abba8..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/fru_syntax.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/fru_syntax.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs index 9c086fe4bd..d2375aa69e 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![warn(unused)] #![feature(rustc_attrs)] #![feature(btree_drain_filter)] diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr deleted file mode 100644 index bc046ecad6..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/lit-pattern-matching-with-methods.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs index afaafbda01..e1b61e85ec 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs @@ -1,9 +1,9 @@ +// edition:2021 // run-pass // Test that move closures compile properly with `capture_disjoint_fields` enabled. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +#![allow(unused)] fn simple_ref() { let mut s = 10; @@ -94,6 +94,15 @@ fn data_moved_but_not_fn_once() { c(); } +// Test that move closures can take ownership of Copy type +fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { + let x = 10; + + let c = move || x; + + c +} + fn main() { simple_ref(); struct_contains_ref_to_another_struct(); @@ -102,4 +111,6 @@ fn main() { disjoint_via_ref(); data_moved_but_not_fn_once(); + + returned_closure_owns_copy_type_data(); } diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr deleted file mode 100644 index c1d8ba575d..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/move_closure.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs index 142c156bd5..b8e4640318 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs @@ -1,3 +1,4 @@ +// edition:2021 // run-pass // Test that closures can catpure paths that are more precise than just one level @@ -7,10 +8,6 @@ // while being able to mutate another path outside the closure, where the two paths are disjoint // after applying two projections on the root variable. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![allow(unused)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr deleted file mode 100644 index 94b877522f..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-1.rs:10:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs index d8f7d55d5a..11a324d8a3 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs @@ -1,9 +1,6 @@ +// edition:2021 // run-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![allow(unused)] // If the closures can handle such precison we should be able to read one path in the closure diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr deleted file mode 100644 index 100a0e167c..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-2.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs index fc3d48ec45..8fc0efb60b 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs @@ -1,9 +1,6 @@ +// edition:2021 // run-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![allow(unused)] // Test that when `capture_disjoint_fields` is enabled we can read a path diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr deleted file mode 100644 index cf5be6a00e..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/multilevel-path-3.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs index 315622443c..9f0c4d96aa 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs @@ -1,11 +1,9 @@ +// edition:2021 // run-pass // Test that we can mutate a place through a mut-borrow // that is captured by the closure -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - // Check that we can mutate when one deref is required fn mut_ref_1() { let mut x = String::new(); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr deleted file mode 100644 index 4b37a0b405..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/mut_ref.rs:6:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs index 2dba923647..bb784774b8 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs @@ -1,3 +1,4 @@ +// edition:2021 // run-pass // Test that we can mutate a place through a mut-borrow @@ -6,9 +7,6 @@ // More specifically we test that the if the mutable reference isn't root variable of a capture // but rather accessed while acessing the precise capture. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - fn mut_tuple() { let mut t = (10, 10); diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr deleted file mode 100644 index 418ab29098..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/mut_ref_struct_mem.rs:9:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs index 238580929e..a80b40bb46 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs @@ -1,12 +1,8 @@ +// edition:2021 // run-pass // Test whether if we can do precise capture when using nested clsoure. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 - struct Point { x: i32, y: i32, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr deleted file mode 100644 index 293aa82ce9..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/nested-closure.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/nested-closure.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs index d260a44892..045fe78040 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![warn(unused)] #![feature(rustc_attrs)] diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr deleted file mode 100644 index 3e4303a371..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/struct-pattern-matching-with-methods.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs index b3bee79254..f3f44433cc 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #[derive(Copy, Clone)] enum PointType { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr deleted file mode 100644 index ded0e37b0f..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/tuple-struct-pattern-matching-with-methods.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs index f6e9862b26..8e4f91c27e 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs @@ -1,10 +1,8 @@ +// edition:2021 // run-pass // Test that we can use raw ptrs when using `capture_disjoint_fields`. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete - #[derive(Debug)] struct S { s: String, diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr deleted file mode 100644 index c64c8b72e8..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/unsafe_ptr.rs:5:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs index 0e6da8f4f1..0206927cc5 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs @@ -1,6 +1,5 @@ +// edition:2021 //check-pass -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete #![feature(rustc_attrs)] fn main() { diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr b/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr deleted file mode 100644 index 7d16d77bf7..0000000000 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/use_of_mutable_borrow_and_fake_reads.rs:2:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs index a6b5e12d2e..563095d440 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs @@ -1,9 +1,5 @@ -// FIXME(arora-aman) add run-pass once 2229 is implemented +// edition:2021 -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 #![feature(rustc_attrs)] // Test to ensure that min analysis meets capture kind for all paths captured. diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr index cbbc879219..05d79797ab 100644 --- a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr +++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/simple-struct-min-capture.rs:27:17 + --> $DIR/simple-struct-min-capture.rs:23:17 | LL | let mut c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,17 +7,8 @@ LL | let mut c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/simple-struct-min-capture.rs:3:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/simple-struct-min-capture.rs:30:5 + --> $DIR/simple-struct-min-capture.rs:26:5 | LL | / || { LL | | @@ -29,18 +20,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> MutBorrow - --> $DIR/simple-struct-min-capture.rs:33:9 + --> $DIR/simple-struct-min-capture.rs:29:9 | LL | p.x += 10; | ^^^ note: Capturing p[] -> ImmBorrow - --> $DIR/simple-struct-min-capture.rs:36:26 + --> $DIR/simple-struct-min-capture.rs:32:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/simple-struct-min-capture.rs:30:5 + --> $DIR/simple-struct-min-capture.rs:26:5 | LL | / || { LL | | @@ -52,7 +43,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> MutBorrow - --> $DIR/simple-struct-min-capture.rs:33:9 + --> $DIR/simple-struct-min-capture.rs:29:9 | LL | p.x += 10; | ^^^ p[] captured as MutBorrow here @@ -60,6 +51,6 @@ LL | p.x += 10; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs index 79d3ecc2d2..eab9f9d08a 100644 --- a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs +++ b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.rs @@ -1,10 +1,9 @@ +// edition:2021 + // Test that we restrict precision of a capture when we access a raw ptr, // i.e. the capture doesn't deref the raw ptr. -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| `#[warn(incomplete_features)]` on by default -//~| see issue #53488 + #![feature(rustc_attrs)] #[derive(Debug)] diff --git a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr index 4508b2426e..e740a4d2d6 100644 --- a/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr +++ b/src/test/ui/closures/2229_closure_analysis/unsafe_ptr.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/unsafe_ptr.rs:26:13 + --> $DIR/unsafe_ptr.rs:25:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/unsafe_ptr.rs:46:13 + --> $DIR/unsafe_ptr.rs:45:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,17 +16,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/unsafe_ptr.rs:4:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/unsafe_ptr.rs:29:6 + --> $DIR/unsafe_ptr.rs:28:6 | LL | / || unsafe { LL | | @@ -38,13 +29,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:32:26 + --> $DIR/unsafe_ptr.rs:31:26 | LL | println!("{:?}", (*t.0).s); | ^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/unsafe_ptr.rs:29:6 + --> $DIR/unsafe_ptr.rs:28:6 | LL | / || unsafe { LL | | @@ -56,13 +47,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:32:26 + --> $DIR/unsafe_ptr.rs:31:26 | LL | println!("{:?}", (*t.0).s); | ^^^^^^^^ error: First Pass analysis includes: - --> $DIR/unsafe_ptr.rs:49:5 + --> $DIR/unsafe_ptr.rs:48:5 | LL | / || { LL | | @@ -74,13 +65,13 @@ LL | | }; | |_____^ | note: Capturing p[Deref,(0, 0)] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:52:31 + --> $DIR/unsafe_ptr.rs:51:31 | LL | let x = unsafe { &mut (*p).s }; | ^^^^^^ error: Min Capture analysis includes: - --> $DIR/unsafe_ptr.rs:49:5 + --> $DIR/unsafe_ptr.rs:48:5 | LL | / || { LL | | @@ -92,11 +83,11 @@ LL | | }; | |_____^ | note: Min Capture p[] -> ImmBorrow - --> $DIR/unsafe_ptr.rs:52:31 + --> $DIR/unsafe_ptr.rs:51:31 | LL | let x = unsafe { &mut (*p).s }; | ^^^^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs b/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs index 90b8033d07..7843c25166 100644 --- a/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs +++ b/src/test/ui/closures/2229_closure_analysis/wild_patterns.rs @@ -1,7 +1,5 @@ -#![feature(capture_disjoint_fields)] -//~^ WARNING: the feature `capture_disjoint_fields` is incomplete -//~| NOTE: `#[warn(incomplete_features)]` on by default -//~| NOTE: see issue #53488 +// edition:2021 + #![feature(rustc_attrs)] // Test to ensure that we can handle cases where diff --git a/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr b/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr index 36be8431be..c64378091e 100644 --- a/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr +++ b/src/test/ui/closures/2229_closure_analysis/wild_patterns.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:24:13 + --> $DIR/wild_patterns.rs:22:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:42:13 + --> $DIR/wild_patterns.rs:40:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | let c = #[rustc_capture_analysis] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:60:13 + --> $DIR/wild_patterns.rs:58:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,17 +25,8 @@ LL | let c = #[rustc_capture_analysis] = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wild_patterns.rs:1:12 - | -LL | #![feature(capture_disjoint_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #53488 for more information - error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:27:5 + --> $DIR/wild_patterns.rs:25:5 | LL | / || { LL | | @@ -47,13 +38,13 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ImmBorrow - --> $DIR/wild_patterns.rs:31:37 + --> $DIR/wild_patterns.rs:29:37 | LL | let Point { x: _x, y: _ } = p; | ^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:27:5 + --> $DIR/wild_patterns.rs:25:5 | LL | / || { LL | | @@ -65,13 +56,13 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> ImmBorrow - --> $DIR/wild_patterns.rs:31:37 + --> $DIR/wild_patterns.rs:29:37 | LL | let Point { x: _x, y: _ } = p; | ^ error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:45:5 + --> $DIR/wild_patterns.rs:43:5 | LL | / || { LL | | @@ -83,13 +74,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 + --> $DIR/wild_patterns.rs:47:23 | LL | let (_x, _) = t; | ^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:45:5 + --> $DIR/wild_patterns.rs:43:5 | LL | / || { LL | | @@ -101,13 +92,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 + --> $DIR/wild_patterns.rs:47:23 | LL | let (_x, _) = t; | ^ error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:63:5 + --> $DIR/wild_patterns.rs:61:5 | LL | / || { LL | | @@ -119,13 +110,13 @@ LL | | }; | |_____^ | note: Capturing arr[Index] -> ByValue - --> $DIR/wild_patterns.rs:67:23 + --> $DIR/wild_patterns.rs:65:23 | LL | let [_x, _] = arr; | ^^^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:63:5 + --> $DIR/wild_patterns.rs:61:5 | LL | / || { LL | | @@ -137,11 +128,11 @@ LL | | }; | |_____^ | note: Min Capture arr[] -> ByValue - --> $DIR/wild_patterns.rs:67:23 + --> $DIR/wild_patterns.rs:65:23 | LL | let [_x, _] = arr; | ^^^ -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index 72ef5b3b96..ffe0bce6f0 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -5,7 +5,7 @@ LL | (&|_| ()) as &dyn for<'x> Fn(>::V); | ^^------^ | | | | | found signature of `fn(u16) -> _` - | expected signature of `fn(>::V) -> _` + | expected signature of `for<'x> fn(>::V) -> _` | = note: required for the cast to the object type `dyn for<'x> Fn(>::V)` diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs index b09ea06c8f..9e4521df8c 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs @@ -1,13 +1,21 @@ // build-pass // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -// only-thumbv8m.main-none-eabi -#![feature(abi_c_cmse_nonsecure_call)] -#![no_std] +// needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] +#![no_core] +#[lang="sized"] +pub trait Sized { } +#[lang="copy"] +pub trait Copy { } + +extern "rust-intrinsic" { + pub fn transmute(e: T) -> U; +} #[no_mangle] pub fn test(a: u32, b: u32, c: u32, d: u32) -> u32 { let non_secure_function = unsafe { - core::mem::transmute:: u32>( + transmute:: u32>( 0x10000004, ) }; diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs index cfdce4f4e9..9697146d5c 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs @@ -1,12 +1,22 @@ +// build-fail // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -// only-thumbv8m.main-none-eabi -#![feature(abi_c_cmse_nonsecure_call)] -#![no_std] +// needs-llvm-components: arm +// min-llvm-version: 11.0 +#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] +#![no_core] +#[lang="sized"] +pub trait Sized { } +#[lang="copy"] +pub trait Copy { } + +extern "rust-intrinsic" { + pub fn transmute(e: T) -> U; +} #[no_mangle] pub fn test(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { let non_secure_function = unsafe { - core::mem::transmute::< + transmute::< usize, extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32> ( diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs index 17117301fe..f32b370900 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs @@ -1,6 +1,8 @@ // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -// only-thumbv8m.main-none-eabi -#![feature(abi_c_cmse_nonsecure_call)] -#![no_std] +// needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)] +#![no_core] +#[lang="sized"] +trait Sized { } pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781] diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr index 78490bf8f6..3564ab4b6c 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr @@ -1,8 +1,8 @@ -error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers. - --> $DIR/wrong-abi-location-1.rs:6:1 +error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers. + --> $DIR/wrong-abi-location-1.rs:8:1 | -LL | pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "C-cmse-nonsecure-call" fn test() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs index 78f553d747..6f8bb24aa6 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs @@ -1,7 +1,9 @@ // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -// only-thumbv8m.main-none-eabi -#![feature(abi_c_cmse_nonsecure_call)] -#![no_std] +// needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)] +#![no_core] +#[lang="sized"] +trait Sized { } extern "C-cmse-nonsecure-call" { //~ ERROR [E0781] fn test(); diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr index 5c148e2cd6..76073f5488 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr @@ -1,8 +1,8 @@ error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers. - --> $DIR/wrong-abi-location-2.rs:6:1 + --> $DIR/wrong-abi-location-2.rs:8:1 | LL | / extern "C-cmse-nonsecure-call" { -LL | | fn test(); //~ ERROR [E0781] +LL | | fn test(); LL | | } | |_^ diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs new file mode 100644 index 0000000000..a839406cd0 --- /dev/null +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs @@ -0,0 +1,9 @@ +// Regression test for the ICE described in #83475. + +#![crate_type="lib"] + +#![feature(cmse_nonsecure_entry)] +#[cmse_nonsecure_entry] +//~^ ERROR: attribute should be applied to a function definition +struct XEmpty2; +//~^ NOTE: not a function definition diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr new file mode 100644 index 0000000000..426d82d8d0 --- /dev/null +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr @@ -0,0 +1,11 @@ +error: attribute should be applied to a function definition + --> $DIR/issue-83475.rs:6:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct XEmpty2; + | --------------- not a function definition + +error: aborting due to previous error + diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs index a723eb7347..8cde9ba58b 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs @@ -1,11 +1,15 @@ // build-pass // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -// only-thumbv8m.main-none-eabi -#![feature(cmse_nonsecure_entry)] -#![no_std] +// needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } +#[lang="copy"] +trait Copy { } #[no_mangle] #[cmse_nonsecure_entry] -pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 { - a + b + c + d +pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { + d } diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs index 553d3a8cb0..74321fdfdd 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs @@ -1,10 +1,16 @@ +// build-fail // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -// only-thumbv8m.main-none-eabi -#![feature(cmse_nonsecure_entry)] -#![no_std] +// needs-llvm-components: arm +// min-llvm-version: 11.0 +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } +#[lang="copy"] +trait Copy { } #[no_mangle] #[cmse_nonsecure_entry] -pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { //~ ERROR - a + b + c + d + e +pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 { + e } diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs index 611c8643dc..6320d29637 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs @@ -1,10 +1,13 @@ // compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -// only-thumbv8m.main-none-eabi -#![feature(cmse_nonsecure_entry)] -#![no_std] +// needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } #[no_mangle] #[cmse_nonsecure_entry] -pub fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 { //~ ERROR [E0776] - a + b + c + d +//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776] +pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { + d } diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr index d6967a11e6..36d76c9674 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr @@ -1,5 +1,5 @@ -error[E0776]: `#[cmse_nonsecure_entry]` functions require C ABI - --> $DIR/wrong-abi.rs:7:1 +error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI + --> $DIR/wrong-abi.rs:9:1 | LL | #[cmse_nonsecure_entry] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs b/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs new file mode 100644 index 0000000000..38dfca347c --- /dev/null +++ b/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs @@ -0,0 +1,35 @@ +// build-pass +// compile-flags: -Copt-level=0 + +// Regression test for #88043: LLVM crash when the RemoveZsts mir-opt pass is enabled. +// We should not see the error: +// `Basic Block in function '_ZN4main10take_until17h0067b8a660429bc9E' does not have terminator!` + +fn bump() -> Option { + unreachable!() +} + +fn take_until(terminate: impl Fn() -> bool) { + loop { + if terminate() { + return; + } else { + bump(); + } + } +} + +// CHECK-LABEL: @main +fn main() { + take_until(|| true); + f(None); +} + +fn f(_a: Option) -> Option { + loop { + g(); + () + } +} + +fn g() -> Option { None } diff --git a/src/test/ui/issues/issue-37655.rs b/src/test/ui/coercion/issue-37655.rs similarity index 100% rename from src/test/ui/issues/issue-37655.rs rename to src/test/ui/coercion/issue-37655.rs 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 7dabd97b94..cfcef9699f 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(fn(&'r ()))` +error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(for<'r> 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(fn(&'r ()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(for<'r> 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/test-cfg.rs b/src/test/ui/conditional-compilation/test-cfg.rs similarity index 100% rename from src/test/ui/test-cfg.rs rename to src/test/ui/conditional-compilation/test-cfg.rs diff --git a/src/test/ui/test-cfg.stderr b/src/test/ui/conditional-compilation/test-cfg.stderr similarity index 100% rename from src/test/ui/test-cfg.stderr rename to src/test/ui/conditional-compilation/test-cfg.stderr diff --git a/src/test/ui/conflicting-repr-hints.rs b/src/test/ui/conflicting-repr-hints.rs index 09dade2099..ed82b6a742 100644 --- a/src/test/ui/conflicting-repr-hints.rs +++ b/src/test/ui/conflicting-repr-hints.rs @@ -66,4 +66,15 @@ union Z { i: i32, } +#[repr(packed, align(0x100))] +pub struct S(u16); //~ ERROR type has conflicting packed and align representation hints + +#[repr(packed, align(0x100))] +pub union U { //~ ERROR type has conflicting packed and align representation hints + u: u16 +} + +static B: U = U { u: 0 }; +static A: S = S(0); + fn main() {} diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 0b78532c73..0f32fc0481 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -74,7 +74,21 @@ LL | | i: i32, LL | | } | |_^ -error: aborting due to 10 previous errors +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:70:1 + | +LL | pub struct S(u16); + | ^^^^^^^^^^^^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:73:1 + | +LL | / pub union U { +LL | | u: u16 +LL | | } + | |_^ + +error: aborting due to 12 previous errors Some errors have detailed explanations: E0566, E0587, E0634. For more information about an error, try `rustc --explain E0566`. diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs new file mode 100644 index 0000000000..744a1c4de4 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs @@ -0,0 +1,18 @@ +// check-pass +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] + +struct Foo([u8; N as usize]) +where + [(); N as usize]:; + +struct Bar([u8; (N + 2) as usize]) where [(); (N + 2) as usize]:; + +// unifying with subtrees +struct Evaluatable; +fn foo() where Evaluatable<{N as usize as u16 }>: { + let _ = Foo::([1; N as usize]); +} + + +fn main() {} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs new file mode 100644 index 0000000000..543774649e --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs @@ -0,0 +1,20 @@ +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] + +struct Evaluatable {} + +struct Foo([u8; N as usize]) +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:` +where + Evaluatable<{N as u128}>:; + +struct Foo2(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +struct Bar([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +fn main() {} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr new file mode 100644 index 0000000000..5ca04d25e5 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr @@ -0,0 +1,26 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:6:25 + | +LL | struct Foo([u8; N as usize]) + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N as usize]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:12:26 + | +LL | struct Foo2(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:16:25 + | +LL | struct Bar([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs new file mode 100644 index 0000000000..2ca06bd1cb --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs @@ -0,0 +1,47 @@ +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128; + +struct HasCastInTraitImpl; +impl Trait for HasCastInTraitImpl {} + +pub fn use_trait_impl() +where + [(); { N + 1}]:, + EvaluatableU128<{N as u128}>:, { + fn assert_impl() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + assert_impl::>(); + //~^ Error: mismatched types +} +pub fn use_trait_impl_2() +where + [(); { N + 1}]:, + EvaluatableU128<{N as _}>:, { + fn assert_impl() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + assert_impl::>(); + //~^ Error: mismatched types +} + +fn main() {} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr new file mode 100644 index 0000000000..c5237fc6f2 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr @@ -0,0 +1,139 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:17:5 + | +LL | fn assert_impl() {} + | ----- required by this bound in `use_trait_impl::assert_impl` +... +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:17:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected type `{ N as u128 }` + found type `{ O as u128 }` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:20:5 + | +LL | fn assert_impl() {} + | ----- required by this bound in `use_trait_impl::assert_impl` +... +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:20:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected type `{ N as _ }` + found type `{ O as u128 }` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:23:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128` + | + = note: expected type `12_u128` + found type `13_u128` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:25:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128` + | + = note: expected type `13_u128` + found type `14_u128` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:35:5 + | +LL | fn assert_impl() {} + | ----- required by this bound in `use_trait_impl_2::assert_impl` +... +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:35:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected type `{ N as u128 }` + found type `{ O as u128 }` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:38:5 + | +LL | fn assert_impl() {} + | ----- required by this bound in `use_trait_impl_2::assert_impl` +... +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:38:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected type `{ N as _ }` + found type `{ O as u128 }` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:41:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128` + | + = note: expected type `12_u128` + found type `13_u128` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:43:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128` + | + = note: expected type `13_u128` + found type `14_u128` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs new file mode 100644 index 0000000000..0bb4fcff4d --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs @@ -0,0 +1,29 @@ +// check-pass +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128; + +struct HasCastInTraitImpl; +impl Trait for HasCastInTraitImpl {} + +pub fn use_trait_impl() where EvaluatableU128<{N as u128}>:, { + fn assert_impl() {} + + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); +} +pub fn use_trait_impl_2() where EvaluatableU128<{N as _}>:, { + fn assert_impl() {} + + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); +} + + +fn main() {} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr index e0e6029252..319e6c2c03 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-ret.rs:17:15 + --> $DIR/object-safety-err-ret.rs:17:16 | LL | fn use_dyn(v: &dyn Foo) { - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` cannot be made into an object | = help: consider moving `test` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs b/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs new file mode 100644 index 0000000000..21f14f58ab --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs @@ -0,0 +1,6 @@ +// check-pass +#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)] +#![allow(incomplete_features)] +struct Foo; +struct Bar(Foo); +fn main() {} diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr deleted file mode 100644 index e0e2b6c69f..0000000000 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: constant expression depends on a generic parameter - --> $DIR/complex-generic-default-expr.rs:6:34 - | -LL | struct Foo; - | ^ - | - = note: this may fail depending on what value the parameter takes - -error: constant expression depends on a generic parameter - --> $DIR/complex-generic-default-expr.rs:10:21 - | -LL | struct Bar() }>(T); - | ^^^^^^^^^ - | - = note: this may fail depending on what value the parameter takes - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr index 58abd8db9f..44df2ac9f4 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -1,5 +1,5 @@ error: generic parameters may not be used in const operations - --> $DIR/complex-generic-default-expr.rs:6:47 + --> $DIR/complex-generic-default-expr.rs:7:47 | LL | struct Foo; | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs index a7b712f7b4..d355800797 100644 --- a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs +++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -1,14 +1,13 @@ // revisions: full min +//[full] check-pass #![cfg_attr(full, feature(const_generics))] #![feature(const_generics_defaults)] #![allow(incomplete_features)] struct Foo; -//[full]~^ ERROR constant expression depends on a generic parameter -//[min]~^^ ERROR generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations struct Bar() }>(T); -//[full]~^ ERROR constant expression depends on a generic parameter -//[min]~^^ ERROR generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs b/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs new file mode 100644 index 0000000000..9af8443925 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs @@ -0,0 +1,16 @@ +#![feature(const_generics_defaults)] + +struct Struct; +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +enum Enum { } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +union Union { not_empty: () } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +fn main() { + let _: Struct; + let _: Enum; + let _: Union; +} diff --git a/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr b/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr new file mode 100644 index 0000000000..5dfec2fcb7 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr @@ -0,0 +1,21 @@ +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:3:34 + | +LL | struct Struct; + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:6:30 + | +LL | enum Enum { } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:9:32 + | +LL | union Union { not_empty: () } + | ^^^^ `Self` in generic parameter default + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0735`. diff --git a/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr index d894fa90ba..09986f623f 100644 --- a/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr +++ b/src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr @@ -3,9 +3,12 @@ error[E0277]: the trait bound `[Adt; _]: Foo` is not satisfied | LL | <[Adt; std::mem::size_of::()] as Foo>::bar() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; _]` -... + | +note: required by `Foo::bar` + --> $DIR/dont-evaluate-array-len-on-err-1.rs:19:5 + | LL | fn bar() {} - | -------- required by `Foo::bar` + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/exhaustive-value.full.stderr b/src/test/ui/const-generics/exhaustive-value.full.stderr index e0e1423ba0..4e89e4a3b1 100644 --- a/src/test/ui/const-generics/exhaustive-value.full.stderr +++ b/src/test/ui/const-generics/exhaustive-value.full.stderr @@ -1,9 +1,6 @@ error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/exhaustive-value.rs:266:5 | -LL | fn test() {} - | --------- required by `Foo::test` -... LL | <() as Foo>::test() | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | @@ -13,6 +10,11 @@ LL | <() as Foo>::test() <() as Foo<101_u8>> <() as Foo<102_u8>> and 252 others +note: required by `Foo::test` + --> $DIR/exhaustive-value.rs:6:5 + | +LL | fn test() {} + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/exhaustive-value.min.stderr b/src/test/ui/const-generics/exhaustive-value.min.stderr index e0e1423ba0..4e89e4a3b1 100644 --- a/src/test/ui/const-generics/exhaustive-value.min.stderr +++ b/src/test/ui/const-generics/exhaustive-value.min.stderr @@ -1,9 +1,6 @@ error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/exhaustive-value.rs:266:5 | -LL | fn test() {} - | --------- required by `Foo::test` -... LL | <() as Foo>::test() | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | @@ -13,6 +10,11 @@ LL | <() as Foo>::test() <() as Foo<101_u8>> <() as Foo<102_u8>> and 252 others +note: required by `Foo::test` + --> $DIR/exhaustive-value.rs:6:5 + | +LL | fn test() {} + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr index 26b965901a..ebc8f458f7 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr @@ -6,3 +6,4 @@ LL | assert_eq!(f::<4usize>(Usizable), 20usize); error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr index 26b965901a..ebc8f458f7 100644 --- a/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr +++ b/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr @@ -6,3 +6,4 @@ LL | assert_eq!(f::<4usize>(Usizable), 20usize); error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/const-generics/auxiliary/impl-const.rs b/src/test/ui/const-generics/issues/auxiliary/impl-const.rs similarity index 100% rename from src/test/ui/const-generics/auxiliary/impl-const.rs rename to src/test/ui/const-generics/issues/auxiliary/impl-const.rs diff --git a/src/test/ui/const-generics/issues/issue-61432.rs b/src/test/ui/const-generics/issues/issue-61432.rs index 0e228126d7..97ab07dacc 100644 --- a/src/test/ui/const-generics/issues/issue-61432.rs +++ b/src/test/ui/const-generics/issues/issue-61432.rs @@ -6,9 +6,9 @@ fn promote() { // works: // // let n = N; - // &n; + // let _ = &n; - &N; + let _ = &N; } fn main() { diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr similarity index 100% rename from src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr rename to src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr similarity index 100% rename from src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr rename to src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs similarity index 100% rename from src/test/ui/const-generics/issue-61522-array-len-succ.rs rename to src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr similarity index 100% rename from src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr rename to src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs b/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs similarity index 100% rename from src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs rename to src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs diff --git a/src/test/ui/const-generics/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67375.full.stderr rename to src/test/ui/const-generics/issues/issue-67375.full.stderr diff --git a/src/test/ui/const-generics/issue-67375.min.stderr b/src/test/ui/const-generics/issues/issue-67375.min.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67375.min.stderr rename to src/test/ui/const-generics/issues/issue-67375.min.stderr diff --git a/src/test/ui/const-generics/issue-67375.rs b/src/test/ui/const-generics/issues/issue-67375.rs similarity index 100% rename from src/test/ui/const-generics/issue-67375.rs rename to src/test/ui/const-generics/issues/issue-67375.rs diff --git a/src/test/ui/const-generics/issue-67945-1.full.stderr b/src/test/ui/const-generics/issues/issue-67945-1.full.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67945-1.full.stderr rename to src/test/ui/const-generics/issues/issue-67945-1.full.stderr diff --git a/src/test/ui/const-generics/issue-67945-1.min.stderr b/src/test/ui/const-generics/issues/issue-67945-1.min.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67945-1.min.stderr rename to src/test/ui/const-generics/issues/issue-67945-1.min.stderr diff --git a/src/test/ui/const-generics/issue-67945-1.rs b/src/test/ui/const-generics/issues/issue-67945-1.rs similarity index 100% rename from src/test/ui/const-generics/issue-67945-1.rs rename to src/test/ui/const-generics/issues/issue-67945-1.rs diff --git a/src/test/ui/const-generics/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67945-2.full.stderr rename to src/test/ui/const-generics/issues/issue-67945-2.full.stderr diff --git a/src/test/ui/const-generics/issue-67945-2.min.stderr b/src/test/ui/const-generics/issues/issue-67945-2.min.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67945-2.min.stderr rename to src/test/ui/const-generics/issues/issue-67945-2.min.stderr diff --git a/src/test/ui/const-generics/issue-67945-2.rs b/src/test/ui/const-generics/issues/issue-67945-2.rs similarity index 100% rename from src/test/ui/const-generics/issue-67945-2.rs rename to src/test/ui/const-generics/issues/issue-67945-2.rs diff --git a/src/test/ui/const-generics/issue-67945-3.full.stderr b/src/test/ui/const-generics/issues/issue-67945-3.full.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67945-3.full.stderr rename to src/test/ui/const-generics/issues/issue-67945-3.full.stderr diff --git a/src/test/ui/const-generics/issue-67945-3.min.stderr b/src/test/ui/const-generics/issues/issue-67945-3.min.stderr similarity index 100% rename from src/test/ui/const-generics/issue-67945-3.min.stderr rename to src/test/ui/const-generics/issues/issue-67945-3.min.stderr diff --git a/src/test/ui/const-generics/issue-67945-3.rs b/src/test/ui/const-generics/issues/issue-67945-3.rs similarity index 100% rename from src/test/ui/const-generics/issue-67945-3.rs rename to src/test/ui/const-generics/issues/issue-67945-3.rs diff --git a/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs similarity index 100% rename from src/test/ui/const-generics/issue-68104-print-stack-overflow.rs rename to src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs diff --git a/src/test/ui/const-generics/issue-70180-1-stalled_on.rs b/src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs similarity index 100% rename from src/test/ui/const-generics/issue-70180-1-stalled_on.rs rename to src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs diff --git a/src/test/ui/const-generics/issue-70180-2-stalled_on.rs b/src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs similarity index 100% rename from src/test/ui/const-generics/issue-70180-2-stalled_on.rs rename to src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs diff --git a/src/test/ui/const-generics/issue-71202.rs b/src/test/ui/const-generics/issues/issue-71202.rs similarity index 100% rename from src/test/ui/const-generics/issue-71202.rs rename to src/test/ui/const-generics/issues/issue-71202.rs diff --git a/src/test/ui/const-generics/issue-71986.rs b/src/test/ui/const-generics/issues/issue-71986.rs similarity index 100% rename from src/test/ui/const-generics/issue-71986.rs rename to src/test/ui/const-generics/issues/issue-71986.rs diff --git a/src/test/ui/const-generics/issue-73899.rs b/src/test/ui/const-generics/issues/issue-73899.rs similarity index 100% rename from src/test/ui/const-generics/issue-73899.rs rename to src/test/ui/const-generics/issues/issue-73899.rs diff --git a/src/test/ui/const-generics/issue-74906.rs b/src/test/ui/const-generics/issues/issue-74906.rs similarity index 100% rename from src/test/ui/const-generics/issue-74906.rs rename to src/test/ui/const-generics/issues/issue-74906.rs diff --git a/src/test/ui/const-generics/issue-75763.rs b/src/test/ui/const-generics/issues/issue-75763.rs similarity index 100% rename from src/test/ui/const-generics/issue-75763.rs rename to src/test/ui/const-generics/issues/issue-75763.rs diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs similarity index 100% rename from src/test/ui/const-generics/issue-79518-default_trait_method_normalization.rs rename to src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs diff --git a/src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr similarity index 100% rename from src/test/ui/const-generics/issue-79518-default_trait_method_normalization.stderr rename to src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr diff --git a/src/test/ui/const-generics/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs similarity index 100% rename from src/test/ui/const-generics/issue-80561-incorrect-param-env.rs rename to src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs new file mode 100644 index 0000000000..f34badc693 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.rs @@ -0,0 +1,38 @@ +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait TensorDimension { + const DIM: usize; +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn lazy_updim(&self, size: [usize; NEWDIM]) {} +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + //~^ ERROR: method not compatible with trait [E0308] + self.reference.size() + //~^ ERROR: unconstrained generic constant + //~| ERROR: mismatched types + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr new file mode 100644 index 0000000000..ef785bf07e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -0,0 +1,29 @@ +error[E0308]: method not compatible with trait + --> $DIR/issue-83765.rs:30:5 + | +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected type `Self::DIM` + found type `DIM` + +error: unconstrained generic constant + --> $DIR/issue-83765.rs:32:24 + | +LL | self.reference.size() + | ^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:` + +error[E0308]: mismatched types + --> $DIR/issue-83765.rs:32:9 + | +LL | self.reference.size() + | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` + | + = note: expected type `DIM` + found type `Self::DIM` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issues/issue-85848.rs b/src/test/ui/const-generics/issues/issue-85848.rs new file mode 100644 index 0000000000..478719869b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-85848.rs @@ -0,0 +1,31 @@ +#![feature(const_generics, const_fn_trait_bound, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait _Contains { + const does_contain: bool; +} + +trait Contains {} + +trait Delegates {} + +impl Delegates for T where T: Contains {} + +const fn contains() -> bool +where + A: _Contains, +{ + A::does_contain +} + +impl Contains() }> for U where T: _Contains {} + +fn writes_to_path(cap: &C) { + writes_to_specific_path(&cap); + //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277] + //~| ERROR: unconstrained generic constant +} + +fn writes_to_specific_path>(cap: &C) {} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-85848.stderr b/src/test/ui/const-generics/issues/issue-85848.stderr new file mode 100644 index 0000000000..5e65136a6b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-85848.stderr @@ -0,0 +1,44 @@ +error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()` +... +LL | fn writes_to_specific_path>(cap: &C) {} + | ------------- required by this bound in `writes_to_specific_path` + | +note: required because of the requirements on the impl of `Contains<(), true>` for `&C` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl Contains() }> for U where T: _Contains {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl Delegates for T where T: Contains {} + | ^^^^^^^^^^^^ ^ + +error: unconstrained generic constant + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn writes_to_specific_path>(cap: &C) {} + | ------------- required by this bound in `writes_to_specific_path` + | + = help: try adding a `where` bound using this expression: `where [(); { contains::() }]:` +note: required because of the requirements on the impl of `Contains<(), true>` for `&C` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl Contains() }> for U where T: _Contains {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl Delegates for T where T: Contains {} + | ^^^^^^^^^^^^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-86820.rs b/src/test/ui/const-generics/issues/issue-86820.rs new file mode 100644 index 0000000000..04650403c6 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-86820.rs @@ -0,0 +1,25 @@ +// Regression test for the ICE described in #86820. + +#![allow(unused,dead_code)] +use std::ops::BitAnd; + +const C: fn() = || is_set(); +fn is_set() { + 0xffu8.bit::<0>(); +} + +trait Bits { + fn bit(self) -> bool; + //~^ NOTE: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8` +} + +impl Bits for u8 { + fn bit(self) -> bool { + //~^ ERROR: method `bit` has an incompatible const parameter type for trait [E0053] + let i = 1 << I; + let mask = u8::from(i); + mask & self == mask + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-86820.stderr b/src/test/ui/const-generics/issues/issue-86820.stderr new file mode 100644 index 0000000000..f4396f2f2b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-86820.stderr @@ -0,0 +1,15 @@ +error[E0053]: method `bit` has an incompatible const parameter type for trait + --> $DIR/issue-86820.rs:17:18 + | +LL | fn bit(self) -> bool { + | ^ + | +note: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8` + --> $DIR/issue-86820.rs:12:18 + | +LL | fn bit(self) -> bool; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/const-generics/issues/issue-87076.rs b/src/test/ui/const-generics/issues/issue-87076.rs new file mode 100644 index 0000000000..5dfda943bf --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87076.rs @@ -0,0 +1,20 @@ +// build-pass + +#![feature(const_generics)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +pub struct UnitDims { + pub time: u8, + pub length: u8, +} + +pub struct UnitValue; + +impl UnitValue { + fn crash() {} +} + +fn main() { + UnitValue::<{ UnitDims { time: 1, length: 2 } }>::crash(); +} diff --git a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs index d845e00694..ae8863c567 100644 --- a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs +++ b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs @@ -13,7 +13,7 @@ fn b() { //~| ERROR expected trait, found constant `BAR` //~| ERROR type provided when a constant was expected //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition } fn c() { foo::<3 + 3>(); //~ ERROR expressions must be enclosed in braces diff --git a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr index 857498a111..b93bd6c6fa 100644 --- a/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr +++ b/src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr @@ -138,7 +138,7 @@ LL | foo::(); | ^^^^^^^^^ help: use `dyn`: `dyn BAR + BAR` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error[E0747]: type provided when a constant was expected diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr index 6830288acc..382dd0ee5a 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -1,16 +1,18 @@ error[E0277]: the trait bound `A<{_: usize}>: Bar<{_: usize}>` is not satisfied --> $DIR/unused-substs-1.rs:12:13 | -LL | / struct A -LL | | where -LL | | A: Bar; - | |_________________- required by `A` -... -LL | let _ = A; - | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` +LL | let _ = A; + | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` | = help: the following implementations were found: as Bar> +note: required by `A` + --> $DIR/unused-substs-1.rs:7:1 + | +LL | / struct A +LL | | where +LL | | A: Bar; + | |_________________^ error: aborting due to previous error diff --git a/src/test/ui/const-ptr/out_of_bounds_read.rs b/src/test/ui/const-ptr/out_of_bounds_read.rs new file mode 100644 index 0000000000..c45198cc39 --- /dev/null +++ b/src/test/ui/const-ptr/out_of_bounds_read.rs @@ -0,0 +1,16 @@ +// error-pattern: evaluation of constant value failed + +#![feature(const_ptr_read)] +#![feature(const_ptr_offset)] + +fn main() { + use std::ptr; + + const DATA: [u32; 1] = [42]; + + const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) }; + + const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; +} diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr new file mode 100644 index 0000000000..9254177921 --- /dev/null +++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr @@ -0,0 +1,70 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | unsafe { copy_nonoverlapping(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | inside `copy_nonoverlapping::` at $SRC_DIR/core/src/intrinsics.rs:LL:COL + | + ::: $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | +LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + | --------------------------------------------- inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + ::: $DIR/out_of_bounds_read.rs:13:33 + | +LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + | ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:13:33 + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | unsafe { copy_nonoverlapping(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | inside `copy_nonoverlapping::` at $SRC_DIR/core/src/intrinsics.rs:LL:COL + | + ::: $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | +LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + | --------------------------------------------- inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | +LL | unsafe { read(self) } + | ---------- inside `ptr::const_ptr::::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + ::: $DIR/out_of_bounds_read.rs:14:39 + | +LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + | ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:14:39 + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | unsafe { copy_nonoverlapping(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | inside `copy_nonoverlapping::` at $SRC_DIR/core/src/intrinsics.rs:LL:COL + | + ::: $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | +LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); + | --------------------------------------------- inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL + | +LL | unsafe { read(self) } + | ---------- inside `ptr::mut_ptr::::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL + | + ::: $DIR/out_of_bounds_read.rs:15:37 + | +LL | const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; + | --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:15:37 + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-ptr/ptr_to_usize_cast.rs b/src/test/ui/const-ptr/ptr_to_usize_cast.rs deleted file mode 100644 index bf1e790b5d..0000000000 --- a/src/test/ui/const-ptr/ptr_to_usize_cast.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(const_raw_ptr_to_usize_cast)] - -fn main() { - const OK: usize = unsafe { 0 as *const i32 as usize }; - - const _ERROR: usize = unsafe { &0 as *const i32 as usize }; - //~^ ERROR [const_err] - //~| NOTE cannot cast pointer to integer because it was not created by cast from integer - //~| NOTE - //~| NOTE `#[deny(const_err)]` on by default - //~| WARN this was previously accepted by the compiler but is being phased out - //~| NOTE see issue #71800 -} diff --git a/src/test/ui/const-ptr/ptr_to_usize_cast.stderr b/src/test/ui/const-ptr/ptr_to_usize_cast.stderr deleted file mode 100644 index 48255860bb..0000000000 --- a/src/test/ui/const-ptr/ptr_to_usize_cast.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: any use of this value will cause an error - --> $DIR/ptr_to_usize_cast.rs:6:36 - | -LL | const _ERROR: usize = unsafe { &0 as *const i32 as usize }; - | -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | cannot cast pointer to integer because it was not created by cast from integer - | - = 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 - -error: aborting due to previous error - 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 187e2760ad..5f23cc2311 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 @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:26:5 | LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc2────────╼ │ ╾──────╼ + ╾───────alloc3────────╼ │ ╾──────╼ } error: any use of this value will cause an error @@ -47,11 +47,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:41:5 | LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc19, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc18───────╼ │ ╾──────╼ + ╾───────alloc19───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -102,11 +102,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:59:5 | LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc38, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc39, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc38───────╼ │ ╾──────╼ + ╾───────alloc39───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -135,11 +135,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:69:5 | LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc50, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc51, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc50───────╼ │ ╾──────╼ + ╾───────alloc51───────╼ │ ╾──────╼ } error: any use of this value will cause an error @@ -201,11 +201,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:92:5 | LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc71, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc72, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc71───────╼ │ ╾──────╼ + ╾───────alloc72───────╼ │ ╾──────╼ } error: any use of this value will cause an error @@ -256,11 +256,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:111:5 | LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc86, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc87, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc86───────╼ │ ╾──────╼ + ╾───────alloc87───────╼ │ ╾──────╼ } error: any use of this value will cause an error @@ -289,11 +289,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:122:5 | LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc95, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc96, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc95───────╼ │ ╾──────╼ + ╾───────alloc96───────╼ │ ╾──────╼ } error: any use of this value will cause an error diff --git a/src/test/ui/consts/const-eval/const_panic.rs b/src/test/ui/consts/const-eval/const_panic.rs index b33b1475a2..e4455d86a1 100644 --- a/src/test/ui/consts/const-eval/const_panic.rs +++ b/src/test/ui/consts/const-eval/const_panic.rs @@ -1,35 +1,35 @@ #![feature(const_panic)] -#![allow(non_fmt_panic)] +#![allow(non_fmt_panics)] #![crate_type = "lib"] const MSG: &str = "hello"; const Z: () = std::panic!("cheese"); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const Z2: () = std::panic!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const Y: () = std::unreachable!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const X: () = std::unimplemented!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed // const W: () = std::panic!(MSG); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const Z_CORE: () = core::panic!("cheese"); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const Z2_CORE: () = core::panic!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const Y_CORE: () = core::unreachable!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const X_CORE: () = core::unimplemented!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const W_CORE: () = core::panic!(MSG); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-eval/const_panic.stderr b/src/test/ui/consts/const-eval/const_panic.stderr index 3c890f78af..c0c749ede5 100644 --- a/src/test/ui/consts/const-eval/const_panic.stderr +++ b/src/test/ui/consts/const-eval/const_panic.stderr @@ -1,100 +1,80 @@ -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:7:15 | LL | const Z: () = std::panic!("cheese"); - | --------------^^^^^^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:10:16 | LL | const Z2: () = std::panic!(); - | ---------------^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:10:16 + | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:10:16 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:13:15 | LL | const Y: () = std::unreachable!(); - | --------------^^^^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:13:15 + | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:13:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:16:15 | LL | const X: () = std::unimplemented!(); - | --------------^^^^^^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:16:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:16:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:19:15 | LL | const W: () = std::panic!(MSG); - | --------------^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'hello', $DIR/const_panic.rs:19:15 + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:19:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:22:20 | LL | const Z_CORE: () = core::panic!("cheese"); - | -------------------^^^^^^^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20 + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:25:21 | LL | const Z2_CORE: () = core::panic!(); - | --------------------^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21 + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:28:20 | LL | const Y_CORE: () = core::unreachable!(); - | -------------------^^^^^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20 + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:31:20 | LL | const X_CORE: () = core::unimplemented!(); - | -------------------^^^^^^^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20 + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:34:20 | LL | const W_CORE: () = core::panic!(MSG); - | -------------------^^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20 + | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs b/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs index 6b03e847de..1ea0845c96 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs +++ b/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs @@ -7,13 +7,13 @@ use core::panic::PanicInfo; const Z: () = panic!("cheese"); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const Y: () = unreachable!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed const X: () = unimplemented!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed #[lang = "eh_personality"] fn eh() {} diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr b/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr index 2a3ad3ca18..9abf8a20b8 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr +++ b/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr @@ -1,30 +1,24 @@ -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic_libcore_bin.rs:9:15 | LL | const Z: () = panic!("cheese"); - | --------------^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_bin.rs:9:15 + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_bin.rs:9:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic_libcore_bin.rs:12:15 | LL | const Y: () = unreachable!(); - | --------------^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_bin.rs:12:15 + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_bin.rs:12:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const_panic_libcore_bin.rs:15:15 | LL | const X: () = unimplemented!(); - | --------------^^^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_bin.rs:15:15 + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_bin.rs:15:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/const-eval/const_panic_track_caller.rs b/src/test/ui/consts/const-eval/const_panic_track_caller.rs new file mode 100644 index 0000000000..7c2532673c --- /dev/null +++ b/src/test/ui/consts/const-eval/const_panic_track_caller.rs @@ -0,0 +1,23 @@ +#![feature(const_panic)] +#![allow(non_fmt_panics)] +#![crate_type = "lib"] + +#[track_caller] +const fn a() -> u32 { + panic!("hey") +} + +#[track_caller] +const fn b() -> u32 { + a() +} + +const fn c() -> u32 { + b() + //~^ ERROR evaluation of constant value failed + //~| NOTE the evaluated program panicked + //~| NOTE inside +} + +const X: u32 = c(); +//~^ NOTE inside diff --git a/src/test/ui/consts/const-eval/const_panic_track_caller.stderr b/src/test/ui/consts/const-eval/const_panic_track_caller.stderr new file mode 100644 index 0000000000..9a458db6ea --- /dev/null +++ b/src/test/ui/consts/const-eval/const_panic_track_caller.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_track_caller.rs:16:5 + | +LL | b() + | ^^^ + | | + | the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:16:5 + | inside `c` at $DIR/const_panic_track_caller.rs:16:5 +... +LL | const X: u32 = c(); + | --- inside `X` at $DIR/const_panic_track_caller.rs:22:16 + +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_raw_ptr_ops2.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs index c6a623b293..11f6a58be3 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -1,16 +1,12 @@ -#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] +#![feature(const_raw_ptr_deref)] fn main() {} -// unconst and fine -const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; -// unconst and bad, will thus error in miri -const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this -//~| WARN this was previously accepted by the compiler but is being phased out -// unconst and fine +// fine const Z: i32 = unsafe { *(&1 as *const i32) }; -// unconst and bad, will thus error in miri -const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause -//~| WARN this was previously accepted by the compiler but is being phased out -const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause -//~| WARN this was previously accepted by the compiler but is being phased out + +// bad, will thus error in miri +const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR evaluation of constant value failed +//~| is not a valid pointer +const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR evaluation of constant value failed +//~| is not a valid pointer diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr index df8b33a089..ca32900773 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr @@ -1,36 +1,15 @@ -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops2.rs:8:28 - | -LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; - | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^------- - | | - | cannot cast pointer to integer because it was not created by cast from integer - | - = 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 - -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops2.rs:13:26 +error[E0080]: evaluation of constant value failed + --> $DIR/const_raw_ptr_ops2.rs:9:26 | LL | const Z2: i32 = unsafe { *(42 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn bytes into a pointer - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^ 0x2a is not a valid pointer -error: any use of this value will cause an error - --> $DIR/const_raw_ptr_ops2.rs:15:26 +error[E0080]: evaluation of constant value failed + --> $DIR/const_raw_ptr_ops2.rs:11:26 | LL | const Z3: i32 = unsafe { *(44 as *const i32) }; - | -------------------------^^^^^^^^^^^^^^^^^^^--- - | | - | unable to turn bytes into a pointer - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^ 0x2c is not a valid pointer -error: aborting due to 3 previous errors +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/dangling.rs b/src/test/ui/consts/const-eval/dangling.rs index 45c429c7eb..610531c7b4 100644 --- a/src/test/ui/consts/const-eval/dangling.rs +++ b/src/test/ui/consts/const-eval/dangling.rs @@ -5,9 +5,8 @@ use std::mem; // Make sure we error with the right kind of error on a too large slice. const TEST: () = { unsafe { let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); - let _val = &*slice; //~ ERROR: any use of this value will cause an error + let _val = &*slice; //~ ERROR: evaluation of constant value failed //~| slice is bigger than largest supported object - //~| WARN this was previously accepted by the compiler but is being phased out } }; fn main() {} diff --git a/src/test/ui/consts/const-eval/dangling.stderr b/src/test/ui/consts/const-eval/dangling.stderr index 224fbb62a4..5665a9c3e0 100644 --- a/src/test/ui/consts/const-eval/dangling.stderr +++ b/src/test/ui/consts/const-eval/dangling.stderr @@ -1,18 +1,9 @@ -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/dangling.rs:8:16 | -LL | / const TEST: () = { unsafe { -LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); -LL | | let _val = &*slice; - | | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object -LL | | -LL | | -LL | | } }; - | |____- - | - = note: `#[deny(const_err)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | let _val = &*slice; + | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs index 43d79badd7..4df541eeeb 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs @@ -8,8 +8,7 @@ const FOO: i32 = foo(); const fn foo() -> i32 { unsafe { let _ = intrinsics::const_allocate(4, 3) as * mut i32; - //~^ 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 constant value failed } 1 diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr index 3d529ab4ca..327e291120 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr @@ -1,19 +1,15 @@ -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/alloc_intrinsic_errors.rs:10:17 | LL | const FOO: i32 = foo(); - | ----------------------- + | ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18 ... LL | let _ = intrinsics::const_allocate(4, 3) as * mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | align has to be a power of 2, `3` is not a power of 2 | inside `foo` at $DIR/alloc_intrinsic_errors.rs:10:17 - | inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18 - | - = 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 error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index 92d990f149..c11fea8533 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc_intrinsic_uninit.rs:9:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc1──╼ │ ╾──╼ + ╾─alloc2──╼ │ ╾──╼ } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr index 6d63233997..58d24dc2e8 100644 --- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr +++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc_intrinsic_uninit.rs:9:1 | LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc1────────╼ │ ╾──────╼ + ╾───────alloc2────────╼ │ ╾──────╼ } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/issue-49296.rs b/src/test/ui/consts/const-eval/issue-49296.rs index f2d9758b8d..baa1848e9c 100644 --- a/src/test/ui/consts/const-eval/issue-49296.rs +++ b/src/test/ui/consts/const-eval/issue-49296.rs @@ -17,8 +17,7 @@ const fn wat(x: u64) -> &'static u64 { unsafe { transmute(&x) } } const X: u64 = *wat(42); -//~^ 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() { println!("{}", X); diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr index 0389471edb..4fd8e18909 100644 --- a/src/test/ui/consts/const-eval/issue-49296.stderr +++ b/src/test/ui/consts/const-eval/issue-49296.stderr @@ -1,14 +1,9 @@ -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/issue-49296.rs:19:16 | LL | const X: u64 = *wat(42); - | ---------------^^^^^^^^- - | | - | pointer to alloc1 was dereferenced after this allocation got freed - | - = 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 + | ^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed 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/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs deleted file mode 100644 index 159b48d42b..0000000000 --- a/src/test/ui/consts/const-eval/issue-52442.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - [(); { &loop { break } as *const _ as usize } ]; - //~^ ERROR casting pointers to integers in constants is unstable -} diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr deleted file mode 100644 index 2a8f34279c..0000000000 --- a/src/test/ui/consts/const-eval/issue-52442.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/issue-52442.rs:2:13 - | -LL | [(); { &loop { break } as *const _ as usize } ]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.rs b/src/test/ui/consts/const-eval/match-test-ptr-null.rs index d980eb92a2..4af97b5487 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.rs +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.rs @@ -4,7 +4,7 @@ fn main() { // bytes. let _: [u8; 0] = [4; { match &1 as *const i32 as usize { - //~^ ERROR casting pointers to integers in constants + //~^ ERROR pointers cannot be cast to integers during const eval 0 => 42, n => n, } diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr index 22d6bb1694..4e55b36da7 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr @@ -1,12 +1,11 @@ -error[E0658]: casting pointers to integers in constants is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/match-test-ptr-null.rs:6:15 | LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. 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 dd18a98035..78cf25308f 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 @@ -9,7 +9,7 @@ struct PrintName; impl PrintName { const VOID: ! = panic!(); - //~^ ERROR any use of this value will cause an error + //~^ ERROR evaluation of constant value failed } fn main() { 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 e186240f53..0856094830 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,10 +1,8 @@ -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/panic-assoc-never-type.rs:11:21 | LL | const VOID: ! = panic!(); - | ----------------^^^^^^^^- - | | - | the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:11:21 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:11:21 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/const-eval/panic-never-type.rs b/src/test/ui/consts/const-eval/panic-never-type.rs index 71b489d828..dd875768b1 100644 --- a/src/test/ui/consts/const-eval/panic-never-type.rs +++ b/src/test/ui/consts/const-eval/panic-never-type.rs @@ -4,7 +4,7 @@ #![feature(never_type)] const VOID: ! = panic!(); -//~^ ERROR any use of this value will cause an error +//~^ ERROR evaluation of constant value failed fn main() { let _ = VOID; 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 2254c3dcfd..9b7f2181c1 100644 --- a/src/test/ui/consts/const-eval/panic-never-type.stderr +++ b/src/test/ui/consts/const-eval/panic-never-type.stderr @@ -1,10 +1,8 @@ -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/panic-never-type.rs:6:17 | LL | const VOID: ! = panic!(); - | ----------------^^^^^^^^- - | | - | the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:6:17 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:6:17 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs index d724fe3060..c7d84303fe 100644 --- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs @@ -1,4 +1,4 @@ -#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)] +#![feature(const_raw_ptr_deref)] fn main() { let x: &'static bool = &(42 as *const i32 == 43 as *const i32); 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 c14457490a..ff90bb5fdd 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 @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ref_to_int_match.rs:26:1 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc2──╼ │ ╾──╼ + ╾─alloc3──╼ │ ╾──╼ } error: could not evaluate constant pattern 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 6ea1cf145a..499c4536c4 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 @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ref_to_int_match.rs:26:1 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc3, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc2────────╼ │ ╾──────╼ + ╾───────alloc3────────╼ │ ╾──────╼ } error: could not evaluate constant pattern 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 2274366fa2..850acb52b0 100644 --- a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:24:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001 at ., but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered 0x00000001, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -13,29 +13,29 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:27:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc8 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc9, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc8──╼ │ ╾──╼ + ╾─alloc9──╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc12 at .0., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc13, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc12─╼ │ ╾──╼ + ╾─alloc13─╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:42:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000 at ., but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered 0x00000000, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -46,29 +46,29 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:44:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc19, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc18─╼ │ ╾──╼ + ╾─alloc19─╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:47:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22 at .0., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc23, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc22─╼ │ ╾──╼ + ╾─alloc23─╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:56:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -79,18 +79,18 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc28 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc29, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc28─╼ │ ╾──╼ + ╾─alloc29─╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:77:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -101,7 +101,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:79:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered a value of uninhabited type Never | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -112,7 +112,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:87:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at ..0.1, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -123,7 +123,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:92:1 | LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0.1: encountered a value of uninhabited type Never | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -134,7 +134,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:94:1 | LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0.1: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { 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 29d97962f3..4f7dd5cdf7 100644 --- a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:24:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x0000000000000001 at ., but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered 0x0000000000000001, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -13,29 +13,29 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:27:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc8 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc9, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc8────────╼ │ ╾──────╼ + ╾───────alloc9────────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc12 at .0., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc13, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc12───────╼ │ ╾──────╼ + ╾───────alloc13───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:42:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x0000000000000000 at ., but expected a valid enum tag + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered 0x0000000000000000, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -46,29 +46,29 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:44:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc18 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc19, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc18───────╼ │ ╾──────╼ + ╾───────alloc19───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:47:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22 at .0., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc23, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc22───────╼ │ ╾──────╼ + ╾───────alloc23───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:56:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -79,18 +79,18 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc28 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc29, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc28───────╼ │ ╾──────╼ + ╾───────alloc29───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:77:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -101,7 +101,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:79:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered a value of uninhabited type Never | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -112,7 +112,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:87:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at ..0.1, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -123,7 +123,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:92:1 | LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0.1: encountered a value of uninhabited type Never | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -134,7 +134,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:94:1 | LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0.1: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr new file mode 100644 index 0000000000..ffde14f894 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -0,0 +1,39 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:19:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2 + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:24:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:34:1 + | +LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = +LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) }; + | |_____________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: alignment `1000` is not a power of 2 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:39:1 + | +LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = +LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) }; + | |______________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: size is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } + +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-eval/ub-incorrect-vtable.64bit.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr new file mode 100644 index 0000000000..2ad164a8c3 --- /dev/null +++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -0,0 +1,39 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:19:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2 + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:24:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:34:1 + | +LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = +LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) }; + | |_____________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: alignment `1000` is not a power of 2 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:39:1 + | +LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = +LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) }; + | |______________________________________________________________________________________________^ type validation failed at .0: encountered invalid vtable: size is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +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-eval/ub-incorrect-vtable.rs b/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs index 0c0e3682de..4ec853576c 100644 --- a/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs +++ b/src/test/ui/consts/const-eval/ub-incorrect-vtable.rs @@ -3,19 +3,42 @@ // triggers an error // - a similar test that triggers a previously-untested const UB error: emitted close to the above // error, it checks the correctness of the size +// +// As is, this code will only hard error when the constants are used, and the errors are emitted via +// the `#[allow]`-able `const_err` lint. However, if the transparent wrapper technique to prevent +// reborrows is used -- from `ub-wide-ptr.rs` -- these two errors reach validation and would trigger +// ICEs as tracked by #86193. So we also use the transparent wrapper to verify proper validation +// errors are emitted instead of ICEs. + +// stderr-per-bitwidth +// normalize-stderr-test "alloc\d+" -> "allocN" trait Trait {} const INVALID_VTABLE_ALIGNMENT: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; -//~^ ERROR any use of this value will cause an error -//~| WARNING this was previously accepted by the compiler +//~^ ERROR evaluation of constant value failed //~| invalid vtable: alignment `1000` is not a power of 2 const INVALID_VTABLE_SIZE: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; -//~^ ERROR any use of this value will cause an error -//~| WARNING this was previously accepted by the compiler +//~^ ERROR evaluation of constant value failed +//~| invalid vtable: size is bigger than largest supported object + +#[repr(transparent)] +struct W(T); + +// The drop fn is checked before size/align are, so get ourselves a "sufficiently valid" drop fn +fn drop_me(_: *mut usize) {} + +const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = + unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) }; +//~^^ ERROR it is undefined behavior to use this value +//~| invalid vtable: alignment `1000` is not a power of 2 + +const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = + unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) }; +//~^^ ERROR it is undefined behavior to use this value //~| invalid vtable: size is bigger than largest supported object fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr b/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr deleted file mode 100644 index c937d039d3..0000000000 --- a/src/test/ui/consts/const-eval/ub-incorrect-vtable.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: any use of this value will cause an error - --> $DIR/ub-incorrect-vtable.rs:10:14 - | -LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait = -LL | | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; - | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__- - | | - | invalid vtable: alignment `1000` is not a power of 2 - | - = 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 - -error: any use of this value will cause an error - --> $DIR/ub-incorrect-vtable.rs:16:14 - | -LL | / const INVALID_VTABLE_SIZE: &dyn Trait = -LL | | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; - | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__- - | | - | invalid vtable: size is bigger than largest supported object - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 - -error: aborting due to 2 previous errors - 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 c13271a1e5..df02bdaa33 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 @@ -8,7 +8,7 @@ LL | | [ ... | LL | | ] LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at [0] + | |__^ type validation failed at [0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -25,7 +25,7 @@ LL | | mem::transmute( ... | LL | | ) LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at [1] + | |__^ type validation failed at [1]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -42,7 +42,7 @@ LL | | mem::transmute( ... | LL | | ) LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at [2] + | |__^ type validation failed at [2]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { 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 c13271a1e5..df02bdaa33 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 @@ -8,7 +8,7 @@ LL | | [ ... | LL | | ] LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at [0] + | |__^ type validation failed at [0]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -25,7 +25,7 @@ LL | | mem::transmute( ... | LL | | ) LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at [1] + | |__^ type validation failed at [1]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { @@ -42,7 +42,7 @@ LL | | mem::transmute( ... | LL | | ) LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at [2] + | |__^ type validation failed at [2]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { 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 635cbb8cef..7e0fb33bc1 100644 --- a/src/test/ui/consts/const-eval/ub-int-array.rs +++ b/src/test/ui/consts/const-eval/ub-int-array.rs @@ -13,7 +13,7 @@ union MaybeUninit { const UNINIT_INT_0: [u32; 3] = unsafe { //~^ ERROR it is undefined behavior to use this value -//~| type validation failed: encountered uninitialized bytes at [0] +//~| type validation failed at [0]: encountered uninitialized bytes [ MaybeUninit { uninit: () }.init, 1, @@ -22,7 +22,7 @@ const UNINIT_INT_0: [u32; 3] = unsafe { }; const UNINIT_INT_1: [u32; 3] = unsafe { //~^ ERROR it is undefined behavior to use this value -//~| type validation failed: encountered uninitialized bytes at [1] +//~| type validation failed at [1]: encountered uninitialized bytes mem::transmute( [ 0u8, @@ -42,7 +42,7 @@ const UNINIT_INT_1: [u32; 3] = unsafe { }; const UNINIT_INT_2: [u32; 3] = unsafe { //~^ ERROR it is undefined behavior to use this value -//~| type validation failed: encountered uninitialized bytes at [2] +//~| type validation failed at [2]: encountered uninitialized bytes mem::transmute( [ 0u8, 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 ce8ab632fc..e44f324945 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr @@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull = 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-nonnull.rs:19:30 | -LL | / const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { -LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle -LL | | // Use address-of-element for pointer arithmetic. This could wrap around to null! -LL | | let out_of_bounds_ptr = &ptr[255]; - | | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1 -LL | | -LL | | mem::transmute(out_of_bounds_ptr) -LL | | } }; - | |____- - | -note: the lint level is defined here - --> $DIR/ub-nonnull.rs:15:8 - | -LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen - | ^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +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:24:1 + --> $DIR/ub-nonnull.rs:23:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -42,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:26:1 + --> $DIR/ub-nonnull.rs:25:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -53,10 +38,10 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:34:1 + --> $DIR/ub-nonnull.rs:33:1 | LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; } 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) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 @@ -75,7 +60,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) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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 3f49a262ae..1ce87bc7c1 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr @@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull = 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-nonnull.rs:19:30 | -LL | / const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { -LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle -LL | | // Use address-of-element for pointer arithmetic. This could wrap around to null! -LL | | let out_of_bounds_ptr = &ptr[255]; - | | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1 -LL | | -LL | | mem::transmute(out_of_bounds_ptr) -LL | | } }; - | |____- - | -note: the lint level is defined here - --> $DIR/ub-nonnull.rs:15:8 - | -LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen - | ^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +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:24:1 + --> $DIR/ub-nonnull.rs:23:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -42,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:26:1 + --> $DIR/ub-nonnull.rs:25:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -53,10 +38,10 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:34:1 + --> $DIR/ub-nonnull.rs:33:1 | LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; } 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) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 @@ -75,7 +60,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) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: 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 75c02a8da1..259707b802 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -16,8 +16,7 @@ const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; const OUT_OF_BOUNDS_PTR: NonNull = { 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! - let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error - //~| WARN this was previously accepted by the compiler but is being phased out + let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed mem::transmute(out_of_bounds_ptr) } }; 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 d4a61a4631..c8ec7cc487 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 @@ -6,7 +6,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | = 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──╼ │ ╾──╼ + ╾─alloc3──╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc6──╼ │ ╾──╼ + ╾─alloc7──╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -46,40 +46,40 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:30:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc14, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc15, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc14─╼ │ ╾──╼ + ╾─alloc15─╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:33:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc20─╼ │ ╾──╼ + ╾─alloc21─╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:36:1 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc25─╼ │ ╾──╼ + ╾─alloc26─╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:39:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x539 is unallocated) | = 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) { @@ -90,7 +90,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:42:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (address 0x539 is unallocated) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr index 17da7c25ba..60a174ac5a 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 @@ -6,7 +6,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | = 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────────╼ │ ╾──────╼ + ╾───────alloc3────────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -17,7 +17,7 @@ LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc6────────╼ │ ╾──────╼ + ╾───────alloc7────────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -46,40 +46,40 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:30:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc14, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc15, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc14───────╼ │ ╾──────╼ + ╾───────alloc15───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:33:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc20───────╼ │ ╾──────╼ + ╾───────alloc21───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:36:1 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc25───────╼ │ ╾──────╼ + ╾───────alloc26───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:39:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (address 0x539 is unallocated) | = 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) { @@ -90,7 +90,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:42:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (address 0x539 is unallocated) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr index 4155a8a2ef..350bd94193 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr @@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -22,7 +22,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} 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 def795c7f5..13a4fde083 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr @@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -22,7 +22,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} diff --git a/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr index 33251535be..27b98c2547 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -6,11 +6,11 @@ LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; LL | | let another_var = 13; LL | | move || { let _ = bad_ref; let _ = another_var; } LL | | }; - | |__^ type validation failed: encountered a null reference at ... + | |__^ type validation failed at ...: encountered a null reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc2──╼ ╾─alloc3──╼ │ ╾──╼╾──╼ + ╾─alloc3──╼ ╾─alloc6──╼ │ ╾──╼╾──╼ } error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr index de6033702a..9cc9fb59bd 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -6,11 +6,11 @@ LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; LL | | let another_var = 13; LL | | move || { let _ = bad_ref; let _ = another_var; } LL | | }; - | |__^ type validation failed: encountered a null reference at ... + | |__^ type validation failed at ...: encountered a null reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc2────────╼ ╾───────alloc3────────╼ │ ╾──────╼╾──────╼ + ╾───────alloc3────────╼ ╾───────alloc6────────╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error 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 c69674a672..2a489e8b69 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 @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:40:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -57,7 +57,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:52:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:55:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -138,7 +138,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:81:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .[0], but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -149,7 +149,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:87:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at ..0, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -160,7 +160,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:90:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at ..1[0], but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..1[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -186,7 +186,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:105:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -197,7 +197,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:108:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -208,7 +208,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:111:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -252,7 +252,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:119:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -263,7 +263,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:123:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .., but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -302,7 +302,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:139:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 12 bytes starting at offset N is out-of-bounds error: aborting due to 28 previous errors 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 bb95343a78..ff850d2dbe 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 @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:40:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -57,7 +57,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:52:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:55:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -138,7 +138,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:81:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .[0], but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -149,7 +149,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:87:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at ..0, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -160,7 +160,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:90:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at ..1[0], but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..1[0]: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -186,7 +186,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:105:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -197,7 +197,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:108:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -208,7 +208,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:111:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -252,7 +252,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:119:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) at .0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -263,7 +263,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:123:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .., but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..: encountered 0x03, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -302,7 +302,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:139:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 24 bytes starting at offset N is out-of-bounds error: aborting due to 28 previous errors diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index 6d44b3c8b2..b1ab03400c 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -16,7 +16,7 @@ LL | / const FIELD_PATH: Struct = Struct { LL | | a: 42, LL | | b: unsafe { UNION.field3 }, LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes + | |__^ type validation failed at .b: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -33,7 +33,7 @@ LL | | unsafe { UNION.field3 }, ... | LL | | a: 42, LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at .b[1] + | |__^ type validation failed at .b[1]: encountered uninitialized bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 40, align: 8) { diff --git a/src/test/ui/consts/const-eval/unwind-abort.rs b/src/test/ui/consts/const-eval/unwind-abort.rs index 9bc63d9328..766a0c49be 100644 --- a/src/test/ui/consts/const-eval/unwind-abort.rs +++ b/src/test/ui/consts/const-eval/unwind-abort.rs @@ -2,7 +2,7 @@ #[unwind(aborts)] const fn foo() { - panic!() //~ ERROR any use of this value will cause an error + panic!() //~ ERROR evaluation of constant value failed } const _: () = foo(); diff --git a/src/test/ui/consts/const-eval/unwind-abort.stderr b/src/test/ui/consts/const-eval/unwind-abort.stderr index b41d786169..e3b871ee52 100644 --- a/src/test/ui/consts/const-eval/unwind-abort.stderr +++ b/src/test/ui/consts/const-eval/unwind-abort.stderr @@ -1,4 +1,4 @@ -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/unwind-abort.rs:5:5 | LL | panic!() @@ -6,10 +6,9 @@ LL | panic!() | | | the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:5:5 | inside `foo` at $SRC_DIR/std/src/panic.rs:LL:COL - | inside `_` at $DIR/unwind-abort.rs:8:15 ... LL | const _: () = foo(); - | -------------------- + | ----- inside `_` at $DIR/unwind-abort.rs:8:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) 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 e25abab7e3..0022d19e95 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 @@ -1,4 +1,4 @@ -warning: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/validate_uninhabited_zsts.rs:5:14 | LL | unsafe { std::mem::transmute(()) } @@ -6,24 +6,15 @@ LL | unsafe { std::mem::transmute(()) } | | | transmuting to uninhabited type | inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14 - | inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26 ... LL | const FOO: [Empty; 3] = [foo(); 3]; - | ----------------------------------- - | -note: the lint level is defined here - --> $DIR/validate_uninhabited_zsts.rs:14:8 - | -LL | #[warn(const_err)] - | ^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26 error[E0080]: it is undefined behavior to use this value - --> $DIR/validate_uninhabited_zsts.rs:18:1 + --> $DIR/validate_uninhabited_zsts.rs:17:1 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} @@ -41,7 +32,7 @@ LL | unsafe { std::mem::transmute(()) } = note: the `!` type has no valid value warning: the type `Empty` does not permit zero-initialization - --> $DIR/validate_uninhabited_zsts.rs:18:35 + --> $DIR/validate_uninhabited_zsts.rs:17:35 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,6 +42,6 @@ LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | = note: enums with no variants have no valid value -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 2 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0080`. 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 e25abab7e3..0022d19e95 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 @@ -1,4 +1,4 @@ -warning: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/validate_uninhabited_zsts.rs:5:14 | LL | unsafe { std::mem::transmute(()) } @@ -6,24 +6,15 @@ LL | unsafe { std::mem::transmute(()) } | | | transmuting to uninhabited type | inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14 - | inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26 ... LL | const FOO: [Empty; 3] = [foo(); 3]; - | ----------------------------------- - | -note: the lint level is defined here - --> $DIR/validate_uninhabited_zsts.rs:14:8 - | -LL | #[warn(const_err)] - | ^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26 error[E0080]: it is undefined behavior to use this value - --> $DIR/validate_uninhabited_zsts.rs:18:1 + --> $DIR/validate_uninhabited_zsts.rs:17:1 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 0, align: 1) {} @@ -41,7 +32,7 @@ LL | unsafe { std::mem::transmute(()) } = note: the `!` type has no valid value warning: the type `Empty` does not permit zero-initialization - --> $DIR/validate_uninhabited_zsts.rs:18:35 + --> $DIR/validate_uninhabited_zsts.rs:17:35 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,6 +42,6 @@ LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | = note: enums with no variants have no valid value -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 2 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs index 112ace5e97..f6b6a1f53e 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs @@ -3,9 +3,8 @@ const fn foo() -> ! { unsafe { std::mem::transmute(()) } - //~^ WARN any use of this value will cause an error [const_err] + //~^ ERROR evaluation of constant value failed //~| WARN the type `!` does not permit zero-initialization [invalid_value] - //~| WARN this was previously accepted by the compiler but is being phased out } #[derive(Clone, Copy)] diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs index 76380ebcb6..4674867306 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -7,7 +7,7 @@ const unsafe extern "C" fn closure() -> fn() { || {} } const unsafe extern "C" fn use_float() { 1.0 + 1.0; } //~^ ERROR floating point arithmetic const extern "C" fn ptr_cast(val: *const u8) { val as usize; } -//~^ ERROR casting pointers to integers +//~^ ERROR pointers cannot be cast to integers fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr index 80d234b0e8..2e52bae2b6 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -25,14 +25,14 @@ LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; } = note: see issue #57241 for more information = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable -error[E0658]: casting pointers to integers in constant functions is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/const-extern-fn-min-const-fn.rs:9:48 | LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } | ^^^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-float-classify.rs b/src/test/ui/consts/const-float-classify.rs index 36fec9976b..5d38e032ac 100644 --- a/src/test/ui/consts/const-float-classify.rs +++ b/src/test/ui/consts/const-float-classify.rs @@ -5,7 +5,6 @@ #![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_trait_impl)] -#![allow(incomplete_features)] // Don't promote const fn nop(x: T) -> T { x } @@ -53,6 +52,9 @@ impl const PartialEq for bool { fn eq(&self, _: &NonDet) -> bool { true } + fn ne(&self, _: &NonDet) -> bool { + false + } } // The result of the `is_sign` methods are not checked for correctness, since LLVM does not diff --git a/src/test/ui/consts/const-int-unchecked.rs b/src/test/ui/consts/const-int-unchecked.rs index 2ccc5d27bb..902a668488 100644 --- a/src/test/ui/consts/const-int-unchecked.rs +++ b/src/test/ui/consts/const-int-unchecked.rs @@ -13,186 +13,137 @@ use std::intrinsics; // unsigned types: const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 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 SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 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 SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 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 SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 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 SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 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 // signed types: const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 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 SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 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 SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 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 SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 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 SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 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 // and make sure we capture y < 0: const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -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 SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -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 SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -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 SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -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 SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -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 // and that there's no special relation to the value -1 by picking some // negative values at random: const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; -//~^ 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 SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; -//~^ 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 SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; -//~^ 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 SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; -//~^ 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 SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; -//~^ 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 // Repeat it all over for `unchecked_shr` // unsigned types: const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 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 SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 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 SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 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 SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 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 SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 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 // signed types: const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 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 SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 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 SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 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 SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 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 SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 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 // and make sure we capture y < 0: const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -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 SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -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 SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -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 SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -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 SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -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 // and that there's no special relation to the value -1 by picking some // negative values at random: const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; -//~^ 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 SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; -//~^ 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 SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; -//~^ 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 SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; -//~^ 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 SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; -//~^ 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 // Other arithmetic functions: const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; -//~^ 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 _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; -//~^ 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 _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; -//~^ 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 = unsafe { std::intrinsics::unchecked_div(1, 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 _: i32 = unsafe { std::intrinsics::unchecked_div(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 _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 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 _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) }; -//~^ ERROR any use of this value will cause an error -//~| WARN this was previously accepted by the compiler but is being phased out +//~^ ERROR evaluation of constant value failed // capture fault with zero value const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) }; -//~^ ERROR any use of this value will cause an error -//~| WARN this was previously accepted by the compiler but is being phased out +//~^ ERROR evaluation of constant value failed const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) }; -//~^ ERROR any use of this value will cause an error -//~| WARN this was previously accepted by the compiler but is being phased out +//~^ ERROR evaluation of constant value failed fn main() {} diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr index 999b26543e..22e8c8dabc 100644 --- a/src/test/ui/consts/const-int-unchecked.stderr +++ b/src/test/ui/consts/const-int-unchecked.stderr @@ -1,542 +1,297 @@ -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:15:29 | LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; - | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 8 in `unchecked_shl` - | - = 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 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:18:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:17:31 | LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 16 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:21:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:19:31 | LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 32 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:24:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:21:31 | LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 64 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:27:33 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:23:33 | LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) }; - | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 128 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:33:29 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:28:29 | LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; - | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 8 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:36:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:30:31 | LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 16 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:39:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:32:31 | LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 32 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:42:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:34:31 | LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 64 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:45:33 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:36:33 | LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) }; - | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 128 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:51:33 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:41:33 | LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; - | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 255 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:54:35 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:43:35 | LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 65535 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:57:35 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:45:35 | LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 4294967295 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:60:35 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:47:35 | LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 18446744073709551615 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:63:37 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:49:37 | LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:70:40 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:55:40 | LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; - | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 250 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:73:42 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:57:42 | LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 65523 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:76:42 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:59:42 | LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 4294967271 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:79:42 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:61:42 | LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 18446744073709551586 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:82:44 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:63:44 | LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; - | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:90:29 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:70:29 | LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; - | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 8 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:93:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:72:31 | LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 16 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:96:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:74:31 | LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 32 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:99:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:76:31 | LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 64 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:102:33 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:78:33 | LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) }; - | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 128 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:108:29 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:83:29 | LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; - | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 8 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:111:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:85:31 | LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 16 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:114:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:87:31 | LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 32 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:117:31 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:89:31 | LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) }; - | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 64 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:120:33 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:91:33 | LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) }; - | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 128 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:126:33 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:96:33 | LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; - | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 255 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:129:35 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:98:35 | LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 65535 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:132:35 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:100:35 | LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 4294967295 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:135:35 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:102:35 | LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; - | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 18446744073709551615 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:138:37 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:104:37 | LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) }; - | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:145:40 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:110:40 | LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; - | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 250 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:148:42 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:112:42 | LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 65523 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:151:42 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:114:42 | LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 4294967271 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:154:42 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:116:42 | LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; - | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 18446744073709551586 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:157:44 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:118:44 | LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; - | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:163:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:123:25 | LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflow executing `unchecked_add` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:167:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:126:25 | LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflow executing `unchecked_sub` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:171:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:129:25 | LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflow executing `unchecked_mul` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:175:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:132:25 | LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | dividing by zero - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dividing by zero -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:178:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:134:25 | LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflow executing `unchecked_div` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_div` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:182:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:137:25 | LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | calculating the remainder with a divisor of zero - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calculating the remainder with a divisor of zero -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:185:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:139:25 | LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | overflow executing `unchecked_rem` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_rem` -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:191:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:144:25 | LL | const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | `ctlz_nonzero` called on 0 - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ctlz_nonzero` called on 0 -error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:194:25 +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:146:25 | LL | const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) }; - | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | `cttz_nonzero` called on 0 - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `cttz_nonzero` called on 0 error: aborting due to 49 previous errors +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr new file mode 100644 index 0000000000..a9411fb0e3 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr @@ -0,0 +1,36 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-76510.rs:5:1 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─alloc3──╼ 07 00 00 00 │ ╾──╼.... + } + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr new file mode 100644 index 0000000000..9ad5f20d57 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -0,0 +1,36 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-76510.rs:5:1 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────alloc3────────╼ 07 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs new file mode 100644 index 0000000000..892f6c9811 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs @@ -0,0 +1,18 @@ +// stderr-per-bitwidth + +use std::mem::{transmute, ManuallyDrop}; + +const S: &'static mut str = &mut " hello "; +//~^ ERROR: mutable references are not allowed in the final value of constants +//~| ERROR: mutation through a reference is not allowed in constants +//~| ERROR: cannot borrow data in a `&` reference as mutable +//~| ERROR: it is undefined behavior to use this value + +const fn trigger() -> [(); unsafe { + let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + 0 + }] { + [(); 0] +} + +fn main() {} diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index 638a98130a..24d7bc4914 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -11,8 +11,8 @@ const fn helper() -> Option<&'static mut i32> { unsafe { // Undefined behaviour (integer as pointer), who doesn't love tests like this. // This code never gets executed, because the static checks fail before that. - Some(&mut *(42 as *mut i32)) //~ ERROR any use of this value will cause an error - //~| WARN this was previously accepted by the compiler but is being phased out + Some(&mut *(42 as *mut i32)) //~ ERROR evaluation of constant value failed + //~| 0x2a is not a valid pointer } } // The error is an evaluation error and not a validation error, so the error is reported // directly at the site where it occurs. diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index 6d3d18f6e6..b3fcd6a7fe 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -1,19 +1,14 @@ -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/mut_ref_in_final_dynamic_check.rs:14:10 | LL | Some(&mut *(42 as *mut i32)) | ^^^^^^^^^^^^^^^^^^^^^^ | | - | unable to turn bytes into a pointer + | 0x2a is not a valid pointer | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:14:10 - | inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:19:29 ... LL | const A: Option<&mut i32> = helper(); - | ------------------------------------- - | - = 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 + | -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:19:29 error: encountered dangling pointer in final constant --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1 @@ -23,3 +18,4 @@ LL | const B: Option<&mut i32> = helper2(); 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-points-to-static.32bit.stderr b/src/test/ui/consts/const-points-to-static.32bit.stderr index c582678e2d..78af2c30d0 100644 --- a/src/test/ui/consts/const-points-to-static.32bit.stderr +++ b/src/test/ui/consts/const-points-to-static.32bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc0──╼ │ ╾──╼ + ╾─alloc1──╼ │ ╾──╼ } warning: skipping const checks diff --git a/src/test/ui/consts/const-points-to-static.64bit.stderr b/src/test/ui/consts/const-points-to-static.64bit.stderr index 1112499a3e..f5a0a6b0ad 100644 --- a/src/test/ui/consts/const-points-to-static.64bit.stderr +++ b/src/test/ui/consts/const-points-to-static.64bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc0────────╼ │ ╾──────╼ + ╾───────alloc1────────╼ │ ╾──────╼ } warning: skipping const checks diff --git a/src/test/ui/consts/const-unwrap.rs b/src/test/ui/consts/const-unwrap.rs index 6ed60ed87b..729ae535ce 100644 --- a/src/test/ui/consts/const-unwrap.rs +++ b/src/test/ui/consts/const-unwrap.rs @@ -4,9 +4,8 @@ const FOO: i32 = Some(42i32).unwrap(); -// This causes an error, but it is attributed to the `panic` *inside* `Option::unwrap` (maybe due -// to `track_caller`?). A note points to the originating `const`. -const BAR: i32 = Option::::None.unwrap(); //~ NOTE +const BAR: i32 = Option::::None.unwrap(); +//~^ERROR: evaluation of constant value failed fn main() { println!("{}", FOO); diff --git a/src/test/ui/consts/const-unwrap.stderr b/src/test/ui/consts/const-unwrap.stderr index 95f4711cb6..d2cbe4550f 100644 --- a/src/test/ui/consts/const-unwrap.stderr +++ b/src/test/ui/consts/const-unwrap.stderr @@ -1,19 +1,8 @@ -error[E0080]: any use of this value will cause an error - --> $SRC_DIR/core/src/option.rs:LL:COL - | -LL | None => panic!("called `Option::unwrap()` on a `None` value"), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:9:38 - | inside `Option::::unwrap` at $SRC_DIR/core/src/panic.rs:LL:COL - | inside `BAR` at $DIR/const-unwrap.rs:9:18 - | - ::: $DIR/const-unwrap.rs:9:1 +error[E0080]: evaluation of constant value failed + --> $DIR/const-unwrap.rs:7:18 | LL | const BAR: i32 = Option::::None.unwrap(); - | ---------------------------------------------- - | - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:7:38 error: aborting due to previous error diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.rs b/src/test/ui/consts/const_unsafe_unreachable_ub.rs index 4ae3a88c45..8cee5b5065 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.rs +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.rs @@ -1,5 +1,4 @@ -// build-fail - +// error-pattern: evaluation of constant value failed #![feature(const_unreachable_unchecked)] const unsafe fn foo(x: bool) -> bool { @@ -9,12 +8,8 @@ const unsafe fn foo(x: bool) -> bool { } } -#[warn(const_err)] const BAR: bool = unsafe { foo(false) }; fn main() { assert_eq!(BAR, true); - //~^ ERROR E0080 - //~| ERROR erroneous constant - //~| WARN this was previously accepted by the compiler but is being phased out } diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr index fc7a53e277..ecdd0ca3f5 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr @@ -1,4 +1,4 @@ -warning: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/hint.rs:LL:COL | LL | unsafe { intrinsics::unreachable() } @@ -6,39 +6,15 @@ LL | unsafe { intrinsics::unreachable() } | | | entering unreachable code | inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL - | inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:8:18 - | inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:13:28 | - ::: $DIR/const_unsafe_unreachable_ub.rs:13:1 + ::: $DIR/const_unsafe_unreachable_ub.rs:7:18 | +LL | false => std::hint::unreachable_unchecked(), + | ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:7:18 +... LL | const BAR: bool = unsafe { foo(false) }; - | ---------------------------------------- - | -note: the lint level is defined here - --> $DIR/const_unsafe_unreachable_ub.rs:12: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 - -error[E0080]: evaluation of constant value failed - --> $DIR/const_unsafe_unreachable_ub.rs:16:14 - | -LL | assert_eq!(BAR, true); - | ^^^ referenced constant has errors - -error: erroneous constant used - --> $DIR/const_unsafe_unreachable_ub.rs:16:3 - | -LL | assert_eq!(BAR, true); - | ^^^^^^^^^^^^^^^^^^^^^^ 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 - = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + | ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:11:28 -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/control-flow/assert.const_panic.stderr b/src/test/ui/consts/control-flow/assert.const_panic.stderr index 8e1a2b5eb4..1deaa937ed 100644 --- a/src/test/ui/consts/control-flow/assert.const_panic.stderr +++ b/src/test/ui/consts/control-flow/assert.const_panic.stderr @@ -1,10 +1,8 @@ -error[E0080]: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/assert.rs:10:15 | LL | const _: () = assert!(false); - | --------------^^^^^^^^^^^^^^- - | | - | the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:10:15 + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:10:15 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/control-flow/assert.rs b/src/test/ui/consts/control-flow/assert.rs index 90017fee19..b311cb140c 100644 --- a/src/test/ui/consts/control-flow/assert.rs +++ b/src/test/ui/consts/control-flow/assert.rs @@ -9,6 +9,6 @@ const _: () = assert!(true); const _: () = assert!(false); //[stock]~^ ERROR panicking in constants is unstable -//[const_panic]~^^ ERROR any use of this value will cause an error +//[const_panic]~^^ ERROR evaluation of constant value failed fn main() {} diff --git a/src/test/ui/consts/copy-intrinsic.rs b/src/test/ui/consts/copy-intrinsic.rs new file mode 100644 index 0000000000..124e16e2b2 --- /dev/null +++ b/src/test/ui/consts/copy-intrinsic.rs @@ -0,0 +1,52 @@ +#![stable(feature = "dummy", since = "1.0.0")] + +// ignore-tidy-linelength +#![feature(intrinsics, staged_api)] +#![feature(const_mut_refs, const_intrinsic_copy, const_ptr_offset)] +use std::mem; + +extern "rust-intrinsic" { + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] + fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] + fn copy(src: *const T, dst: *mut T, count: usize); +} + +const COPY_ZERO: () = unsafe { + // Since we are not copying anything, this should be allowed. + let src = (); + let mut dst = (); + copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0); +}; + +const COPY_OOB_1: () = unsafe { + let mut x = 0i32; + let dangle = (&mut x as *mut i32).wrapping_add(10); + // Even if the first ptr is an int ptr and this is a ZST copy, we should detect dangling 2nd ptrs. + copy_nonoverlapping(0x100 as *const i32, dangle, 0); //~ ERROR evaluation of constant value failed [E0080] + //~| pointer at offset 40 is out-of-bounds +}; +const COPY_OOB_2: () = unsafe { + let x = 0i32; + let dangle = (&x as *const i32).wrapping_add(10); + // Even if the second ptr is an int ptr and this is a ZST copy, we should detect dangling 1st ptrs. + copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); //~ ERROR evaluation of constant value failed [E0080] + //~| pointer at offset 40 is out-of-bounds +}; + +const COPY_SIZE_OVERFLOW: () = unsafe { + let x = 0; + let mut y = 0; + copy(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); //~ ERROR evaluation of constant value failed [E0080] + //~| overflow computing total size of `copy` +}; +const COPY_NONOVERLAPPING_SIZE_OVERFLOW: () = unsafe { + let x = 0; + let mut y = 0; + copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); //~ evaluation of constant value failed [E0080] + //~| overflow computing total size of `copy_nonoverlapping` +}; + +fn main() { +} diff --git a/src/test/ui/consts/copy-intrinsic.stderr b/src/test/ui/consts/copy-intrinsic.stderr new file mode 100644 index 0000000000..be41c2db39 --- /dev/null +++ b/src/test/ui/consts/copy-intrinsic.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:27:5 + | +LL | copy_nonoverlapping(0x100 as *const i32, dangle, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer at offset 40 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:34:5 + | +LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc7 has size 4, so pointer at offset 40 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:41:5 + | +LL | copy(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy` + +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:47:5 + | +LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/issue-17458.rs b/src/test/ui/consts/issue-17458.rs index d56ffebad7..44125a1c3d 100644 --- a/src/test/ui/consts/issue-17458.rs +++ b/src/test/ui/consts/issue-17458.rs @@ -1,5 +1,5 @@ static X: usize = unsafe { core::ptr::null::() as usize }; -//~^ ERROR: casting pointers to integers in statics is unstable +//~^ ERROR: pointers cannot be cast to integers during const eval fn main() { assert_eq!(X, 0); diff --git a/src/test/ui/consts/issue-17458.stderr b/src/test/ui/consts/issue-17458.stderr index 68e86ea21b..aab7d798db 100644 --- a/src/test/ui/consts/issue-17458.stderr +++ b/src/test/ui/consts/issue-17458.stderr @@ -1,12 +1,11 @@ -error[E0658]: casting pointers to integers in statics is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/issue-17458.rs:1:28 | LL | static X: usize = unsafe { core::ptr::null::() as usize }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-17756.rs b/src/test/ui/consts/issue-17756.rs similarity index 100% rename from src/test/ui/issues/issue-17756.rs rename to src/test/ui/consts/issue-17756.rs diff --git a/src/test/ui/consts/issue-39161-bogus-error.rs b/src/test/ui/consts/issue-39161-bogus-error.rs new file mode 100644 index 0000000000..a954385da4 --- /dev/null +++ b/src/test/ui/consts/issue-39161-bogus-error.rs @@ -0,0 +1,13 @@ +// check-pass + +pub struct X { + pub a: i32, + pub b: i32, +} + +fn main() { + const DX: X = X { a: 0, b: 0 }; + const _X1: X = X { a: 1, ..DX }; + let _x2 = X { a: 1, b: 2, ..DX }; + const _X3: X = X { a: 1, b: 2, ..DX }; +} diff --git a/src/test/ui/consts/issue-51559.rs b/src/test/ui/consts/issue-51559.rs deleted file mode 100644 index cc644404f7..0000000000 --- a/src/test/ui/consts/issue-51559.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(const_raw_ptr_to_usize_cast)] - -const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut (); -pub const FOO: usize = unsafe { BAR as usize }; -//~^ ERROR any use of this value will cause an error -//~| WARN this was previously accepted by the compiler but is being phased out - -fn main() {} diff --git a/src/test/ui/consts/issue-51559.stderr b/src/test/ui/consts/issue-51559.stderr deleted file mode 100644 index d571eb5496..0000000000 --- a/src/test/ui/consts/issue-51559.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: any use of this value will cause an error - --> $DIR/issue-51559.rs:4:33 - | -LL | pub const FOO: usize = unsafe { BAR as usize }; - | --------------------------------^^^^^^^^^^^^--- - | | - | cannot cast pointer to integer because it was not created by cast from integer - | - = 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 - -error: aborting due to previous error - diff --git a/src/test/ui/consts/issue-52023-array-size-pointer-cast.rs b/src/test/ui/consts/issue-52023-array-size-pointer-cast.rs index cc756ce815..2249d9879f 100644 --- a/src/test/ui/consts/issue-52023-array-size-pointer-cast.rs +++ b/src/test/ui/consts/issue-52023-array-size-pointer-cast.rs @@ -1,3 +1,3 @@ fn main() { - let _ = [0; (&0 as *const i32) as usize]; //~ ERROR casting pointers to integers in constants + let _ = [0; (&0 as *const i32) as usize]; //~ ERROR pointers cannot be cast to integers during const eval } diff --git a/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr index 68b5cbd9bd..363c7b2c8e 100644 --- a/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr +++ b/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr @@ -1,12 +1,11 @@ -error[E0658]: casting pointers to integers in constants is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17 | LL | let _ = [0; (&0 as *const i32) as usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/issue-52432.rs b/src/test/ui/consts/issue-52432.rs deleted file mode 100644 index d719bf1b97..0000000000 --- a/src/test/ui/consts/issue-52432.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(const_raw_ptr_to_usize_cast)] - -fn main() { - [(); &(static |x| {}) as *const _ as usize]; - //~^ ERROR: closures cannot be static - //~| ERROR: type annotations needed - [(); &(static || {}) as *const _ as usize]; - //~^ ERROR: closures cannot be static - //~| ERROR evaluation of constant value failed -} diff --git a/src/test/ui/consts/issue-52432.stderr b/src/test/ui/consts/issue-52432.stderr deleted file mode 100644 index 2999895055..0000000000 --- a/src/test/ui/consts/issue-52432.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0697]: closures cannot be static - --> $DIR/issue-52432.rs:4:12 - | -LL | [(); &(static |x| {}) as *const _ as usize]; - | ^^^^^^^^^^ - -error[E0697]: closures cannot be static - --> $DIR/issue-52432.rs:7:12 - | -LL | [(); &(static || {}) as *const _ as usize]; - | ^^^^^^^^^ - -error[E0282]: type annotations needed - --> $DIR/issue-52432.rs:4:20 - | -LL | [(); &(static |x| {}) as *const _ as usize]; - | ^ consider giving this closure parameter a type - -error[E0080]: evaluation of constant value failed - --> $DIR/issue-52432.rs:7:10 - | -LL | [(); &(static || {}) as *const _ as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot cast pointer to integer because it was not created by cast from integer - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0080, E0282, E0697. -For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/issue-63952.32bit.stderr b/src/test/ui/consts/issue-63952.32bit.stderr index 6d52ed065b..6a6097d5ec 100644 --- a/src/test/ui/consts/issue-63952.32bit.stderr +++ b/src/test/ui/consts/issue-63952.32bit.stderr @@ -12,7 +12,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc3──╼ ff ff ff ff │ ╾──╼.... + ╾─alloc4──╼ ff ff ff ff │ ╾──╼.... } error: aborting due to previous error diff --git a/src/test/ui/consts/issue-63952.64bit.stderr b/src/test/ui/consts/issue-63952.64bit.stderr index 3335c5bf72..6547c3384d 100644 --- a/src/test/ui/consts/issue-63952.64bit.stderr +++ b/src/test/ui/consts/issue-63952.64bit.stderr @@ -12,7 +12,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc3────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + ╾───────alloc4────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ } error: aborting due to previous error diff --git a/src/test/ui/issues/issue-69532.rs b/src/test/ui/consts/issue-69532.rs similarity index 100% rename from src/test/ui/issues/issue-69532.rs rename to src/test/ui/consts/issue-69532.rs diff --git a/src/test/ui/consts/issue-79690.64bit.stderr b/src/test/ui/consts/issue-79690.64bit.stderr index 2639bc4812..bf0ef9e6dc 100644 --- a/src/test/ui/consts/issue-79690.64bit.stderr +++ b/src/test/ui/consts/issue-79690.64bit.stderr @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-79690.rs:30:1 | LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered (potentially part of) a pointer at .1..size.foo, but expected plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .1..size.foo: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc2────────╼ ╾───────alloc3────────╼ │ ╾──────╼╾──────╼ + ╾───────alloc3────────╼ ╾───────alloc6────────╼ │ ╾──────╼╾──────╼ } error: aborting due to previous error diff --git a/src/test/ui/consts/issue-83182.32bit.stderr b/src/test/ui/consts/issue-83182.32bit.stderr index 3352f0e172..a15668d4ec 100644 --- a/src/test/ui/consts/issue-83182.32bit.stderr +++ b/src/test/ui/consts/issue-83182.32bit.stderr @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-83182.rs:5:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer in `str` at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered a pointer in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc3──╼ 01 00 00 00 │ ╾──╼.... + ╾─alloc4──╼ 01 00 00 00 │ ╾──╼.... } error: aborting due to previous error diff --git a/src/test/ui/consts/issue-83182.64bit.stderr b/src/test/ui/consts/issue-83182.64bit.stderr index b757072074..5c3ade7c1d 100644 --- a/src/test/ui/consts/issue-83182.64bit.stderr +++ b/src/test/ui/consts/issue-83182.64bit.stderr @@ -2,11 +2,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-83182.rs:5:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer in `str` at ..0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered a pointer in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc3────────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc4────────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ } error: aborting due to previous error diff --git a/src/test/ui/consts/issue-83182.rs b/src/test/ui/consts/issue-83182.rs index 55a0722e5d..f714fd6e8f 100644 --- a/src/test/ui/consts/issue-83182.rs +++ b/src/test/ui/consts/issue-83182.rs @@ -4,5 +4,5 @@ use std::mem; struct MyStr(str); const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; //~^ ERROR: it is undefined behavior to use this value -//~| type validation failed: encountered a pointer in `str` +//~| type validation failed at ..0: encountered a pointer in `str` fn main() {} diff --git a/src/test/ui/consts/issue-87046.rs b/src/test/ui/consts/issue-87046.rs new file mode 100644 index 0000000000..1f147439f8 --- /dev/null +++ b/src/test/ui/consts/issue-87046.rs @@ -0,0 +1,34 @@ +// Regression test for the ICE described in #87046. + +#![crate_type="lib"] +#![allow(unreachable_patterns)] +#![feature(const_fn_union)] + +#[derive(PartialEq, Eq)] +#[repr(transparent)] +pub struct Username(str); + +pub const ROOT_USER: &Username = Username::from_str("root"); + +impl Username { + pub const fn from_str(raw: &str) -> &Self { + union Transmute<'a> { + raw: &'a str, + typed: &'a Username, + } + + unsafe { Transmute { raw }.typed } + } + + pub const fn as_str(&self) -> &str { + &self.0 + } + + pub fn is_root(&self) -> bool { + match self { + ROOT_USER => true, + //~^ ERROR: cannot use unsized non-slice type `Username` in constant patterns + _ => false, + } + } +} diff --git a/src/test/ui/consts/issue-87046.stderr b/src/test/ui/consts/issue-87046.stderr new file mode 100644 index 0000000000..5da7a9e239 --- /dev/null +++ b/src/test/ui/consts/issue-87046.stderr @@ -0,0 +1,8 @@ +error: cannot use unsized non-slice type `Username` in constant patterns + --> $DIR/issue-87046.rs:29:13 + | +LL | ROOT_USER => true, + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/large_const_alloc.rs b/src/test/ui/consts/large_const_alloc.rs new file mode 100644 index 0000000000..54abaab224 --- /dev/null +++ b/src/test/ui/consts/large_const_alloc.rs @@ -0,0 +1,18 @@ +// only-64bit +// on 32bit and 16bit platforms it is plausible that the maximum allocation size will succeed + +const FOO: () = { + // 128 TiB, unlikely anyone has that much RAM + let x = [0_u8; (1 << 47) - 1]; + //~^ ERROR evaluation of constant value failed +}; + +static FOO2: () = { + let x = [0_u8; (1 << 47) - 1]; + //~^ ERROR could not evaluate static initializer +}; + +fn main() { + let _ = FOO; + let _ = FOO2; +} diff --git a/src/test/ui/consts/large_const_alloc.stderr b/src/test/ui/consts/large_const_alloc.stderr new file mode 100644 index 0000000000..25d660f121 --- /dev/null +++ b/src/test/ui/consts/large_const_alloc.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/large_const_alloc.rs:6:13 + | +LL | let x = [0_u8; (1 << 47) - 1]; + | ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler + +error[E0080]: could not evaluate static initializer + --> $DIR/large_const_alloc.rs:11:13 + | +LL | let x = [0_u8; (1 << 47) - 1]; + | ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler + +error: aborting due to 2 previous errors + +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 b7904e6841..bb525d5719 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 @@ -90,13 +90,13 @@ static BAR: u32 = 42; const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot refer to statics const fn foo30(x: *const u32) -> usize { x as usize } -//~^ ERROR casting pointers to integers +//~^ ERROR pointers cannot be cast to integers const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } -//~^ ERROR casting pointers to integers +//~^ ERROR pointers cannot be cast to integers const fn foo30_2(x: *mut u32) -> usize { x as usize } -//~^ ERROR casting pointers to integers +//~^ ERROR pointers cannot be cast to integers const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } -//~^ ERROR casting pointers to integers +//~^ ERROR pointers cannot be cast to integers const fn foo30_6() -> bool { let x = true; x } const fn inc(x: &mut i32) { *x += 1 } //~^ ERROR 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 d31d412193..fcbf39d386 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -164,41 +164,41 @@ LL | const fn foo26() -> &'static u32 { &BAR } | = help: consider extracting the value of the `static` to a `const`, and referring to that -error[E0658]: casting pointers to integers in constant functions is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/min_const_fn.rs:92:42 | LL | const fn foo30(x: *const u32) -> usize { x as usize } | ^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error[E0658]: casting pointers to integers in constant functions is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/min_const_fn.rs:94:63 | LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } | ^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error[E0658]: casting pointers to integers in constant functions is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/min_const_fn.rs:96:42 | LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } | ^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error[E0658]: casting pointers to integers in constant functions is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/min_const_fn.rs:98:63 | LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } | ^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error[E0658]: mutable references are not allowed in constant functions --> $DIR/min_const_fn.rs:101:14 diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr index 64ebd01226..1a6ed0f43b 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr @@ -10,7 +10,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc0──╼ │ ╾──╼ + ╾─alloc1──╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -25,7 +25,7 @@ LL | | }; | = 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──╼ │ ╾──╼ + ╾─alloc2──╼ │ ╾──╼ } warning: skipping const checks diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr index 4157b313f9..4f268dd905 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr @@ -10,7 +10,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc0────────╼ │ ╾──────╼ + ╾───────alloc1────────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -25,7 +25,7 @@ LL | | }; | = 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────────╼ │ ╾──────╼ + ╾───────alloc2────────╼ │ ╾──────╼ } warning: skipping const checks diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index 583b2ef672..64a1214e8b 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 @@ -9,7 +9,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc0──╼ │ ╾──╼ + ╾─alloc1──╼ │ ╾──╼ } error: could not evaluate constant pattern @@ -29,7 +29,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc0──╼ │ ╾──╼ + ╾─alloc1──╼ │ ╾──╼ } error: could not evaluate constant pattern 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 b381a25a63..66fe4ec076 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 @@ -9,7 +9,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc0────────╼ │ ╾──────╼ + ╾───────alloc1────────╼ │ ╾──────╼ } error: could not evaluate constant pattern @@ -29,7 +29,7 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc0────────╼ │ ╾──────╼ + ╾───────alloc1────────╼ │ ╾──────╼ } error: could not evaluate constant pattern 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 62126ef2ba..9d1bb2ac91 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 @@ -4,22 +4,22 @@ error[E0080]: it is undefined behavior to use this value LL | / const MUH: Meh = Meh { LL | | x: &UnsafeCell::new(42), LL | | }; - | |__^ type validation failed: encountered `UnsafeCell` in a `const` at .x. + | |__^ type validation failed at .x.: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc2──╼ │ ╾──╼ + ╾─alloc3──╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:27:1 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered `UnsafeCell` in a `const` at ...x + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ...x: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾─alloc6──╼ ╾─alloc7──╼ │ ╾──╼╾──╼ + ╾─alloc7──╼ ╾─alloc9──╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -30,7 +30,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾─alloc10─╼ │ ╾──╼ + ╾─alloc11─╼ │ ╾──╼ } warning: skipping const checks 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 606184e573..fe939c0393 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 @@ -4,22 +4,22 @@ error[E0080]: it is undefined behavior to use this value LL | / const MUH: Meh = Meh { LL | | x: &UnsafeCell::new(42), LL | | }; - | |__^ type validation failed: encountered `UnsafeCell` in a `const` at .x. + | |__^ type validation failed at .x.: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc2────────╼ │ ╾──────╼ + ╾───────alloc3────────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:27:1 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered `UnsafeCell` in a `const` at ...x + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ...x: encountered `UnsafeCell` in a `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾───────alloc6────────╼ ╾───────alloc7────────╼ │ ╾──────╼╾──────╼ + ╾───────alloc7────────╼ ╾───────alloc9────────╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -30,7 +30,7 @@ LL | const BLUNT: &mut i32 = &mut 42; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc10───────╼ │ ╾──────╼ + ╾───────alloc11───────╼ │ ╾──────╼ } warning: skipping const checks diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs index aae6d83720..22314160c5 100644 --- a/src/test/ui/consts/miri_unleashed/ptr_arith.rs +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs @@ -8,14 +8,21 @@ static CMP: () = { let x = &0 as *const _; let _v = x == x; //~^ ERROR could not evaluate static initializer - //~| NOTE pointer arithmetic or comparison + //~| "pointer arithmetic or comparison" needs an rfc before being allowed inside constants }; -static INT_PTR_ARITH: () = unsafe { +static PTR_INT_CAST: () = { + let x = &0 as *const _ as usize; + //~^ ERROR could not evaluate static initializer + //~| unable to turn pointer into raw bytes + let _v = x == x; +}; + +static PTR_INT_TRANSMUTE: () = unsafe { let x: usize = std::mem::transmute(&0); let _v = x + 0; //~^ ERROR could not evaluate static initializer - //~| NOTE cannot cast pointer to integer + //~| unable to turn pointer into raw bytes }; fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr index 8ac4aa87f6..2764d10348 100644 --- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr @@ -5,10 +5,16 @@ LL | let _v = x == x; | ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants error[E0080]: could not evaluate static initializer - --> $DIR/ptr_arith.rs:16:14 + --> $DIR/ptr_arith.rs:15:13 + | +LL | let x = &0 as *const _ as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:23:14 | LL | let _v = x + 0; - | ^^^^^ cannot cast pointer to integer because it was not created by cast from integer + | ^^^^^ unable to turn pointer into raw bytes warning: skipping const checks | @@ -17,7 +23,12 @@ help: skipping check that does not even have a feature gate | LL | let _v = x == x; | ^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/ptr_arith.rs:15:13 + | +LL | let x = &0 as *const _ as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/miri_unleashed/tls.stderr b/src/test/ui/consts/miri_unleashed/tls.stderr index 62e2dc7121..30309da499 100644 --- a/src/test/ui/consts/miri_unleashed/tls.stderr +++ b/src/test/ui/consts/miri_unleashed/tls.stderr @@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer --> $DIR/tls.rs:12:25 | LL | unsafe { let _val = A; } - | ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A)) + | ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A)) error[E0080]: could not evaluate static initializer --> $DIR/tls.rs:19:26 | LL | unsafe { let _val = &A; } - | ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A)) + | ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A)) warning: skipping const checks | diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs index b73191d56a..4b55c299b5 100644 --- a/src/test/ui/consts/offset_from_ub.rs +++ b/src/test/ui/consts/offset_from_ub.rs @@ -1,5 +1,8 @@ #![feature(const_raw_ptr_deref)] #![feature(const_ptr_offset_from)] +#![feature(core_intrinsics)] + +use std::intrinsics::ptr_offset_from; #[repr(C)] struct Struct { @@ -8,39 +11,38 @@ struct Struct { } pub const DIFFERENT_ALLOC: usize = { - //~^ NOTE let uninit = std::mem::MaybeUninit::::uninit(); let base_ptr: *const Struct = &uninit as *const _ as *const Struct; let uninit2 = std::mem::MaybeUninit::::uninit(); let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct; - let offset = unsafe { field_ptr.offset_from(base_ptr) }; + let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed + //~| cannot compute offset of pointers into different allocations. offset as usize }; pub const NOT_PTR: usize = { - //~^ NOTE unsafe { (42 as *const u8).offset_from(&5u8) as usize } }; pub const NOT_MULTIPLE_OF_SIZE: isize = { - //~^ NOTE let data = [5u8, 6, 7]; let base_ptr = data.as_ptr(); let field_ptr = &data[1] as *const u8 as *const u16; - unsafe { field_ptr.offset_from(base_ptr as *const u16) } + unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } //~ERROR evaluation of constant value failed + //~| 1_isize cannot be divided by 2_isize without remainder }; pub const OFFSET_FROM_NULL: isize = { - //~^ NOTE let ptr = 0 as *const u8; - unsafe { ptr.offset_from(ptr) } + unsafe { ptr_offset_from(ptr, ptr) } //~ERROR evaluation of constant value failed + //~| null pointer is not a valid pointer }; pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC - //~^ NOTE let ptr1 = 8 as *const u8; let ptr2 = 16 as *const u8; - unsafe { ptr2.offset_from(ptr1) } + unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed + //~| 0x10 is not a valid pointer }; fn main() {} diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index 4254cda2a0..663bfbdade 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -1,117 +1,41 @@ -error: any use of this value will cause an error - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | -LL | unsafe { intrinsics::ptr_offset_from(self, origin) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | ptr_offset_from cannot compute offset of pointers into different allocations. - | inside `ptr::const_ptr::::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:16:27 - | - ::: $DIR/offset_from_ub.rs:10:1 +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:18:27 | -LL | / pub const DIFFERENT_ALLOC: usize = { -LL | | -LL | | let uninit = std::mem::MaybeUninit::::uninit(); -LL | | let base_ptr: *const Struct = &uninit as *const _ as *const Struct; -... | -LL | | offset as usize -LL | | }; - | |__- - | - = note: `#[deny(const_err)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from cannot compute offset of pointers into different allocations. -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | -LL | unsafe { intrinsics::ptr_offset_from(self, origin) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn bytes into a pointer - | inside `ptr::const_ptr::::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `NOT_PTR` at $DIR/offset_from_ub.rs:22:14 +LL | unsafe { intrinsics::ptr_offset_from(self, origin) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | 0x2a is not a valid pointer + | inside `ptr::const_ptr::::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/offset_from_ub.rs:20:1 - | -LL | / pub const NOT_PTR: usize = { -LL | | -LL | | unsafe { (42 as *const u8).offset_from(&5u8) as usize } -LL | | }; - | |__- + ::: $DIR/offset_from_ub.rs:24:14 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize } + | ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14 -error: any use of this value will cause an error - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | -LL | unsafe { intrinsics::ptr_offset_from(self, origin) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | exact_div: 1_isize cannot be divided by 2_isize without remainder - | inside `ptr::const_ptr::::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:30:14 - | - ::: $DIR/offset_from_ub.rs:25:1 - | -LL | / pub const NOT_MULTIPLE_OF_SIZE: isize = { -LL | | -LL | | let data = [5u8, 6, 7]; -LL | | let base_ptr = data.as_ptr(); -LL | | let field_ptr = &data[1] as *const u8 as *const u16; -LL | | unsafe { field_ptr.offset_from(base_ptr as *const u16) } -LL | | }; - | |__- +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:31:14 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder -error: any use of this value will cause an error - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | -LL | unsafe { intrinsics::ptr_offset_from(self, origin) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | null pointer is not a valid pointer for this operation - | inside `ptr::const_ptr::::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:36:14 - | - ::: $DIR/offset_from_ub.rs:33:1 - | -LL | / pub const OFFSET_FROM_NULL: isize = { -LL | | -LL | | let ptr = 0 as *const u8; -LL | | unsafe { ptr.offset_from(ptr) } -LL | | }; - | |__- +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:37:14 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | unsafe { ptr_offset_from(ptr, ptr) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ null pointer is not a valid pointer for this operation -error: any use of this value will cause an error - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | -LL | unsafe { intrinsics::ptr_offset_from(self, origin) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | unable to turn bytes into a pointer - | inside `ptr::const_ptr::::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:43:14 - | - ::: $DIR/offset_from_ub.rs:39:1 - | -LL | / pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC -LL | | -LL | | let ptr1 = 8 as *const u8; -LL | | let ptr2 = 16 as *const u8; -LL | | unsafe { ptr2.offset_from(ptr1) } -LL | | }; - | |__- +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:44:14 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | unsafe { ptr_offset_from(ptr2, ptr1) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0x10 is not a valid pointer error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/offset_ub.rs b/src/test/ui/consts/offset_ub.rs index 7ce45ba9c4..42a285a6ea 100644 --- a/src/test/ui/consts/offset_ub.rs +++ b/src/test/ui/consts/offset_ub.rs @@ -2,6 +2,8 @@ use std::ptr; // normalize-stderr-test "alloc\d+" -> "allocN" +// normalize-stderr-test "0x7f+" -> "0x7f..f" + pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~NOTE pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; //~NOTE @@ -11,6 +13,7 @@ pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; //~NOTE pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; //~NOTE pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; //~NOTE +pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; //~NOTE pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; //~NOTE pub const DANGLING: *const u8 = unsafe { ptr::NonNull::::dangling().as_ptr().offset(4) }; //~NOTE diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr index 45203d3e27..66a2722ed4 100644 --- a/src/test/ui/consts/offset_ub.stderr +++ b/src/test/ui/consts/offset_ub.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/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } @@ -6,54 +6,41 @@ LL | unsafe { intrinsics::offset(self, count) } | | | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `BEFORE_START` at $DIR/offset_ub.rs:6:46 | - ::: $DIR/offset_ub.rs:6:1 + ::: $DIR/offset_ub.rs:8:46 | LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-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 + | ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:8:46 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1 + | pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `AFTER_END` at $DIR/offset_ub.rs:7:43 | - ::: $DIR/offset_ub.rs:7:1 + ::: $DIR/offset_ub.rs:9:43 | LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; - | -------------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:9:43 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100 + | pointer arithmetic failed: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `AFTER_ARRAY` at $DIR/offset_ub.rs:8:45 | - ::: $DIR/offset_ub.rs:8:1 + ::: $DIR/offset_ub.rs:10:45 | LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; - | ------------------------------------------------------------------------------ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:10:45 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } @@ -61,17 +48,13 @@ LL | unsafe { intrinsics::offset(self, count) } | | | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `OVERFLOW` at $DIR/offset_ub.rs:10:43 | - ::: $DIR/offset_ub.rs:10:1 + ::: $DIR/offset_ub.rs:12:43 | LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; - | ---------------------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:12:43 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } @@ -79,17 +62,13 @@ LL | unsafe { intrinsics::offset(self, count) } | | | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `UNDERFLOW` at $DIR/offset_ub.rs:11:44 | - ::: $DIR/offset_ub.rs:11:1 + ::: $DIR/offset_ub.rs:13:44 | LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; - | ----------------------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:13:44 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } @@ -97,17 +76,13 @@ LL | unsafe { intrinsics::offset(self, count) } | | | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:12:56 | - ::: $DIR/offset_ub.rs:12:1 + ::: $DIR/offset_ub.rs:14:56 | LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; - | --------------------------------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:56 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } @@ -115,53 +90,55 @@ LL | unsafe { intrinsics::offset(self, count) } | | | overflowing in-bounds pointer arithmetic | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:57 | - ::: $DIR/offset_ub.rs:13:1 + ::: $DIR/offset_ub.rs:15:57 | LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; - | -------------------------------------------------------------------------------------- + | --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:15:57 + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | +LL | unsafe { intrinsics::offset(self, count) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds + | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + ::: $DIR/offset_ub.rs:16:49 | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; + | ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:16:49 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0 + | pointer arithmetic failed: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:15:50 | - ::: $DIR/offset_ub.rs:15:1 + ::: $DIR/offset_ub.rs:18:50 | LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(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 + | --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:18:50 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) as *mut T } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | unable to turn bytes into a pointer + | 0x1 is not a valid pointer | inside `ptr::mut_ptr::::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - | inside `DANGLING` at $DIR/offset_ub.rs:16:42 | - ::: $DIR/offset_ub.rs:16:1 + ::: $DIR/offset_ub.rs:19:42 | LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::::dangling().as_ptr().offset(4) }; - | --------------------------------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:19:42 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } @@ -169,33 +146,26 @@ LL | unsafe { intrinsics::offset(self, count) } | | | pointer arithmetic failed: 0x0 is not a valid pointer | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:19:50 | - ::: $DIR/offset_ub.rs:19:1 + ::: $DIR/offset_ub.rs:22:50 | LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::().offset(0) }; - | ------------------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:22:50 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | unable to turn bytes into a pointer + | 0x7f..f is not a valid pointer | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:22:47 | - ::: $DIR/offset_ub.rs:22:1 + ::: $DIR/offset_ub.rs:25:47 | LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) }; - | --------------------------------------------------------------------------------------------- - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 + | -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:25:47 -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs index 0306a55af4..9b5fd18f81 100644 --- a/src/test/ui/consts/ptr_comparisons.rs +++ b/src/test/ui/consts/ptr_comparisons.rs @@ -1,6 +1,6 @@ // compile-flags: --crate-type=lib -// normalize-stderr-32bit: "offset 8" -> "offset $$TWO_WORDS" -// normalize-stderr-64bit: "offset 16" -> "offset $$TWO_WORDS" +// normalize-stderr-32bit: "8 bytes" -> "$$TWO_WORDS bytes" +// normalize-stderr-64bit: "16 bytes" -> "$$TWO_WORDS bytes" // normalize-stderr-32bit: "size 4" -> "size $$WORD" // normalize-stderr-64bit: "size 8" -> "size $$WORD" @@ -62,15 +62,15 @@ const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; const _: *const u8 = unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; -//~^ 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 +//~| out-of-bounds const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; //~^ ERROR any use of this value will cause an error -//~| cannot cast pointer to integer +//~| 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 -//~| cannot cast pointer to integer +//~| 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 943de47879..6ae24c179f 100644 --- a/src/test/ui/consts/ptr_comparisons.stderr +++ b/src/test/ui/consts/ptr_comparisons.stderr @@ -1,33 +1,22 @@ -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | LL | unsafe { intrinsics::offset(self, count) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | pointer arithmetic failed: pointer must be in-bounds at offset $TWO_WORDS, but is outside bounds of alloc2 which has size $WORD + | pointer arithmetic failed: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds | inside `ptr::const_ptr::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | inside `_` at $DIR/ptr_comparisons.rs:61:34 | - ::: $DIR/ptr_comparisons.rs:61:1 + ::: $DIR/ptr_comparisons.rs:61:34 | LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - | ------------------------------------------------------------------- - | - = 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 + | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:61:34 -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/ptr_comparisons.rs:64:33 | -LL | / const _: *const u8 = -LL | | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; - | |_________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___- - | | - | memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 +LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds error: any use of this value will cause an error --> $DIR/ptr_comparisons.rs:68:27 @@ -35,8 +24,9 @@ error: any use of this value will cause an error LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | cannot cast pointer to integer because it was not created by cast from integer + | 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 @@ -46,10 +36,11 @@ error: any use of this value will cause an error LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | cannot cast pointer to integer because it was not created by cast from integer + | 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 error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/rustc-const-stability-require-const.rs b/src/test/ui/consts/rustc-const-stability-require-const.rs new file mode 100644 index 0000000000..4fb259b335 --- /dev/null +++ b/src/test/ui/consts/rustc-const-stability-require-const.rs @@ -0,0 +1,47 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "foo", since = "1.0.0")] + +#[stable(feature = "foo", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_foo", issue = "none")] +pub fn foo() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + +#[stable(feature = "bar", since = "1.0.0")] +#[rustc_const_stable(feature = "const_bar", since = "1.0.0")] +pub fn bar() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + +#[stable(feature = "potato", since = "1.0.0")] +pub struct Potato; + +impl Potato { + #[stable(feature = "salad", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_salad", issue = "none")] + pub fn salad(&self) -> &'static str { "mmmmmm" } + //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + + #[stable(feature = "roasted", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_roasted", issue = "none")] + pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" } + //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` +} + +#[stable(feature = "bar", since = "1.0.0")] +#[rustc_const_stable(feature = "const_bar", since = "1.0.0")] +pub extern "C" fn bar_c() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + +#[stable(feature = "foo", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_foo", issue = "none")] +pub extern "C" fn foo_c() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + + +#[stable(feature = "foobar", since = "1.0.0")] +#[rustc_const_unstable(feature = "foobar_const", issue = "none")] +pub const fn foobar() {} + +#[stable(feature = "barfoo", since = "1.0.0")] +#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")] +pub const fn barfoo() {} diff --git a/src/test/ui/consts/rustc-const-stability-require-const.stderr b/src/test/ui/consts/rustc-const-stability-require-const.stderr new file mode 100644 index 0000000000..1027b9311b --- /dev/null +++ b/src/test/ui/consts/rustc-const-stability-require-const.stderr @@ -0,0 +1,86 @@ +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")] + | -------------------------------------------------------------- attribute specified here +LL | pub fn foo() {} + | ^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:7:1 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:12:1 + | +LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")] + | ------------------------------------------------------------- attribute specified here +LL | pub fn bar() {} + | ^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:12:1 + | +LL | pub fn bar() {} + | ^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:21:5 + | +LL | #[rustc_const_unstable(feature = "const_salad", issue = "none")] + | ---------------------------------------------------------------- attribute specified here +LL | pub fn salad(&self) -> &'static str { "mmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:21:5 + | +LL | pub fn salad(&self) -> &'static str { "mmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:26:5 + | +LL | #[rustc_const_unstable(feature = "const_roasted", issue = "none")] + | ------------------------------------------------------------------ attribute specified here +LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:26:5 + | +LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:32:1 + | +LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")] + | ------------------------------------------------------------- attribute specified here +LL | pub extern "C" fn bar_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:32:1 + | +LL | pub extern "C" fn bar_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:37:1 + | +LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")] + | -------------------------------------------------------------- attribute specified here +LL | pub extern "C" fn foo_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:37:1 + | +LL | pub extern "C" fn foo_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/consts/rustc-impl-const-stability.rs b/src/test/ui/consts/rustc-impl-const-stability.rs new file mode 100644 index 0000000000..e3fda57548 --- /dev/null +++ b/src/test/ui/consts/rustc-impl-const-stability.rs @@ -0,0 +1,20 @@ +// build-pass + +#![crate_type = "lib"] +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![stable(feature = "foo", since = "1.0.0")] + + +#[stable(feature = "potato", since = "1.27.0")] +pub struct Data { + _data: u128 +} + +#[stable(feature = "potato", since = "1.27.0")] +impl const Default for Data { + #[rustc_const_unstable(feature = "data_foo", issue = "none")] + fn default() -> Data { + Data { _data: 42 } + } +} diff --git a/src/test/ui/consts/std/alloc.32bit.stderr b/src/test/ui/consts/std/alloc.32bit.stderr index bb9ccbba37..67bc3202c1 100644 --- a/src/test/ui/consts/std/alloc.32bit.stderr +++ b/src/test/ui/consts/std/alloc.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc.rs:8:1 | LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .align_: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/std/alloc.64bit.stderr b/src/test/ui/consts/std/alloc.64bit.stderr index 2c891b1d79..ec89dec272 100644 --- a/src/test/ui/consts/std/alloc.64bit.stderr +++ b/src/test/ui/consts/std/alloc.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/alloc.rs:8:1 | LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .align_: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/consts/validate_never_arrays.32bit.stderr b/src/test/ui/consts/validate_never_arrays.32bit.stderr index 2d1bba391e..e2f5175bf0 100644 --- a/src/test/ui/consts/validate_never_arrays.32bit.stderr +++ b/src/test/ui/consts/validate_never_arrays.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:4:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered a value of the never type `!` | = 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) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:8:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { diff --git a/src/test/ui/consts/validate_never_arrays.64bit.stderr b/src/test/ui/consts/validate_never_arrays.64bit.stderr index dd677f1b21..c145eddef5 100644 --- a/src/test/ui/consts/validate_never_arrays.64bit.stderr +++ b/src/test/ui/consts/validate_never_arrays.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:4:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered a value of the never type `!` | = 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) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:8:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .[0]: encountered a value of the never type `!` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { diff --git a/src/test/ui/crate-loading/auxiliary/proc-macro.rs b/src/test/ui/crate-loading/auxiliary/proc-macro.rs new file mode 100644 index 0000000000..52631de575 --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/proc-macro.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_name = "reproduction"] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn mac(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui/crate-loading/cross-compiled-proc-macro.rs b/src/test/ui/crate-loading/cross-compiled-proc-macro.rs new file mode 100644 index 0000000000..c1f4331438 --- /dev/null +++ b/src/test/ui/crate-loading/cross-compiled-proc-macro.rs @@ -0,0 +1,8 @@ +// edition:2018 +// compile-flags:--extern reproduction +// aux-build:proc-macro.rs +// check-pass + +reproduction::mac!(); + +fn main() {} diff --git a/src/test/ui/crate-loading/missing-std.rs b/src/test/ui/crate-loading/missing-std.rs index 442a7c01e5..de4ccc1856 100644 --- a/src/test/ui/crate-loading/missing-std.rs +++ b/src/test/ui/crate-loading/missing-std.rs @@ -1,4 +1,5 @@ // compile-flags: --target x86_64-unknown-uefi +// needs-llvm-components: x86 // rustc-env:CARGO=/usr/bin/cargo // rustc-env:RUSTUP_HOME=/home/bors/.rustup #![no_core] diff --git a/src/test/ui/crate-loading/missing-std.stderr b/src/test/ui/crate-loading/missing-std.stderr index 25808efdfa..e61486fdc6 100644 --- a/src/test/ui/crate-loading/missing-std.stderr +++ b/src/test/ui/crate-loading/missing-std.stderr @@ -1,5 +1,5 @@ error[E0463]: can't find crate for `core` - --> $DIR/missing-std.rs:5:1 + --> $DIR/missing-std.rs:6:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ can't find crate diff --git a/src/test/ui/custom_test_frameworks/mismatch.stderr b/src/test/ui/custom_test_frameworks/mismatch.stderr index 8967a7c6d3..e848ddc55b 100644 --- a/src/test/ui/custom_test_frameworks/mismatch.stderr +++ b/src/test/ui/custom_test_frameworks/mismatch.stderr @@ -1,6 +1,8 @@ error[E0277]: the trait bound `TestDescAndFn: Testable` is not satisfied --> $DIR/mismatch.rs:9:1 | +LL | #[test] + | ------- in this procedural macro expansion LL | fn wrong_kind(){} | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn` | diff --git a/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr deleted file mode 100644 index 7f6a432d5a..0000000000 --- a/src/test/ui/deduplicate-diagnostics-2.deduplicate.stderr +++ /dev/null @@ -1,30 +0,0 @@ -warning: floating-point types cannot be used in patterns - --> $DIR/deduplicate-diagnostics-2.rs:7:9 - | -LL | 1.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 - -warning: floating-point types cannot be used in patterns - --> $DIR/deduplicate-diagnostics-2.rs:11:9 - | -LL | 2.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 - -warning: floating-point types cannot be used in patterns - --> $DIR/deduplicate-diagnostics-2.rs:7:9 - | -LL | 1.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 - -warning: 3 warnings emitted - diff --git a/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr b/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr deleted file mode 100644 index f2315bc91e..0000000000 --- a/src/test/ui/deduplicate-diagnostics-2.duplicate.stderr +++ /dev/null @@ -1,39 +0,0 @@ -warning: floating-point types cannot be used in patterns - --> $DIR/deduplicate-diagnostics-2.rs:7:9 - | -LL | 1.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 - -warning: floating-point types cannot be used in patterns - --> $DIR/deduplicate-diagnostics-2.rs:11:9 - | -LL | 2.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 - -warning: floating-point types cannot be used in patterns - --> $DIR/deduplicate-diagnostics-2.rs:7:9 - | -LL | 1.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 - -warning: floating-point types cannot be used in patterns - --> $DIR/deduplicate-diagnostics-2.rs:11:9 - | -LL | 2.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 - -warning: 4 warnings emitted - diff --git a/src/test/ui/deduplicate-diagnostics-2.rs b/src/test/ui/deduplicate-diagnostics-2.rs deleted file mode 100644 index f46a7c0c1c..0000000000 --- a/src/test/ui/deduplicate-diagnostics-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// build-pass -// revisions: duplicate deduplicate -//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes - -fn main() { - match 0.0 { - 1.0 => {} //~ WARNING floating-point types cannot be used in patterns - //~| WARNING this was previously accepted - //~| WARNING floating-point types cannot be used in patterns - //~| WARNING this was previously accepted - 2.0 => {} //~ WARNING floating-point types cannot be used in patterns - //~| WARNING this was previously accepted - //[duplicate]~| WARNING floating-point types cannot be used in patterns - //[duplicate]~| WARNING this was previously accepted - _ => {} - } -} diff --git a/src/test/ui/deprecation/deprecation-lint-3.stderr b/src/test/ui/deprecation/deprecation-lint-3.stderr index c33ad1519b..f499ff85e5 100644 --- a/src/test/ui/deprecation/deprecation-lint-3.stderr +++ b/src/test/ui/deprecation/deprecation-lint-3.stderr @@ -1,15 +1,14 @@ error: use of deprecated function `deprecation_lint::deprecated_text`: text - --> $DIR/deprecation-lint-3.rs:13:5 + --> $DIR/deprecation-lint-3.rs:13:28 | LL | macro_test_arg_nested!(deprecated_text); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/deprecation-lint-3.rs:4:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ - = note: this error originates in the macro `macro_test_arg_nested` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr index 3699a939e2..20af4f62e6 100644 --- a/src/test/ui/deprecation/deprecation-lint.stderr +++ b/src/test/ui/deprecation/deprecation-lint.stderr @@ -11,16 +11,16 @@ LL | #![deny(deprecated)] | ^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:21:9 + --> $DIR/deprecation-lint.rs:21:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:23:9 + --> $DIR/deprecation-lint.rs:23:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_text`: text --> $DIR/deprecation-lint.rs:25:9 @@ -29,16 +29,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:30:9 + --> $DIR/deprecation-lint.rs:30:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:32:9 + --> $DIR/deprecation-lint.rs:32:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text --> $DIR/deprecation-lint.rs:34:17 @@ -53,10 +53,10 @@ LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:40:17 + --> $DIR/deprecation-lint.rs:40:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text --> $DIR/deprecation-lint.rs:42:17 @@ -65,28 +65,28 @@ LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:44:17 + --> $DIR/deprecation-lint.rs:44:25 | LL | let _ = nested::DeprecatedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:48:17 + --> $DIR/deprecation-lint.rs:48:25 | LL | let _ = nested::DeprecatedUnitStruct; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:50:17 + --> $DIR/deprecation-lint.rs:50:31 | LL | ... let _ = nested::Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:52:17 + --> $DIR/deprecation-lint.rs:52:25 | LL | ... let _ = nested::DeprecatedTupleStruct (1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_text`: text --> $DIR/deprecation-lint.rs:59:25 @@ -101,28 +101,28 @@ LL | macro_test_arg!(macro_test_arg!(deprecated_text())); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:65:9 + --> $DIR/deprecation-lint.rs:65:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:67:9 + --> $DIR/deprecation-lint.rs:67:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:69:9 + --> $DIR/deprecation-lint.rs:69:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:71:9 + --> $DIR/deprecation-lint.rs:71:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text --> $DIR/deprecation-lint.rs:81:10 @@ -173,10 +173,10 @@ LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text - --> $DIR/deprecation-lint.rs:162:9 + --> $DIR/deprecation-lint.rs:162:25 | LL | deprecated_mod::deprecated(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated`: text --> $DIR/deprecation-lint.rs:245:9 @@ -185,16 +185,16 @@ LL | deprecated(); | ^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:250:9 + --> $DIR/deprecation-lint.rs:250:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:252:9 + --> $DIR/deprecation-lint.rs:252:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_text`: text --> $DIR/deprecation-lint.rs:254:9 @@ -203,16 +203,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:259:9 + --> $DIR/deprecation-lint.rs:259:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:261:9 + --> $DIR/deprecation-lint.rs:261:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_future`: text --> $DIR/deprecation-lint.rs:264:9 @@ -239,10 +239,10 @@ LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:274:17 + --> $DIR/deprecation-lint.rs:274:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text --> $DIR/deprecation-lint.rs:276:17 @@ -251,52 +251,52 @@ LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text - --> $DIR/deprecation-lint.rs:278:17 + --> $DIR/deprecation-lint.rs:278:25 | LL | let _ = nested::DeprecatedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text - --> $DIR/deprecation-lint.rs:283:17 + --> $DIR/deprecation-lint.rs:283:25 | LL | let _ = nested::DeprecatedUnitStruct; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text - --> $DIR/deprecation-lint.rs:285:17 + --> $DIR/deprecation-lint.rs:285:31 | LL | ... let _ = nested::Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text - --> $DIR/deprecation-lint.rs:287:17 + --> $DIR/deprecation-lint.rs:287:25 | LL | ... let _ = nested::DeprecatedTupleStruct (1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:292:9 + --> $DIR/deprecation-lint.rs:292:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/deprecation-lint.rs:294:9 + --> $DIR/deprecation-lint.rs:294:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:296:9 + --> $DIR/deprecation-lint.rs:296:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/deprecation-lint.rs:298:9 + --> $DIR/deprecation-lint.rs:298:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar` --> $DIR/deprecation-lint.rs:316:13 diff --git a/src/test/ui/deprecation/suggestion.fixed b/src/test/ui/deprecation/suggestion.fixed index eba72f88a8..7d66222788 100644 --- a/src/test/ui/deprecation/suggestion.fixed +++ b/src/test/ui/deprecation/suggestion.fixed @@ -21,8 +21,22 @@ impl Foo { fn replacement(&self) {} } +mod bar { + #[rustc_deprecated( + since = "1.0.0", + reason = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + pub fn deprecated() {} + + pub fn replacement() {} +} + fn main() { let foo = Foo; foo.replacement(); //~ ERROR use of deprecated + + bar::replacement(); //~ ERROR use of deprecated } diff --git a/src/test/ui/deprecation/suggestion.rs b/src/test/ui/deprecation/suggestion.rs index 8f9791c13e..b34dc0eb83 100644 --- a/src/test/ui/deprecation/suggestion.rs +++ b/src/test/ui/deprecation/suggestion.rs @@ -21,8 +21,22 @@ impl Foo { fn replacement(&self) {} } +mod bar { + #[rustc_deprecated( + since = "1.0.0", + reason = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + pub fn deprecated() {} + + pub fn replacement() {} +} + fn main() { let foo = Foo; foo.deprecated(); //~ ERROR use of deprecated + + bar::deprecated(); //~ ERROR use of deprecated } diff --git a/src/test/ui/deprecation/suggestion.stderr b/src/test/ui/deprecation/suggestion.stderr index 8a7cb1def9..7d78b22224 100644 --- a/src/test/ui/deprecation/suggestion.stderr +++ b/src/test/ui/deprecation/suggestion.stderr @@ -1,8 +1,8 @@ -error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement` - --> $DIR/suggestion.rs:27:9 +error: use of deprecated function `bar::deprecated`: replaced by `replacement` + --> $DIR/suggestion.rs:41:10 | -LL | foo.deprecated(); - | ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement` +LL | bar::deprecated(); + | ^^^^^^^^^^ help: replace the use of the deprecated function: `replacement` | note: the lint level is defined here --> $DIR/suggestion.rs:7:9 @@ -10,5 +10,11 @@ note: the lint level is defined here LL | #![deny(deprecated)] | ^^^^^^^^^^ -error: aborting due to previous error +error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement` + --> $DIR/suggestion.rs:39:9 + | +LL | foo.deprecated(); + | ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement` + +error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs b/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs index b847000a81..7e579ec22d 100644 --- a/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs +++ b/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs @@ -1,6 +1,6 @@ trait Foo { #[derive(Clone)] - //~^ ERROR `derive` may only be applied to structs, enums and unions + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s type Bar; } @@ -8,7 +8,7 @@ struct Bar; impl Bar { #[derive(Clone)] - //~^ ERROR `derive` may only be applied to structs, enums and unions + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s fn bar(&self) {} } diff --git a/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr b/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr index e892d3f086..1fd97bdd5e 100644 --- a/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr +++ b/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr @@ -1,14 +1,20 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/derive-on-trait-item-or-impl-item.rs:2:5 | LL | #[derive(Clone)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | type Bar; + | --------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/derive-on-trait-item-or-impl-item.rs:10:5 | LL | #[derive(Clone)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | fn bar(&self) {} + | ---------------- not a `struct`, `enum` or `union` error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr index 3d62bd8e8e..c5bc50e407 100644 --- a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Clone` is not satisfied --> $DIR/derives-span-Clone-enum-struct-variant.rs:9:6 | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | - = note: required by `clone` +note: required by `clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Clone-enum.stderr b/src/test/ui/derives/derives-span-Clone-enum.stderr index c855ec8e99..a6dc818eb6 100644 --- a/src/test/ui/derives/derives-span-Clone-enum.stderr +++ b/src/test/ui/derives/derives-span-Clone-enum.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Clone` is not satisfied --> $DIR/derives-span-Clone-enum.rs:9:6 | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +... LL | Error | ^^^^^ the trait `Clone` is not implemented for `Error` | - = note: required by `clone` +note: required by `clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Clone-struct.stderr b/src/test/ui/derives/derives-span-Clone-struct.stderr index 522ec9719e..cf7b9ec276 100644 --- a/src/test/ui/derives/derives-span-Clone-struct.stderr +++ b/src/test/ui/derives/derives-span-Clone-struct.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Clone` is not satisfied --> $DIR/derives-span-Clone-struct.rs:8:5 | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | - = note: required by `clone` +note: required by `clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr index b1f3e72f0d..80733d6273 100644 --- a/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Clone` is not satisfied --> $DIR/derives-span-Clone-tuple-struct.rs:8:5 | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ the trait `Clone` is not implemented for `Error` | - = note: required by `clone` +note: required by `clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr index 2151335992..bdcbbf0c75 100644 --- a/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr @@ -1,13 +1,14 @@ error[E0277]: `Error` doesn't implement `Debug` --> $DIR/derives-span-Debug-enum-struct-variant.rs:9:6 | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ `Error` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `Error` - = note: add `#[derive(Debug)]` or manually implement `Debug` - = note: required because of the requirements on the impl of `Debug` for `&Error` - = note: required for the cast to the object type `dyn Debug` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Debug-enum.stderr b/src/test/ui/derives/derives-span-Debug-enum.stderr index 99e618b40e..4ffb75935a 100644 --- a/src/test/ui/derives/derives-span-Debug-enum.stderr +++ b/src/test/ui/derives/derives-span-Debug-enum.stderr @@ -1,13 +1,14 @@ error[E0277]: `Error` doesn't implement `Debug` --> $DIR/derives-span-Debug-enum.rs:9:6 | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +... LL | Error | ^^^^^ `Error` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `Error` - = note: add `#[derive(Debug)]` or manually implement `Debug` - = note: required because of the requirements on the impl of `Debug` for `&Error` - = note: required for the cast to the object type `dyn Debug` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Debug-struct.stderr b/src/test/ui/derives/derives-span-Debug-struct.stderr index 0086642c55..74d2460bb6 100644 --- a/src/test/ui/derives/derives-span-Debug-struct.stderr +++ b/src/test/ui/derives/derives-span-Debug-struct.stderr @@ -1,13 +1,14 @@ error[E0277]: `Error` doesn't implement `Debug` --> $DIR/derives-span-Debug-struct.rs:8:5 | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ `Error` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `Error` - = note: add `#[derive(Debug)]` or manually implement `Debug` - = note: required because of the requirements on the impl of `Debug` for `&Error` - = note: required for the cast to the object type `dyn Debug` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr b/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr index 0b74908d1e..34ddb4e594 100644 --- a/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr @@ -1,13 +1,14 @@ error[E0277]: `Error` doesn't implement `Debug` --> $DIR/derives-span-Debug-tuple-struct.rs:8:5 | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ `Error` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `Error` - = note: add `#[derive(Debug)]` or manually implement `Debug` - = note: required because of the requirements on the impl of `Debug` for `&Error` - = note: required for the cast to the object type `dyn Debug` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Default-struct.stderr b/src/test/ui/derives/derives-span-Default-struct.stderr index b4cf1119ee..c60b6ac456 100644 --- a/src/test/ui/derives/derives-span-Default-struct.stderr +++ b/src/test/ui/derives/derives-span-Default-struct.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Default` is not satisfied --> $DIR/derives-span-Default-struct.rs:8:5 | +LL | #[derive(Default)] + | ------- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Default` is not implemented for `Error` | - = note: required by `std::default::Default::default` +note: required by `std::default::Default::default` + --> $SRC_DIR/core/src/default.rs:LL:COL + | +LL | fn default() -> Self; + | ^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Default-tuple-struct.stderr b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr index 62661a659b..ed342f539d 100644 --- a/src/test/ui/derives/derives-span-Default-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Default` is not satisfied --> $DIR/derives-span-Default-tuple-struct.rs:8:5 | +LL | #[derive(Default)] + | ------- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ the trait `Default` is not implemented for `Error` | - = note: required by `std::default::Default::default` +note: required by `std::default::Default::default` + --> $SRC_DIR/core/src/default.rs:LL:COL + | +LL | fn default() -> Self; + | ^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr index b14f2f8f07..0a76405382 100644 --- a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Eq` is not satisfied --> $DIR/derives-span-Eq-enum-struct-variant.rs:9:6 | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ the trait `Eq` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Eq-enum.stderr b/src/test/ui/derives/derives-span-Eq-enum.stderr index ed7e6936f5..c17e2c518a 100644 --- a/src/test/ui/derives/derives-span-Eq-enum.stderr +++ b/src/test/ui/derives/derives-span-Eq-enum.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Eq` is not satisfied --> $DIR/derives-span-Eq-enum.rs:9:6 | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +... LL | Error | ^^^^^ the trait `Eq` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Eq-struct.stderr b/src/test/ui/derives/derives-span-Eq-struct.stderr index ec26c56172..7a7640b40f 100644 --- a/src/test/ui/derives/derives-span-Eq-struct.stderr +++ b/src/test/ui/derives/derives-span-Eq-struct.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Eq` is not satisfied --> $DIR/derives-span-Eq-struct.rs:8:5 | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Eq` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr index a41acfbf5b..35932986b0 100644 --- a/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Eq` is not satisfied --> $DIR/derives-span-Eq-tuple-struct.rs:8:5 | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ the trait `Eq` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr index fef7b8f75a..4616dadbe6 100644 --- a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Hash` is not satisfied --> $DIR/derives-span-Hash-enum-struct-variant.rs:9:6 | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Hash-enum.stderr b/src/test/ui/derives/derives-span-Hash-enum.stderr index 90c5f91af9..ffc7f7bb7d 100644 --- a/src/test/ui/derives/derives-span-Hash-enum.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Hash` is not satisfied --> $DIR/derives-span-Hash-enum.rs:8:6 | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +... LL | Error | ^^^^^ the trait `Hash` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Hash-struct.stderr b/src/test/ui/derives/derives-span-Hash-struct.stderr index b48828f439..14aebb4faa 100644 --- a/src/test/ui/derives/derives-span-Hash-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-struct.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Hash` is not satisfied --> $DIR/derives-span-Hash-struct.rs:8:5 | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr index 3db0299192..50139dc3f0 100644 --- a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `Error: Hash` is not satisfied --> $DIR/derives-span-Hash-tuple-struct.rs:8:5 | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ the trait `Hash` is not implemented for `Error` | diff --git a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr index 9f77122286..1e1cd715e6 100644 --- a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Ord` is not satisfied --> $DIR/derives-span-Ord-enum-struct-variant.rs:9:6 | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Ord-enum.stderr b/src/test/ui/derives/derives-span-Ord-enum.stderr index f5d2dd3dae..43abe9a954 100644 --- a/src/test/ui/derives/derives-span-Ord-enum.stderr +++ b/src/test/ui/derives/derives-span-Ord-enum.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Ord` is not satisfied --> $DIR/derives-span-Ord-enum.rs:9:6 | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +... LL | Error | ^^^^^ the trait `Ord` is not implemented for `Error` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Ord-struct.stderr b/src/test/ui/derives/derives-span-Ord-struct.stderr index 7a61ca4831..44f6bab08c 100644 --- a/src/test/ui/derives/derives-span-Ord-struct.stderr +++ b/src/test/ui/derives/derives-span-Ord-struct.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Ord` is not satisfied --> $DIR/derives-span-Ord-struct.rs:8:5 | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr index cd67d9ce98..e604018245 100644 --- a/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `Error: Ord` is not satisfied --> $DIR/derives-span-Ord-tuple-struct.rs:8:5 | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ the trait `Ord` is not implemented for `Error` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr index a579d69570..abcba6da8a 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr @@ -1,6 +1,9 @@ error[E0369]: binary operation `==` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ | @@ -10,6 +13,9 @@ LL | x: Error error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ | diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.stderr b/src/test/ui/derives/derives-span-PartialEq-enum.stderr index 532430729c..cdb40c39f1 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum.stderr @@ -1,6 +1,9 @@ error[E0369]: binary operation `==` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-enum.rs:9:6 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +... LL | Error | ^^^^^ | @@ -10,6 +13,9 @@ LL | Error error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-enum.rs:9:6 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +... LL | Error | ^^^^^ | diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-struct.stderr index 5fec402dcd..4cf8851a09 100644 --- a/src/test/ui/derives/derives-span-PartialEq-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-struct.stderr @@ -1,6 +1,9 @@ error[E0369]: binary operation `==` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-struct.rs:8:5 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ | @@ -10,6 +13,9 @@ LL | x: Error error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-struct.rs:8:5 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ | diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr index 0a7f9e1485..66bc168735 100644 --- a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr @@ -1,6 +1,9 @@ error[E0369]: binary operation `==` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ | @@ -10,6 +13,9 @@ LL | Error error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ | diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr index 8d84b1217b..9a716048e2 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr @@ -1,11 +1,18 @@ error[E0277]: can't compare `Error` with `Error` --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:9:6 | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +... LL | x: Error | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr index ce12727989..c726d33eab 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr @@ -1,11 +1,18 @@ error[E0277]: can't compare `Error` with `Error` --> $DIR/derives-span-PartialOrd-enum.rs:9:6 | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +... LL | Error | ^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr index fc488e734f..a56c163ca7 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr @@ -1,11 +1,18 @@ error[E0277]: can't compare `Error` with `Error` --> $DIR/derives-span-PartialOrd-struct.rs:8:5 | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +LL | struct Struct { LL | x: Error | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr index e18b039f21..7a0a52e582 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr @@ -1,11 +1,18 @@ error[E0277]: can't compare `Error` with `Error` --> $DIR/derives-span-PartialOrd-tuple-struct.rs:8:5 | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +LL | struct Struct( LL | Error | ^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr index 4919bac526..09611555fb 100644 --- a/src/test/ui/derives/deriving-copyclone.stderr +++ b/src/test/ui/derives/deriving-copyclone.stderr @@ -10,7 +10,12 @@ LL | is_copy(B { a: 1, b: C }); | expected an implementor of trait `Copy` | help: consider borrowing here: `&B { a: 1, b: C }` | - = note: required because of the requirements on the impl of `Copy` for `B` +note: required because of the requirements on the impl of `Copy` for `B` + --> $DIR/deriving-copyclone.rs:9:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `C: Clone` is not satisfied --> $DIR/deriving-copyclone.rs:32:14 @@ -24,7 +29,12 @@ LL | is_clone(B { a: 1, b: C }); | expected an implementor of trait `Clone` | help: consider borrowing here: `&B { a: 1, b: C }` | - = note: required because of the requirements on the impl of `Clone` for `B` +note: required because of the requirements on the impl of `Clone` for `B` + --> $DIR/deriving-copyclone.rs:9:16 + | +LL | #[derive(Copy, Clone)] + | ^^^^^ + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `D: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:35:13 @@ -38,7 +48,12 @@ LL | is_copy(B { a: 1, b: D }); | expected an implementor of trait `Copy` | help: consider borrowing here: `&B { a: 1, b: D }` | - = note: required because of the requirements on the impl of `Copy` for `B` +note: required because of the requirements on the impl of `Copy` for `B` + --> $DIR/deriving-copyclone.rs:9:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr index 0f69f94bf3..b97f87da4b 100644 --- a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr +++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr @@ -1,6 +1,9 @@ error[E0369]: binary operation `==` cannot be applied to type `NoCloneOrEq` --> $DIR/deriving-no-inner-impl-error-message.rs:5:5 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct E { LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ | @@ -10,6 +13,9 @@ LL | x: NoCloneOrEq error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq` --> $DIR/deriving-no-inner-impl-error-message.rs:5:5 | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct E { LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ | @@ -19,10 +25,17 @@ LL | x: NoCloneOrEq error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied --> $DIR/deriving-no-inner-impl-error-message.rs:10:5 | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct C { LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq` | - = note: required by `clone` +note: required by `clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/test/ui/derives/deriving-non-type.rs b/src/test/ui/derives/deriving-non-type.rs index 7e14c12c0a..9afffa9008 100644 --- a/src/test/ui/derives/deriving-non-type.rs +++ b/src/test/ui/derives/deriving-non-type.rs @@ -2,29 +2,29 @@ struct S; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s trait T { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s impl S { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s impl T for S { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s static s: usize = 0; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s const c: usize = 0; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s mod m { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s extern "C" { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s type A = usize; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s fn main() { } diff --git a/src/test/ui/derives/deriving-non-type.stderr b/src/test/ui/derives/deriving-non-type.stderr index 8c9daf4d4b..ef7ef54d1a 100644 --- a/src/test/ui/derives/deriving-non-type.stderr +++ b/src/test/ui/derives/deriving-non-type.stderr @@ -1,56 +1,74 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:5:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | trait T { } + | ----------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:8:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | impl S { } + | ---------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:11:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | impl T for S { } + | ---------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:14:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | static s: usize = 0; + | -------------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:17:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | const c: usize = 0; + | ------------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:20:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | mod m { } + | --------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:23:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | extern "C" { } + | -------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:26:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | type A = usize; + | --------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/deriving-non-type.rs:29:1 | LL | #[derive(PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | fn main() { } + | ------------- not a `struct`, `enum` or `union` error: aborting due to 9 previous errors diff --git a/src/test/ui/deriving/deriving-with-helper.rs b/src/test/ui/deriving/deriving-with-helper.rs new file mode 100644 index 0000000000..ea74a15624 --- /dev/null +++ b/src/test/ui/deriving/deriving-with-helper.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: --crate-type=lib + +#![feature(decl_macro)] +#![feature(lang_items)] +#![feature(no_core)] +#![feature(rustc_attrs)] + +#![no_core] + +#[rustc_builtin_macro] +macro derive() {} + +#[rustc_builtin_macro(Default, attributes(default))] +macro Default() {} + +mod default { + pub trait Default { + fn default() -> Self; + } + + impl Default for u8 { + fn default() -> u8 { + 0 + } + } +} + +#[lang = "sized"] +trait Sized {} + +#[derive(Default)] +struct S { + #[default] // OK + field: u8, +} diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index 99ebe84cd9..1b6bcfbb9f 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -16,7 +16,7 @@ type D = (u8, u8)::AssocTy; type E = _::AssocTy; //~^ ERROR missing angle brackets in associated item path -//~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases type F = &'static (u8)::AssocTy; //~^ ERROR missing angle brackets in associated item path @@ -47,37 +47,37 @@ type I = ty!()::AssocTy; trait K {} fn foo>(x: X) {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn bar(_: F) where F: Fn() -> _ {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn baz _>(_: F) {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions struct L(F) where F: Fn() -> _; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs struct M where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs a: F, } enum N where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for enums Foo(F), } union O where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for unions foo: F, } trait P where F: Fn() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for traits } trait Q { fn foo(_: F) where F: Fn() -> _ {} - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions } fn main() {} 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 fc5f218c04..8db9652b1e 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -81,7 +81,7 @@ error[E0223]: ambiguous associated type LL | type D = (u8, u8)::AssocTy; | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases --> $DIR/bad-assoc-ty.rs:17:10 | LL | type E = _::AssocTy; @@ -122,7 +122,7 @@ error[E0223]: ambiguous associated type LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:49:13 | LL | fn foo>(x: X) {} @@ -135,7 +135,7 @@ help: use type parameters instead LL | fn foo, T>(x: X) {} | ^ ^ ^^^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:52:34 | LL | fn bar(_: F) where F: Fn() -> _ {} @@ -146,7 +146,7 @@ help: use type parameters instead LL | fn bar(_: F) where F: Fn() -> T {} | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:55:19 | LL | fn baz _>(_: F) {} @@ -157,7 +157,7 @@ help: use type parameters instead LL | fn baz T, T>(_: F) {} | ^^^^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs --> $DIR/bad-assoc-ty.rs:58:33 | LL | struct L(F) where F: Fn() -> _; @@ -168,7 +168,7 @@ help: use type parameters instead LL | struct L(F) where F: Fn() -> T; | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs --> $DIR/bad-assoc-ty.rs:60:30 | LL | struct M where F: Fn() -> _ { @@ -179,7 +179,7 @@ help: use type parameters instead LL | struct M where F: Fn() -> T { | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for enums --> $DIR/bad-assoc-ty.rs:64:28 | LL | enum N where F: Fn() -> _ { @@ -190,7 +190,7 @@ help: use type parameters instead LL | enum N where F: Fn() -> T { | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for unions --> $DIR/bad-assoc-ty.rs:69:29 | LL | union O where F: Fn() -> _ { @@ -201,7 +201,7 @@ help: use type parameters instead LL | union O where F: Fn() -> T { | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for traits --> $DIR/bad-assoc-ty.rs:74:29 | LL | trait P where F: Fn() -> _ { @@ -212,7 +212,7 @@ help: use type parameters instead LL | trait P where F: Fn() -> T { | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:79:38 | LL | fn foo(_: F) where F: Fn() -> _ {} diff --git a/src/test/ui/did_you_mean/issue-39544.rs b/src/test/ui/did_you_mean/issue-39544.rs index 3c86f29a89..a19d3f7047 100644 --- a/src/test/ui/did_you_mean/issue-39544.rs +++ b/src/test/ui/did_you_mean/issue-39544.rs @@ -46,5 +46,5 @@ pub fn with_tuple() { let mut y = 0; let x = (&y,); *x.0 = 1; - //~^ ERROR cannot assign to `*x.0` which is behind a `&` reference + //~^ ERROR cannot assign to `*x.0`, which is behind a `&` reference } diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index ce0d697238..68180eaee0 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -90,7 +90,7 @@ LL | let _ = &mut z.x; LL | let _ = &mut w.x; | ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable -error[E0594]: cannot assign to `*x.0` which is behind a `&` reference +error[E0594]: cannot assign to `*x.0`, which is behind a `&` reference --> $DIR/issue-39544.rs:48:5 | LL | *x.0 = 1; diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index 1bd4543f23..fcb4ea1d59 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -1,9 +1,6 @@ error[E0277]: the trait bound `i8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:24:21 | -LL | fn bar(&self){} - | ------------- required by `Foo::bar` -... LL | Foo::::bar(&1i8); | ^^^^ the trait `Foo` is not implemented for `i8` | @@ -13,13 +10,15 @@ LL | Foo::::bar(&1i8); > > > +note: required by `Foo::bar` + --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 + | +LL | fn bar(&self){} + | ^^^^^^^^^^^^^ error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 | -LL | fn bar(&self){} - | ------------- required by `Foo::bar` -... LL | Foo::::bar(&1u8); | ^^^^ the trait `Foo` is not implemented for `u8` | @@ -28,13 +27,15 @@ LL | Foo::::bar(&1u8); > > > +note: required by `Foo::bar` + --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 + | +LL | fn bar(&self){} + | ^^^^^^^^^^^^^ error[E0277]: the trait bound `bool: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 | -LL | fn bar(&self){} - | ------------- required by `Foo::bar` -... LL | Foo::::bar(&true); | ^^^^^ the trait `Foo` is not implemented for `bool` | @@ -44,6 +45,11 @@ LL | Foo::::bar(&true); > > and 2 others +note: required by `Foo::bar` + --> $DIR/issue-39802-show-5-trait-impls.rs:2:5 + | +LL | fn bar(&self){} + | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/dyn-drop/dyn-drop.rs b/src/test/ui/dyn-drop/dyn-drop.rs new file mode 100644 index 0000000000..e1668a3f18 --- /dev/null +++ b/src/test/ui/dyn-drop/dyn-drop.rs @@ -0,0 +1,16 @@ +#![deny(dyn_drop)] +#![allow(bare_trait_objects)] +fn foo(_: Box) {} //~ ERROR +fn bar(_: &dyn Drop) {} //~ERROR +fn baz(_: *mut Drop) {} //~ ERROR +struct Foo { + _x: Box //~ ERROR +} +trait Bar { + type T: ?Sized; +} +struct Baz {} +impl Bar for Baz { + type T = dyn Drop; //~ ERROR +} +fn main() {} diff --git a/src/test/ui/dyn-drop/dyn-drop.stderr b/src/test/ui/dyn-drop/dyn-drop.stderr new file mode 100644 index 0000000000..1b1dbc4d12 --- /dev/null +++ b/src/test/ui/dyn-drop/dyn-drop.stderr @@ -0,0 +1,38 @@ +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/dyn-drop.rs:3:19 + | +LL | fn foo(_: Box) {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/dyn-drop.rs:1:9 + | +LL | #![deny(dyn_drop)] + | ^^^^^^^^ + +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/dyn-drop.rs:4:16 + | +LL | fn bar(_: &dyn Drop) {} + | ^^^^ + +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/dyn-drop.rs:5:16 + | +LL | fn baz(_: *mut Drop) {} + | ^^^^ + +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/dyn-drop.rs:7:15 + | +LL | _x: Box + | ^^^^ + +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/dyn-drop.rs:14:16 + | +LL | type T = dyn Drop; + | ^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed index 003736208e..c815080fc4 100644 --- a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed +++ b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed @@ -3,7 +3,8 @@ // to detect or fix uses of `dyn` under a macro. Since we are testing // this file via `rustfix`, we want the rustfix output to be // compilable; so the macros here carefully use `dyn` "correctly." - +// +// edition:2015 // run-rustfix #![allow(non_camel_case_types)] @@ -12,27 +13,27 @@ mod outer_mod { pub mod r#dyn { //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition pub struct r#dyn; //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition } } use outer_mod::r#dyn::r#dyn; //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition fn main() { match r#dyn { r#dyn => {} } //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition macro_defn::r#dyn(); //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition macro_defn::boxed(); } @@ -42,7 +43,7 @@ mod macro_defn { macro_rules! r#dyn { //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition // Note that we do not lint nor fix occurrences under macros ($dyn:tt) => { (Box, Box<$dyn Trait>) } @@ -50,23 +51,23 @@ mod macro_defn { pub fn r#dyn() -> ::outer_mod::r#dyn::r#dyn { //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition ::outer_mod::r#dyn::r#dyn //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition } pub fn boxed() -> r#dyn!( //~^ ERROR `dyn` is a keyword - //~| WARN was previously accepted + //~| WARN this is accepted in the current edition // Note that we do not lint nor fix occurrences under macros dyn diff --git a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs index 0e5c39fc50..6cdc707149 100644 --- a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs +++ b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs @@ -3,7 +3,8 @@ // to detect or fix uses of `dyn` under a macro. Since we are testing // this file via `rustfix`, we want the rustfix output to be // compilable; so the macros here carefully use `dyn` "correctly." - +// +// edition:2015 // run-rustfix #![allow(non_camel_case_types)] @@ -12,27 +13,27 @@ mod outer_mod { pub mod dyn { //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition pub struct dyn; //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition } } use outer_mod::dyn::dyn; //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition fn main() { match dyn { dyn => {} } //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition macro_defn::dyn(); //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition macro_defn::boxed(); } @@ -42,7 +43,7 @@ mod macro_defn { macro_rules! dyn { //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition // Note that we do not lint nor fix occurrences under macros ($dyn:tt) => { (Box, Box<$dyn Trait>) } @@ -50,23 +51,23 @@ mod macro_defn { pub fn dyn() -> ::outer_mod::dyn::dyn { //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition ::outer_mod::dyn::dyn //~^ ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition //~| ERROR `dyn` is a keyword -//~| WARN was previously accepted +//~| WARN this is accepted in the current edition } pub fn boxed() -> dyn!( //~^ ERROR `dyn` is a keyword - //~| WARN was previously accepted + //~| WARN this is accepted in the current edition // Note that we do not lint nor fix occurrences under macros dyn 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 32f06b62bb..3eb5bb7b26 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 @@ -1,132 +1,132 @@ error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:13:13 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:14:13 | LL | pub mod dyn { | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | note: the lint level is defined here - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:10:9 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:11:9 | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:16:20 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:17:20 | LL | pub struct dyn; | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:16 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:22:16 | LL | use outer_mod::dyn::dyn; | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:21:21 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:22:21 | LL | use outer_mod::dyn::dyn; | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:11 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:29:11 | LL | match dyn { dyn => {} } | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:28:17 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:29:17 | LL | match dyn { dyn => {} } | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:33:17 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:34:17 | LL | macro_defn::dyn(); | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:43:18 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:44:18 | LL | macro_rules! dyn { | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:12 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:12 | LL | pub fn dyn() -> ::outer_mod::dyn::dyn { | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:34 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:34 | LL | pub fn dyn() -> ::outer_mod::dyn::dyn { | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:51:39 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:39 | LL | pub fn dyn() -> ::outer_mod::dyn::dyn { | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:22 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:59:22 | LL | ::outer_mod::dyn::dyn | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:58:27 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:59:27 | LL | ::outer_mod::dyn::dyn | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `dyn` is a keyword in the 2018 edition - --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:67:23 + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:68:23 | LL | pub fn boxed() -> dyn!( | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 14 previous errors diff --git a/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs b/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs index cf14aef790..bda2ed17ec 100644 --- a/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs +++ b/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs @@ -1,11 +1,12 @@ -// build-pass (FIXME(62277): could be check-pass?) - // Under the 2015 edition with the keyword_idents lint, `dyn` is // not entirely acceptable as an identifier. // // We currently do not attempt to detect or fix uses of `dyn` as an // identifier under a macro, including under the declarative `macro` // forms from macros 1.2 and macros 2.0. +// +// check-pass +// edition:2015 #![feature(decl_macro)] #![allow(non_camel_case_types)] diff --git a/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs b/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs index 0d85b87dee..472f6b5c8e 100644 --- a/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs +++ b/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs @@ -1,10 +1,11 @@ -// build-pass (FIXME(62277): could be check-pass?) - // Under the 2015 edition with the keyword_idents lint, `dyn` is // not entirely acceptable as an identifier. // // We currently do not attempt to detect or fix uses of `dyn` as an // identifier under a macro. +// +// check-pass +// edition:2015 #![allow(non_camel_case_types)] #![deny(keyword_idents)] diff --git a/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs b/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs index 2a8b6b2483..d6a33c08d1 100644 --- a/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs +++ b/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs @@ -1,7 +1,8 @@ // Under the 2015 edition without the keyword_idents lint, `dyn` is // entirely acceptable as an identifier. - -// build-pass (FIXME(62277): could be check-pass?) +// +// check-pass +// edition:2015 #![allow(non_camel_case_types)] diff --git a/src/test/ui/dyn-keyword/dyn-2018-edition-lint.rs b/src/test/ui/dyn-keyword/dyn-2018-edition-lint.rs index 7c2babaf7a..23ca36b71e 100644 --- a/src/test/ui/dyn-keyword/dyn-2018-edition-lint.rs +++ b/src/test/ui/dyn-keyword/dyn-2018-edition-lint.rs @@ -3,12 +3,12 @@ fn function(x: &SomeTrait, y: Box) { //~^ ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition let _x: &SomeTrait = todo!(); //~^ ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition } trait SomeTrait {} 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 ea73e56d84..30f09e2279 100644 --- a/src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr +++ b/src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #[deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: trait objects without an explicit `dyn` are deprecated @@ -18,7 +18,7 @@ error: trait objects without an explicit `dyn` are deprecated LL | fn function(x: &SomeTrait, y: Box) { | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: trait objects without an explicit `dyn` are deprecated @@ -27,7 +27,7 @@ error: trait objects without an explicit `dyn` are deprecated LL | let _x: &SomeTrait = todo!(); | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: aborting due to 3 previous errors diff --git a/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs b/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs index 4cb9bd1975..59e7f9a608 100644 --- a/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs +++ b/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs @@ -1,5 +1,6 @@ // check-pass - +// edition:2015 +// // rust-lang/rust#56327: Some occurrences of `dyn` within a macro are // not instances of identifiers, and thus should *not* be caught by the // keyword_ident lint. @@ -9,6 +10,7 @@ // anything. #![deny(rust_2018_compatibility)] +#![allow(dyn_drop)] macro_rules! foo { () => { diff --git a/src/test/ui/dynamically-sized-types/dst-index.rs b/src/test/ui/dynamically-sized-types/dst-index.rs index 980d99a6d6..8aa65bbfdc 100644 --- a/src/test/ui/dynamically-sized-types/dst-index.rs +++ b/src/test/ui/dynamically-sized-types/dst-index.rs @@ -29,6 +29,6 @@ impl Index for T { fn main() { assert_eq!(&S[0], "hello"); - &T[0]; + let _ = &T[0]; // let x = &x as &Debug; } diff --git a/src/test/ui/editions/edition-feature-ok.rs b/src/test/ui/editions/edition-feature-ok.rs index 1264213269..69242fd715 100644 --- a/src/test/ui/editions/edition-feature-ok.rs +++ b/src/test/ui/editions/edition-feature-ok.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(rust_2018_preview)] diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs index 310bff21d1..3fffb30c61 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // edition:2018 // compile-flags:--extern edition_imports_2015 // aux-build:edition-imports-2015.rs diff --git a/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs index 9c3beb1ce5..b2695bea5c 100644 --- a/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs @@ -1,6 +1,6 @@ // edition:2015 // aux-build:edition-kw-macro-2015.rs -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(keyword_idents)] diff --git a/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs index 619e6424db..707d8e95c1 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs @@ -1,6 +1,6 @@ // edition:2018 // aux-build:edition-kw-macro-2015.rs -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![allow(keyword_idents)] diff --git a/src/test/ui/editions/edition-raw-pointer-method-2015.rs b/src/test/ui/editions/edition-raw-pointer-method-2015.rs index 3631415fc5..fcfe493c1a 100644 --- a/src/test/ui/editions/edition-raw-pointer-method-2015.rs +++ b/src/test/ui/editions/edition-raw-pointer-method-2015.rs @@ -8,5 +8,5 @@ fn main() { let y = &x as *const _; let _ = y.is_null(); //~^ error: type annotations needed [tyvar_behind_raw_pointer] - //~^^ warning: this was previously accepted + //~^^ warning: this is accepted in the current edition } 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 1df582ee06..417daf36fc 100644 --- a/src/test/ui/editions/edition-raw-pointer-method-2015.stderr +++ b/src/test/ui/editions/edition-raw-pointer-method-2015.stderr @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(tyvar_behind_raw_pointer)]` implied by `#[deny(warnings)]` - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to previous error diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs index 559f10de10..d8553815b7 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs @@ -1,12 +1,14 @@ #![feature(imported_main)] -#![feature(min_type_alias_impl_trait, impl_trait_in_bindings)] +#![feature(min_type_alias_impl_trait)] #![allow(incomplete_features)] //~^^^ ERROR `main` function not found in crate pub mod foo { type MainFn = impl Fn(); + //~^ ERROR could not find defining uses fn bar() {} pub const BAR: MainFn = bar; + //~^ ERROR mismatched types [E0308] } use foo::BAR as main; diff --git a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr index 9b879fc09f..c4c0afc568 100644 --- a/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr +++ b/src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -2,7 +2,7 @@ error[E0601]: `main` function not found in crate `imported_main_const_fn_item_ty --> $DIR/imported_main_const_fn_item_type_forbidden.rs:1:1 | LL | / #![feature(imported_main)] -LL | | #![feature(min_type_alias_impl_trait, impl_trait_in_bindings)] +LL | | #![feature(min_type_alias_impl_trait)] LL | | #![allow(incomplete_features)] LL | | ... | @@ -12,6 +12,25 @@ LL | | use foo::BAR as main; | | | non-function item at `crate::main` is found -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/imported_main_const_fn_item_type_forbidden.rs:10:29 + | +LL | type MainFn = impl Fn(); + | --------- the expected opaque type +... +LL | pub const BAR: MainFn = bar; + | ^^^ expected opaque type, found fn item + | + = note: expected opaque type `impl Fn<()>` + found fn item `fn() {bar}` + +error: could not find defining uses + --> $DIR/imported_main_const_fn_item_type_forbidden.rs:6:19 + | +LL | type MainFn = impl Fn(); + | ^^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0601`. +Some errors have detailed explanations: E0308, E0601. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index eb68a6298d..cead9776e4 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/E0038.rs:5:16 + --> $DIR/E0038.rs:5:20 | LL | fn call_foo(x: Box) { - | ^^^^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` cannot be made into an object | = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/error-codes/E0121.rs b/src/test/ui/error-codes/E0121.rs index f8b4d61b32..98cd6d54c1 100644 --- a/src/test/ui/error-codes/E0121.rs +++ b/src/test/ui/error-codes/E0121.rs @@ -2,5 +2,4 @@ fn foo() -> _ { 5 } //~ ERROR E0121 static BAR: _ = "test"; //~ ERROR E0121 -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index 246f69558f..cc0c2df72e 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/E0121.rs:1:13 | LL | fn foo() -> _ { 5 } @@ -7,7 +7,7 @@ LL | fn foo() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/E0121.rs:3:13 | LL | static BAR: _ = "test"; diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index 2f0dfb6dd8..b6078e3023 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -1,13 +1,15 @@ error[E0283]: type annotations needed --> $DIR/E0283.rs:30:21 | -LL | fn create() -> u32; - | ------------------- required by `Generator::create` -... LL | let cont: u32 = Generator::create(); | ^^^^^^^^^^^^^^^^^ cannot infer type | = note: cannot satisfy `_: Generator` +note: required by `Generator::create` + --> $DIR/E0283.rs:2:5 + | +LL | fn create() -> u32; + | ^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/E0283.rs:35:24 diff --git a/src/test/ui/error-codes/E0389.rs b/src/test/ui/error-codes/E0389.rs index 9dab2c3092..41172b362f 100644 --- a/src/test/ui/error-codes/E0389.rs +++ b/src/test/ui/error-codes/E0389.rs @@ -5,6 +5,6 @@ struct FancyNum { fn main() { let mut fancy = FancyNum{ num: 5 }; let fancy_ref = &(&mut fancy); - fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num` which is behind a `&` reference + fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num`, which is behind a `&` reference println!("{}", fancy_ref.num); } diff --git a/src/test/ui/error-codes/E0389.stderr b/src/test/ui/error-codes/E0389.stderr index c47750b6f4..3d615bd932 100644 --- a/src/test/ui/error-codes/E0389.stderr +++ b/src/test/ui/error-codes/E0389.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference +error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference --> $DIR/E0389.rs:8:5 | LL | let fancy_ref = &(&mut fancy); diff --git a/src/test/ui/error-codes/E0396-fixed.rs b/src/test/ui/error-codes/E0396-fixed.rs index 76dd857ea5..654b21f05b 100644 --- a/src/test/ui/error-codes/E0396-fixed.rs +++ b/src/test/ui/error-codes/E0396-fixed.rs @@ -3,8 +3,7 @@ const REG_ADDR: *const u8 = 0x5f3759df as *const u8; const VALUE: u8 = unsafe { *REG_ADDR }; -//~^ 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/error-codes/E0396-fixed.stderr b/src/test/ui/error-codes/E0396-fixed.stderr index 521394bdc8..91997fcf0f 100644 --- a/src/test/ui/error-codes/E0396-fixed.stderr +++ b/src/test/ui/error-codes/E0396-fixed.stderr @@ -1,14 +1,9 @@ -error: any use of this value will cause an error +error[E0080]: evaluation of constant value failed --> $DIR/E0396-fixed.rs:5:28 | LL | const VALUE: u8 = unsafe { *REG_ADDR }; - | ---------------------------^^^^^^^^^--- - | | - | unable to turn bytes into a pointer - | - = 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 + | ^^^^^^^^^ 0x5f3759df is not a valid pointer error: aborting due to previous error +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/error-codes/E0565.rs b/src/test/ui/error-codes/E0565.rs index 3bf4286761..df76f6b13a 100644 --- a/src/test/ui/error-codes/E0565.rs +++ b/src/test/ui/error-codes/E0565.rs @@ -1,6 +1,5 @@ // repr currently doesn't support literals #[repr("C")] //~ ERROR E0565 - //~| ERROR E0565 -struct A { } +struct A {} -fn main() { } +fn main() {} diff --git a/src/test/ui/error-codes/E0565.stderr b/src/test/ui/error-codes/E0565.stderr index aa0951528e..6ed90c0ae4 100644 --- a/src/test/ui/error-codes/E0565.stderr +++ b/src/test/ui/error-codes/E0565.stderr @@ -4,12 +4,6 @@ error[E0565]: meta item in `repr` must be an identifier LL | #[repr("C")] | ^^^ -error[E0565]: meta item in `repr` must be an identifier - --> $DIR/E0565.rs:2:8 - | -LL | #[repr("C")] - | ^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0565`. diff --git a/src/test/ui/error-codes/E0624.stderr b/src/test/ui/error-codes/E0624.stderr index 1d3336fb18..e59b8a8ae3 100644 --- a/src/test/ui/error-codes/E0624.stderr +++ b/src/test/ui/error-codes/E0624.stderr @@ -1,6 +1,9 @@ error[E0624]: associated function `method` is private --> $DIR/E0624.rs:11:9 | +LL | fn method(&self) {} + | ---------------- private associated function defined here +... LL | foo.method(); | ^^^^^^ private associated function diff --git a/src/test/ui/error-codes/E0777.stderr b/src/test/ui/error-codes/E0777.stderr index ea73c58993..14697d89e8 100644 --- a/src/test/ui/error-codes/E0777.stderr +++ b/src/test/ui/error-codes/E0777.stderr @@ -2,7 +2,7 @@ error[E0777]: expected path to a trait, found literal --> $DIR/E0777.rs:1:10 | LL | #[derive("Clone")] - | ^^^^^^^ + | ^^^^^^^ not a trait | = help: try using `#[derive(Clone)]` @@ -12,7 +12,7 @@ error[E0777]: expected path to a trait, found literal LL | #[derive("Clone | __________^ LL | | ")] - | |_^ + | |_^ not a trait | = help: for example, write `#[derive(Debug)]` for `Debug` diff --git a/src/test/ui/explore-issue-38412.stderr b/src/test/ui/explore-issue-38412.stderr index 55f43840b9..f4a2330da1 100644 --- a/src/test/ui/explore-issue-38412.stderr +++ b/src/test/ui/explore-issue-38412.stderr @@ -84,18 +84,33 @@ error[E0624]: associated function `pub_crate` is private | LL | r.pub_crate(); | ^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:114:9 + | +LL | pub(crate) fn pub_crate(&self) -> i32 { self.d_priv } + | ------------------------------------- private associated function defined here error[E0624]: associated function `pub_mod` is private --> $DIR/explore-issue-38412.rs:51:7 | LL | r.pub_mod(); | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:116:9 + | +LL | pub(in m) fn pub_mod(&self) -> i32 { self.d_priv } + | ---------------------------------- private associated function defined here error[E0624]: associated function `private` is private --> $DIR/explore-issue-38412.rs:52:7 | LL | r.private(); | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:118:9 + | +LL | fn private(&self) -> i32 { self.d_priv } + | ------------------------ private associated function defined here error[E0658]: use of unstable library feature 'unstable_undeclared' --> $DIR/explore-issue-38412.rs:57:7 @@ -120,18 +135,33 @@ error[E0624]: associated function `pub_crate` is private | LL | t.pub_crate(); | ^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:129:9 + | +LL | pub(crate) fn pub_crate(&self) -> i32 { self.0 } + | ------------------------------------- private associated function defined here error[E0624]: associated function `pub_mod` is private --> $DIR/explore-issue-38412.rs:64:7 | LL | t.pub_mod(); | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:130:9 + | +LL | pub(in m) fn pub_mod(&self) -> i32 { self.0 } + | ---------------------------------- private associated function defined here error[E0624]: associated function `private` is private --> $DIR/explore-issue-38412.rs:65:7 | LL | t.private(); | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:131:9 + | +LL | fn private(&self) -> i32 { self.0 } + | ------------------------ private associated function defined here error: aborting due to 19 previous errors diff --git a/src/test/ui/extern/extern-main-issue-86110.rs b/src/test/ui/extern/extern-main-issue-86110.rs new file mode 100644 index 0000000000..83af7a14cc --- /dev/null +++ b/src/test/ui/extern/extern-main-issue-86110.rs @@ -0,0 +1,7 @@ +// missing and missing2 exist to make sure that the error only happens on a `main` declaration +extern "C" { + fn missing(); + fn main(); + //~^ the `main` function cannot be declared in an `extern` block + fn missing2(); +} diff --git a/src/test/ui/extern/extern-main-issue-86110.stderr b/src/test/ui/extern/extern-main-issue-86110.stderr new file mode 100644 index 0000000000..cd3de227dc --- /dev/null +++ b/src/test/ui/extern/extern-main-issue-86110.stderr @@ -0,0 +1,8 @@ +error: the `main` function cannot be declared in an `extern` block + --> $DIR/extern-main-issue-86110.rs:4:5 + | +LL | fn main(); + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/extern/extern-methods.rs b/src/test/ui/extern/extern-methods.rs index 97559a6844..3909b5301a 100644 --- a/src/test/ui/extern/extern-methods.rs +++ b/src/test/ui/extern/extern-methods.rs @@ -1,7 +1,5 @@ // run-pass -// ignore-arm -// ignore-aarch64 -// ignore-riscv64 fastcall isn't supported +// only-i686 trait A { extern "fastcall" fn test1(i: i32); diff --git a/src/test/ui/extern/extern-thiscall.rs b/src/test/ui/extern/extern-thiscall.rs index c6ff8a4320..8ce94aa71a 100644 --- a/src/test/ui/extern/extern-thiscall.rs +++ b/src/test/ui/extern/extern-thiscall.rs @@ -1,7 +1,5 @@ // run-pass -// ignore-arm -// ignore-aarch64 -// ignore-riscv64 thiscall isn't supported +// only-i686 #![feature(abi_thiscall)] diff --git a/src/test/ui/extern/extern-types-distinct-types.stderr b/src/test/ui/extern/extern-types-distinct-types.stderr index 32b45ee10a..f69629232a 100644 --- a/src/test/ui/extern/extern-types-distinct-types.stderr +++ b/src/test/ui/extern/extern-types-distinct-types.stderr @@ -6,6 +6,8 @@ LL | type A; LL | type B; | ------- the expected foreign type ... +LL | fn foo(r: &A) -> &B { + | -- expected `&B` because of return type LL | r | ^ expected extern type `B`, found extern type `A` | diff --git a/src/test/ui/extern/extern-vectorcall.rs b/src/test/ui/extern/extern-vectorcall.rs index da50c3fb92..f625eb0890 100644 --- a/src/test/ui/extern/extern-vectorcall.rs +++ b/src/test/ui/extern/extern-vectorcall.rs @@ -1,7 +1,7 @@ // run-pass -// ignore-arm -// ignore-aarch64 -// ignore-riscv64 vectorcall isn't supported +// revisions: x64 x32 +// [x64]only-x86_64 +// [x32]only-i686 #![feature(abi_vectorcall)] diff --git a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs index 0d7df8182c..05461297af 100644 --- a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs +++ b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs @@ -1,9 +1,51 @@ +// needs-llvm-components: avr +// compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + // Test that the AVR interrupt ABI cannot be used when avr_interrupt // feature gate is not used. -extern "avr-interrupt" fn foo() {} -//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change +extern "avr-non-blocking-interrupt" fn fu() {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +extern "avr-interrupt" fn f() {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + +trait T { + extern "avr-interrupt" fn m(); + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn mu(); + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + + extern "avr-interrupt" fn dm() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn dmu() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +} + +struct S; +impl T for S { + extern "avr-interrupt" fn m() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn mu() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +} -fn main() { - foo(); +impl S { + extern "avr-interrupt" fn im() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn imu() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental } + +type TA = extern "avr-interrupt" fn(); +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +type TAU = extern "avr-non-blocking-interrupt" fn(); +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + +extern "avr-interrupt" {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +extern "avr-non-blocking-interrupt" {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental diff --git a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr index be7040e149..d017d03a38 100644 --- a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr @@ -1,12 +1,129 @@ error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change - --> $DIR/feature-gate-abi-avr-interrupt.rs:4:8 + --> $DIR/feature-gate-abi-avr-interrupt.rs:11:8 | -LL | extern "avr-interrupt" fn foo() {} +LL | extern "avr-non-blocking-interrupt" fn fu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:13:8 + | +LL | extern "avr-interrupt" fn f() {} | ^^^^^^^^^^^^^^^ | = note: see issue #69664 for more information = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:17:12 + | +LL | extern "avr-interrupt" fn m(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:19:12 + | +LL | extern "avr-non-blocking-interrupt" fn mu(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:22:12 + | +LL | extern "avr-interrupt" fn dm() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:24:12 + | +LL | extern "avr-non-blocking-interrupt" fn dmu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:30:12 + | +LL | extern "avr-interrupt" fn m() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:32:12 + | +LL | extern "avr-non-blocking-interrupt" fn mu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:37:12 + | +LL | extern "avr-interrupt" fn im() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:39:12 + | +LL | extern "avr-non-blocking-interrupt" fn imu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:43:18 + | +LL | type TA = extern "avr-interrupt" fn(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:45:19 + | +LL | type TAU = extern "avr-non-blocking-interrupt" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:48:8 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:50:8 + | +LL | extern "avr-non-blocking-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs index 440570c549..8b7d8066aa 100644 --- a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs +++ b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs @@ -1,11 +1,34 @@ -// Test that the MSP430 interrupt ABI cannot be used when msp430_interrupt -// feature gate is not used. +// needs-llvm-components: msp430 +// compile-flags: --target=msp430-none-elf --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } -// ignore-riscv64 msp430 is not supported +extern "msp430-interrupt" fn f() {} +//~^ ERROR msp430-interrupt ABI is experimental -extern "msp430-interrupt" fn foo() {} -//~^ ERROR msp430-interrupt ABI is experimental and subject to change +trait T { + extern "msp430-interrupt" fn m(); + //~^ ERROR msp430-interrupt ABI is experimental -fn main() { - foo(); + extern "msp430-interrupt" fn dm() {} + //~^ ERROR msp430-interrupt ABI is experimental } + +struct S; +impl T for S { + extern "msp430-interrupt" fn m() {} + //~^ ERROR msp430-interrupt ABI is experimental +} + +impl S { + extern "msp430-interrupt" fn im() {} + //~^ ERROR msp430-interrupt ABI is experimental +} + +type TA = extern "msp430-interrupt" fn(); +//~^ ERROR msp430-interrupt ABI is experimental + +extern "msp430-interrupt" {} +//~^ ERROR msp430-interrupt ABI is experimental diff --git a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr index 554226bd2b..c19ec97896 100644 --- a/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr @@ -1,12 +1,66 @@ error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi-msp430-interrupt.rs:6:8 + --> $DIR/feature-gate-abi-msp430-interrupt.rs:8:8 | -LL | extern "msp430-interrupt" fn foo() {} +LL | extern "msp430-interrupt" fn f() {} | ^^^^^^^^^^^^^^^^^^ | = note: see issue #38487 for more information = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:12:12 + | +LL | extern "msp430-interrupt" fn m(); + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:15:12 + | +LL | extern "msp430-interrupt" fn dm() {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:21:12 + | +LL | extern "msp430-interrupt" fn m() {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:26:12 + | +LL | extern "msp430-interrupt" fn im() {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:30:18 + | +LL | type TA = extern "msp430-interrupt" fn(); + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:33:8 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.rs b/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.rs new file mode 100644 index 0000000000..7c3e4d10d9 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.rs @@ -0,0 +1,28 @@ +// needs-llvm-components: x86 +// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental +trait Tr { + extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental + extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental +} + +struct S; + +// Methods in trait impl +impl Tr for S { + extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental +} + +// Methods in inherent impl +impl S { + extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental +} + +type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental + +extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental diff --git a/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr new file mode 100644 index 0000000000..3b727a745e --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr @@ -0,0 +1,66 @@ +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:8:8 + | +LL | extern "x86-interrupt" fn f7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:10:12 + | +LL | extern "x86-interrupt" fn m7(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:11:12 + | +LL | extern "x86-interrupt" fn dm7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:18:12 + | +LL | extern "x86-interrupt" fn m7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:23:12 + | +LL | extern "x86-interrupt" fn im7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:26:18 + | +LL | type A7 = extern "x86-interrupt" fn(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:28:8 + | +LL | extern "x86-interrupt" {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs index 49cf2e158e..855263595d 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.rs +++ b/src/test/ui/feature-gates/feature-gate-abi.rs @@ -1,27 +1,21 @@ -// only-x86_64 // gate-test-intrinsics // gate-test-platform_intrinsics -// gate-test-abi_vectorcall -// gate-test-abi_thiscall -// gate-test-abi_ptx -// gate-test-abi_x86_interrupt -// gate-test-abi_amdgpu_kernel // gate-test-abi_efiapi +// compile-flags: --crate-type=rlib + +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } // Functions extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in -extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change -extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental -extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change -extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental -extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change -extern "amdgpu-kernel" fn f9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn f10() {} //~ ERROR efiapi ABI is experimental and subject to change -extern "wasm" fn f11() {} //~ ERROR wasm ABI is experimental and subject to change // Methods in trait definition trait Tr { @@ -29,25 +23,11 @@ trait Tr { //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in - extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change - extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental - extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change - extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental - extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change - extern "amdgpu-kernel" fn m9(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change - extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change - extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental - extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change - extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental - extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change - extern "amdgpu-kernel" fn dm9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn dm10() {} //~ ERROR efiapi ABI is experimental and subject to change - extern "wasm" fn dm11() {} //~ ERROR wasm ABI is experimental and subject to change } struct S; @@ -58,15 +38,8 @@ impl Tr for S { //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in - extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental - extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change - extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental - extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change - extern "amdgpu-kernel" fn m9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn m10() {} //~ ERROR efiapi ABI is experimental and subject to change - extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change } // Methods in inherent impl @@ -75,41 +48,18 @@ impl S { //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental //~^ ERROR intrinsic must be in - extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change - extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental - extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change - extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental - extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change - extern "amdgpu-kernel" fn im9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to change - extern "wasm" fn im11() {} //~ ERROR wasm ABI is experimental and subject to change } // Function pointer types type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental -type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change -type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental -type A6 = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental and subject to change -type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental -type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change -type A9 = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change type A10 = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental and subject to change -type A11 = extern "wasm" fn(); //~ ERROR wasm ABI is experimental and subject to change // Foreign modules extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental -extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" {} //~ ERROR rust-call ABI is subject to change -extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental -extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change -extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental -extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change -extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" {} //~ ERROR efiapi ABI is experimental and subject to change -extern "wasm" {} //~ ERROR wasm ABI is experimental and subject to change - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index 078d21ad36..bcca39c8fb 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -1,5 +1,5 @@ error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:12:8 + --> $DIR/feature-gate-abi.rs:13:8 | LL | extern "rust-intrinsic" fn f1() {} | ^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:14:8 + --> $DIR/feature-gate-abi.rs:15:8 | LL | extern "platform-intrinsic" fn f2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -15,14 +15,6 @@ LL | extern "platform-intrinsic" fn f2() {} = note: see issue #27731 for more information = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable -error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:16:8 - | -LL | extern "vectorcall" fn f3() {} - | ^^^^^^^^^^^^ - | - = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change --> $DIR/feature-gate-abi.rs:17:8 | @@ -32,52 +24,8 @@ LL | extern "rust-call" fn f4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:18:8 - | -LL | extern "msp430-interrupt" fn f5() {} - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #38487 for more information - = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable - -error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:19:8 - | -LL | extern "ptx-kernel" fn f6() {} - | ^^^^^^^^^^^^ - | - = note: see issue #38788 for more information - = help: add `#![feature(abi_ptx)]` to the crate attributes to enable - -error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:20:8 - | -LL | extern "x86-interrupt" fn f7() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #40180 for more information - = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable - -error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:21:8 - | -LL | extern "thiscall" fn f8() {} - | ^^^^^^^^^^ - | - = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:22:8 - | -LL | extern "amdgpu-kernel" fn f9() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:23:8 + --> $DIR/feature-gate-abi.rs:18:8 | LL | extern "efiapi" fn f10() {} | ^^^^^^^^ @@ -85,17 +33,8 @@ LL | extern "efiapi" fn f10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:24:8 - | -LL | extern "wasm" fn f11() {} - | ^^^^^^ - | - = note: see issue #83788 for more information - = help: add `#![feature(wasm_abi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:28:12 + --> $DIR/feature-gate-abi.rs:22:12 | LL | extern "rust-intrinsic" fn m1(); | ^^^^^^^^^^^^^^^^ @@ -103,7 +42,7 @@ LL | extern "rust-intrinsic" fn m1(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:30:12 + --> $DIR/feature-gate-abi.rs:24:12 | LL | extern "platform-intrinsic" fn m2(); | ^^^^^^^^^^^^^^^^^^^^ @@ -111,16 +50,8 @@ LL | extern "platform-intrinsic" fn m2(); = note: see issue #27731 for more information = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable -error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:32:12 - | -LL | extern "vectorcall" fn m3(); - | ^^^^^^^^^^^^ - | - = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:33:12 + --> $DIR/feature-gate-abi.rs:26:12 | LL | extern "rust-call" fn m4(_: ()); | ^^^^^^^^^^^ @@ -128,52 +59,8 @@ LL | extern "rust-call" fn m4(_: ()); = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:34:12 - | -LL | extern "msp430-interrupt" fn m5(); - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #38487 for more information - = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable - -error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:35:12 - | -LL | extern "ptx-kernel" fn m6(); - | ^^^^^^^^^^^^ - | - = note: see issue #38788 for more information - = help: add `#![feature(abi_ptx)]` to the crate attributes to enable - -error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:36:12 - | -LL | extern "x86-interrupt" fn m7(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #40180 for more information - = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable - -error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:37:12 - | -LL | extern "thiscall" fn m8(); - | ^^^^^^^^^^ - | - = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:38:12 - | -LL | extern "amdgpu-kernel" fn m9(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:39:12 + --> $DIR/feature-gate-abi.rs:27:12 | LL | extern "efiapi" fn m10(); | ^^^^^^^^ @@ -181,25 +68,8 @@ LL | extern "efiapi" fn m10(); = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:40:12 - | -LL | extern "wasm" fn m11() {} - | ^^^^^^ - | - = note: see issue #83788 for more information - = help: add `#![feature(wasm_abi)]` to the crate attributes to enable - -error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:42:12 - | -LL | extern "vectorcall" fn dm3() {} - | ^^^^^^^^^^^^ - | - = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:43:12 + --> $DIR/feature-gate-abi.rs:29:12 | LL | extern "rust-call" fn dm4(_: ()) {} | ^^^^^^^^^^^ @@ -207,52 +77,8 @@ LL | extern "rust-call" fn dm4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:44:12 - | -LL | extern "msp430-interrupt" fn dm5() {} - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #38487 for more information - = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable - -error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:45:12 - | -LL | extern "ptx-kernel" fn dm6() {} - | ^^^^^^^^^^^^ - | - = note: see issue #38788 for more information - = help: add `#![feature(abi_ptx)]` to the crate attributes to enable - -error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:46:12 - | -LL | extern "x86-interrupt" fn dm7() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #40180 for more information - = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable - -error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:47:12 - | -LL | extern "thiscall" fn dm8() {} - | ^^^^^^^^^^ - | - = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:48:12 - | -LL | extern "amdgpu-kernel" fn dm9() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:49:12 + --> $DIR/feature-gate-abi.rs:30:12 | LL | extern "efiapi" fn dm10() {} | ^^^^^^^^ @@ -260,17 +86,8 @@ LL | extern "efiapi" fn dm10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:50:12 - | -LL | extern "wasm" fn dm11() {} - | ^^^^^^ - | - = note: see issue #83788 for more information - = help: add `#![feature(wasm_abi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:57:12 + --> $DIR/feature-gate-abi.rs:37:12 | LL | extern "rust-intrinsic" fn m1() {} | ^^^^^^^^^^^^^^^^ @@ -278,7 +95,7 @@ LL | extern "rust-intrinsic" fn m1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:59:12 + --> $DIR/feature-gate-abi.rs:39:12 | LL | extern "platform-intrinsic" fn m2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -286,16 +103,8 @@ LL | extern "platform-intrinsic" fn m2() {} = note: see issue #27731 for more information = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable -error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:61:12 - | -LL | extern "vectorcall" fn m3() {} - | ^^^^^^^^^^^^ - | - = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:62:12 + --> $DIR/feature-gate-abi.rs:41:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -303,52 +112,8 @@ LL | extern "rust-call" fn m4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:63:12 - | -LL | extern "msp430-interrupt" fn m5() {} - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #38487 for more information - = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable - -error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:64:12 - | -LL | extern "ptx-kernel" fn m6() {} - | ^^^^^^^^^^^^ - | - = note: see issue #38788 for more information - = help: add `#![feature(abi_ptx)]` to the crate attributes to enable - -error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:65:12 - | -LL | extern "x86-interrupt" fn m7() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #40180 for more information - = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable - -error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:66:12 - | -LL | extern "thiscall" fn m8() {} - | ^^^^^^^^^^ - | - = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:67:12 - | -LL | extern "amdgpu-kernel" fn m9() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:68:12 + --> $DIR/feature-gate-abi.rs:42:12 | LL | extern "efiapi" fn m10() {} | ^^^^^^^^ @@ -356,17 +121,8 @@ LL | extern "efiapi" fn m10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:69:12 - | -LL | extern "wasm" fn m11() {} - | ^^^^^^ - | - = note: see issue #83788 for more information - = help: add `#![feature(wasm_abi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:74:12 + --> $DIR/feature-gate-abi.rs:47:12 | LL | extern "rust-intrinsic" fn im1() {} | ^^^^^^^^^^^^^^^^ @@ -374,7 +130,7 @@ LL | extern "rust-intrinsic" fn im1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:76:12 + --> $DIR/feature-gate-abi.rs:49:12 | LL | extern "platform-intrinsic" fn im2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -382,16 +138,8 @@ LL | extern "platform-intrinsic" fn im2() {} = note: see issue #27731 for more information = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable -error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:78:12 - | -LL | extern "vectorcall" fn im3() {} - | ^^^^^^^^^^^^ - | - = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:79:12 + --> $DIR/feature-gate-abi.rs:51:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -399,52 +147,8 @@ LL | extern "rust-call" fn im4(_: ()) {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:80:12 - | -LL | extern "msp430-interrupt" fn im5() {} - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #38487 for more information - = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable - -error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:81:12 - | -LL | extern "ptx-kernel" fn im6() {} - | ^^^^^^^^^^^^ - | - = note: see issue #38788 for more information - = help: add `#![feature(abi_ptx)]` to the crate attributes to enable - -error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:82:12 - | -LL | extern "x86-interrupt" fn im7() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #40180 for more information - = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable - -error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:83:12 - | -LL | extern "thiscall" fn im8() {} - | ^^^^^^^^^^ - | - = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:84:12 - | -LL | extern "amdgpu-kernel" fn im9() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:85:12 + --> $DIR/feature-gate-abi.rs:52:12 | LL | extern "efiapi" fn im10() {} | ^^^^^^^^ @@ -452,17 +156,8 @@ LL | extern "efiapi" fn im10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:86:12 - | -LL | extern "wasm" fn im11() {} - | ^^^^^^ - | - = note: see issue #83788 for more information - = help: add `#![feature(wasm_abi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:90:18 + --> $DIR/feature-gate-abi.rs:56:18 | LL | type A1 = extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^ @@ -470,7 +165,7 @@ LL | type A1 = extern "rust-intrinsic" fn(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:91:18 + --> $DIR/feature-gate-abi.rs:57:18 | LL | type A2 = extern "platform-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^ @@ -478,16 +173,8 @@ LL | type A2 = extern "platform-intrinsic" fn(); = note: see issue #27731 for more information = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable -error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:92:18 - | -LL | type A3 = extern "vectorcall" fn(); - | ^^^^^^^^^^^^ - | - = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:93:18 + --> $DIR/feature-gate-abi.rs:58:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -495,52 +182,8 @@ LL | type A4 = extern "rust-call" fn(_: ()); = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:94:18 - | -LL | type A5 = extern "msp430-interrupt" fn(); - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #38487 for more information - = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable - -error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:95:18 - | -LL | type A6 = extern "ptx-kernel" fn(); - | ^^^^^^^^^^^^ - | - = note: see issue #38788 for more information - = help: add `#![feature(abi_ptx)]` to the crate attributes to enable - -error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:96:18 - | -LL | type A7 = extern "x86-interrupt" fn(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #40180 for more information - = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable - -error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:97:18 - | -LL | type A8 = extern "thiscall" fn(); - | ^^^^^^^^^^ - | - = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:98:18 - | -LL | type A9 = extern "amdgpu-kernel" fn(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:99:19 + --> $DIR/feature-gate-abi.rs:59:19 | LL | type A10 = extern "efiapi" fn(); | ^^^^^^^^ @@ -548,17 +191,8 @@ LL | type A10 = extern "efiapi" fn(); = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:100:19 - | -LL | type A11 = extern "wasm" fn(); - | ^^^^^^ - | - = note: see issue #83788 for more information - = help: add `#![feature(wasm_abi)]` to the crate attributes to enable - error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:103:8 + --> $DIR/feature-gate-abi.rs:62:8 | LL | extern "rust-intrinsic" {} | ^^^^^^^^^^^^^^^^ @@ -566,7 +200,7 @@ LL | extern "rust-intrinsic" {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:104:8 + --> $DIR/feature-gate-abi.rs:63:8 | LL | extern "platform-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^ @@ -574,16 +208,8 @@ LL | extern "platform-intrinsic" {} = note: see issue #27731 for more information = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable -error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:105:8 - | -LL | extern "vectorcall" {} - | ^^^^^^^^^^^^ - | - = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable - error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:106:8 + --> $DIR/feature-gate-abi.rs:64:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -591,52 +217,8 @@ LL | extern "rust-call" {} = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:107:8 - | -LL | extern "msp430-interrupt" {} - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #38487 for more information - = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable - -error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:108:8 - | -LL | extern "ptx-kernel" {} - | ^^^^^^^^^^^^ - | - = note: see issue #38788 for more information - = help: add `#![feature(abi_ptx)]` to the crate attributes to enable - -error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:109:8 - | -LL | extern "x86-interrupt" {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #40180 for more information - = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable - -error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:110:8 - | -LL | extern "thiscall" {} - | ^^^^^^^^^^ - | - = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:111:8 - | -LL | extern "amdgpu-kernel" {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:112:8 + --> $DIR/feature-gate-abi.rs:65:8 | LL | extern "efiapi" {} | ^^^^^^^^ @@ -644,63 +226,54 @@ LL | extern "efiapi" {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:113:8 - | -LL | extern "wasm" {} - | ^^^^^^ - | - = note: see issue #83788 for more information - = help: add `#![feature(wasm_abi)]` to the crate attributes to enable - error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:28:32 + --> $DIR/feature-gate-abi.rs:22:32 | LL | extern "rust-intrinsic" fn m1(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:30:36 + --> $DIR/feature-gate-abi.rs:24:36 | LL | extern "platform-intrinsic" fn m2(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:12:33 + --> $DIR/feature-gate-abi.rs:13:33 | LL | extern "rust-intrinsic" fn f1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:14:37 + --> $DIR/feature-gate-abi.rs:15:37 | LL | extern "platform-intrinsic" fn f2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:57:37 + --> $DIR/feature-gate-abi.rs:37:37 | LL | extern "rust-intrinsic" fn m1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:59:41 + --> $DIR/feature-gate-abi.rs:39:41 | LL | extern "platform-intrinsic" fn m2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:74:38 + --> $DIR/feature-gate-abi.rs:47:38 | LL | extern "rust-intrinsic" fn im1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:76:42 + --> $DIR/feature-gate-abi.rs:49:42 | LL | extern "platform-intrinsic" fn im2() {} | ^^ -error: aborting due to 83 previous errors +error: aborting due to 34 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs b/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs new file mode 100644 index 0000000000..465b81d7fe --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs @@ -0,0 +1,30 @@ +// compile-flags: --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "amdgpu-kernel" fn fu() {} //~ ERROR amdgpu-kernel ABI is experimental +//~^ ERROR is not a supported ABI + +trait T { + extern "amdgpu-kernel" fn mu(); //~ ERROR amdgpu-kernel ABI is experimental + extern "amdgpu-kernel" fn dmu() {} //~ ERROR amdgpu-kernel ABI is experimental + //~^ ERROR is not a supported ABI +} + +struct S; +impl T for S { + extern "amdgpu-kernel" fn mu() {} //~ ERROR amdgpu-kernel ABI is experimental + //~^ ERROR is not a supported ABI +} + +impl S { + extern "amdgpu-kernel" fn imu() {} //~ ERROR amdgpu-kernel ABI is experimental + //~^ ERROR is not a supported ABI +} + +type TAU = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental + +extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental +//~^ ERROR is not a supported ABI diff --git a/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr b/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr new file mode 100644 index 0000000000..c89ab7bae1 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr @@ -0,0 +1,97 @@ +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:8 + | +LL | extern "amdgpu-kernel" fn fu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:11:12 + | +LL | extern "amdgpu-kernel" fn mu(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:12 + | +LL | extern "amdgpu-kernel" fn dmu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:12 + | +LL | extern "amdgpu-kernel" fn mu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:12 + | +LL | extern "amdgpu-kernel" fn imu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:27:19 + | +LL | type TAU = extern "amdgpu-kernel" fn(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:8 + | +LL | extern "amdgpu-kernel" {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:1 + | +LL | extern "amdgpu-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:1 + | +LL | extern "amdgpu-kernel" fn fu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:5 + | +LL | extern "amdgpu-kernel" fn dmu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:5 + | +LL | extern "amdgpu-kernel" fn mu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:5 + | +LL | extern "amdgpu-kernel" fn imu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0570, E0658. +For more information about an error, try `rustc --explain E0570`. diff --git a/src/test/ui/feature-gates/feature-gate-abi_ptx.rs b/src/test/ui/feature-gates/feature-gate-abi_ptx.rs new file mode 100644 index 0000000000..e3405641ec --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi_ptx.rs @@ -0,0 +1,26 @@ +// needs-llvm-components: nvptx +// compile-flags: --target=nvptx64-nvidia-cuda --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "ptx-kernel" fn fu() {} //~ ERROR PTX ABIs are experimental + +trait T { + extern "ptx-kernel" fn mu(); //~ ERROR PTX ABIs are experimental + extern "ptx-kernel" fn dmu() {} //~ ERROR PTX ABIs are experimental +} + +struct S; +impl T for S { + extern "ptx-kernel" fn mu() {} //~ ERROR PTX ABIs are experimental +} + +impl S { + extern "ptx-kernel" fn imu() {} //~ ERROR PTX ABIs are experimental +} + +type TAU = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental + +extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental diff --git a/src/test/ui/feature-gates/feature-gate-abi_ptx.stderr b/src/test/ui/feature-gates/feature-gate-abi_ptx.stderr new file mode 100644 index 0000000000..40782d361e --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-abi_ptx.stderr @@ -0,0 +1,66 @@ +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:8:8 + | +LL | extern "ptx-kernel" fn fu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:11:12 + | +LL | extern "ptx-kernel" fn mu(); + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:12:12 + | +LL | extern "ptx-kernel" fn dmu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:17:12 + | +LL | extern "ptx-kernel" fn mu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:21:12 + | +LL | extern "ptx-kernel" fn imu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:24:19 + | +LL | type TAU = extern "ptx-kernel" fn(); + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:26:8 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index 38be85ff82..1e48996acb 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -57,20 +57,20 @@ fn _rpit_dyn() -> Box> { Box::new(S1) } const _cdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` not allowed outside of function and inherent method return types [E0562] +//~| ERROR `impl Trait` not allowed outside of function and method return types [E0562] // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // const _cdef_dyn: &dyn Tr1 = &S1; static _sdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable -//~| ERROR `impl Trait` not allowed outside of function and inherent method return types [E0562] +//~| ERROR `impl Trait` not allowed outside of function and method return types [E0562] // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // static _sdef_dyn: &dyn Tr1 = &S1; fn main() { let _: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable - //~| ERROR `impl Trait` not allowed outside of function and inherent method return types [E0562] + //~| ERROR `impl Trait` not allowed outside of function and method return types [E0562] // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. // let _: &dyn Tr1 = &S1; } diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index be5d35139b..2dacb94bcc 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -115,29 +115,23 @@ LL | let _: impl Tr1 = S1; = note: see issue #52662 for more information = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/feature-gate-associated_type_bounds.rs:58:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/feature-gate-associated_type_bounds.rs:64:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/feature-gate-associated_type_bounds.rs:71:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied --> $DIR/feature-gate-associated_type_bounds.rs:15:28 diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-abi.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-abi.rs new file mode 100644 index 0000000000..f265149398 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-abi.rs @@ -0,0 +1,11 @@ +#[cfg(target_abi = "x")] //~ ERROR `cfg(target_abi)` is experimental +#[cfg_attr(target_abi = "x", x)] //~ ERROR `cfg(target_abi)` is experimental +struct Foo(u64, u64); + +#[cfg(not(any(all(target_abi = "x"))))] //~ ERROR `cfg(target_abi)` is experimental +fn foo() {} + +fn main() { + cfg!(target_abi = "x"); + //~^ ERROR `cfg(target_abi)` is experimental and subject to change +} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-abi.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-abi.stderr new file mode 100644 index 0000000000..ed8cbcbe4f --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-abi.stderr @@ -0,0 +1,39 @@ +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:2:12 + | +LL | #[cfg_attr(target_abi = "x", x)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:1:7 + | +LL | #[cfg(target_abi = "x")] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:5:19 + | +LL | #[cfg(not(any(all(target_abi = "x"))))] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:9:10 + | +LL | cfg!(target_abi = "x"); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-fn_align.rs b/src/test/ui/feature-gates/feature-gate-fn_align.rs new file mode 100644 index 0000000000..ea873dba26 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-fn_align.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +#[repr(align(16))] //~ ERROR `repr(align)` attributes on functions are unstable +fn requires_alignment() {} diff --git a/src/test/ui/feature-gates/feature-gate-fn_align.stderr b/src/test/ui/feature-gates/feature-gate-fn_align.stderr new file mode 100644 index 0000000000..5ff124e48d --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-fn_align.stderr @@ -0,0 +1,12 @@ +error[E0658]: `repr(align)` attributes on functions are unstable + --> $DIR/feature-gate-fn_align.rs:3:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ + | + = note: see issue #82232 for more information + = help: add `#![feature(fn_align)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs deleted file mode 100644 index 39cc64f11a..0000000000 --- a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.rs +++ /dev/null @@ -1,11 +0,0 @@ -const FOO: impl Copy = 42; -//~^ ERROR `impl Trait` not allowed - -static BAR: impl Copy = 42; -//~^ ERROR `impl Trait` not allowed - -fn main() { - let foo = impl Copy = 42; -//~^ ERROR expected expression, found keyword `impl` - let foo: impl Copy = 42; -} diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr deleted file mode 100644 index bd648b4059..0000000000 --- a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: expected expression, found keyword `impl` - --> $DIR/feature-gate-impl_trait_in_bindings.rs:8:15 - | -LL | let foo = impl Copy = 42; - | ^^^^ expected expression - -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-impl_trait_in_bindings.rs:1:12 - | -LL | const FOO: impl Copy = 42; - | ^^^^^^^^^ - | - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable - -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-impl_trait_in_bindings.rs:4:13 - | -LL | static BAR: impl Copy = 42; - | ^^^^^^^^^ - | - = help: add `#![feature(impl_trait_in_bindings)]` 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-min_type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-min_type_alias_impl_trait.stderr index b82867c670..07857289aa 100644 --- a/src/test/ui/feature-gates/feature-gate-min_type_alias_impl_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-min_type_alias_impl_trait.stderr @@ -106,7 +106,7 @@ LL | type Baa = (Vec, impl Debug, impl Iterator for more information = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/feature-gate-min_type_alias_impl_trait.rs:23:18 | LL | type Assoc = impl Debug; diff --git a/src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr b/src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr index b49cc40800..80ebcabcf8 100644 --- a/src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr +++ b/src/test/ui/feature-gates/feature-gate-more-qualified-paths.stderr @@ -4,7 +4,7 @@ error[E0658]: usage of qualified paths in this context is experimental LL | let ::Assoc { br } = StructStruct { br: 2 }; | ^^^^^^^^^^^^^^^^^ | - = note: see issue #80080 for more information + = note: see issue #86935 for more information = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable error[E0658]: usage of qualified paths in this context is experimental @@ -13,7 +13,7 @@ error[E0658]: usage of qualified paths in this context is experimental LL | let _ = ::Assoc { br: 2 }; | ^^^^^^^^^^^^^^^^^ | - = note: see issue #80080 for more information + = note: see issue #86935 for more information = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable error[E0658]: usage of qualified paths in this context is experimental @@ -22,7 +22,7 @@ error[E0658]: usage of qualified paths in this context is experimental LL | let ::V(..) = E::V(0); | ^^^^^^ | - = note: see issue #80080 for more information + = note: see issue #86935 for more information = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable error: aborting due to 3 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr index 12195bc107..c13c05f146 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:38 + --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39 | LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - | ^^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 @@ -35,10 +35,10 @@ LL | fn static_fn() where Self: Sized {} | ^^^^^^^^^^^^^^^^^ error[E0038]: the trait `NonObjectSafe3` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35 + --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39 | LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object | = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/feature-gates/feature-gate-optimize_attribute.stderr b/src/test/ui/feature-gates/feature-gate-optimize_attribute.stderr index 50ce6427e8..a3ced35155 100644 --- a/src/test/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/src/test/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -51,4 +51,5 @@ LL | #[optimize(banana)] error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0658, E0722. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index dfd82a25f4..4fb1cd2aae 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -31,7 +31,7 @@ type Foo4 = impl Debug; fn define4() { let y: Foo4 = 42; - //~^ ERROR not permitted here + //~^ ERROR mismatched types [E0308] } fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr index 43fd76ef0e..10409d5fc4 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr @@ -45,14 +45,19 @@ LL | define3(42) = note: expected opaque type `impl Debug` found type `{integer}` -error[E0658]: type alias impl trait is not permitted here - --> $DIR/feature-gate-type_alias_impl_trait.rs:33:12 +error[E0308]: mismatched types + --> $DIR/feature-gate-type_alias_impl_trait.rs:33:19 | +LL | type Foo4 = impl Debug; + | ---------- the expected opaque type +... LL | let y: Foo4 = 42; - | ^^^^ + | ---- ^^ expected opaque type, found integer + | | + | expected due to this | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: expected opaque type `impl Debug` + found type `{integer}` error: could not find defining uses --> $DIR/feature-gate-type_alias_impl_trait.rs:5:12 diff --git a/src/test/ui/feature-gates/feature-gate-vectorcall.rs b/src/test/ui/feature-gates/feature-gate-vectorcall.rs new file mode 100644 index 0000000000..5a6c6d2880 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-vectorcall.rs @@ -0,0 +1,31 @@ +// gate-test-abi_vectorcall +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +// Test that the "vectorcall-unwind" ABI is feature-gated, and cannot be used when +// the `c_unwind` feature gate is not used. + +extern "vectorcall" fn f() {} //~ ERROR vectorcall is experimental + +trait T { + extern "vectorcall" fn m(); //~ ERROR vectorcall is experimental + + extern "vectorcall" fn dm() {} //~ ERROR vectorcall is experimental +} + +struct S; +impl T for S { + extern "vectorcall" fn m() {} //~ ERROR vectorcall is experimental +} + +impl S { + extern "vectorcall" fn im() {} //~ ERROR vectorcall is experimental +} + +type TA = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental + +extern "vectorcall" {} //~ ERROR vectorcall is experimental diff --git a/src/test/ui/feature-gates/feature-gate-vectorcall.stderr b/src/test/ui/feature-gates/feature-gate-vectorcall.stderr new file mode 100644 index 0000000000..55ee76ec3f --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-vectorcall.stderr @@ -0,0 +1,59 @@ +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:12:8 + | +LL | extern "vectorcall" fn f() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:15:12 + | +LL | extern "vectorcall" fn m(); + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:17:12 + | +LL | extern "vectorcall" fn dm() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:22:12 + | +LL | extern "vectorcall" fn m() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:26:12 + | +LL | extern "vectorcall" fn im() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:29:18 + | +LL | type TA = extern "vectorcall" fn(); + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:31:8 + | +LL | extern "vectorcall" {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-wasm_abi.rs b/src/test/ui/feature-gates/feature-gate-wasm_abi.rs index 8c8de07636..222c88daf9 100644 --- a/src/test/ui/feature-gates/feature-gate-wasm_abi.rs +++ b/src/test/ui/feature-gates/feature-gate-wasm_abi.rs @@ -1,7 +1,26 @@ -extern "wasm" fn foo() { - //~^ ERROR: wasm ABI is experimental and subject to change +// needs-llvm-components: webassembly +// compile-flags: --target=wasm32-unknown-unknown --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "wasm" fn fu() {} //~ ERROR wasm ABI is experimental + +trait T { + extern "wasm" fn mu(); //~ ERROR wasm ABI is experimental + extern "wasm" fn dmu() {} //~ ERROR wasm ABI is experimental +} + +struct S; +impl T for S { + extern "wasm" fn mu() {} //~ ERROR wasm ABI is experimental } -fn main() { - foo(); +impl S { + extern "wasm" fn imu() {} //~ ERROR wasm ABI is experimental } + +type TAU = extern "wasm" fn(); //~ ERROR wasm ABI is experimental + +extern "wasm" {} //~ ERROR wasm ABI is experimental diff --git a/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr b/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr index c4113fd6af..0140002e35 100644 --- a/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr @@ -1,12 +1,66 @@ error[E0658]: wasm ABI is experimental and subject to change - --> $DIR/feature-gate-wasm_abi.rs:1:8 + --> $DIR/feature-gate-wasm_abi.rs:8:8 | -LL | extern "wasm" fn foo() { +LL | extern "wasm" fn fu() {} | ^^^^^^ | = note: see issue #83788 for more information = help: add `#![feature(wasm_abi)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:11:12 + | +LL | extern "wasm" fn mu(); + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:12:12 + | +LL | extern "wasm" fn dmu() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:17:12 + | +LL | extern "wasm" fn mu() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:21:12 + | +LL | extern "wasm" fn imu() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:24:19 + | +LL | type TAU = extern "wasm" fn(); + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:26:8 + | +LL | extern "wasm" {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs index 5404b8c04b..86a352251b 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-derive.rs @@ -2,14 +2,14 @@ // definitions. #[derive(Debug)] -//~^ ERROR `derive` may only be applied to structs, enums and unions +//~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s mod derive { mod inner { #![derive(Debug)] } - //~^ ERROR `derive` may only be applied to structs, enums and unions + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s //~| ERROR inner macro attributes are unstable #[derive(Debug)] - //~^ ERROR `derive` may only be applied to structs, enums and unions + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s fn derive() { } #[derive(Copy, Clone)] // (can't derive Debug for unions) @@ -22,11 +22,11 @@ mod derive { enum E { } #[derive(Debug)] - //~^ ERROR `derive` may only be applied to structs, enums and unions + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s type T = S; #[derive(Debug)] - //~^ ERROR `derive` may only be applied to structs, enums and unions + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s impl S { } } diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr index 9b1f4f4621..bb8651ffb0 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-derive.stderr @@ -1,8 +1,17 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43106-gating-of-derive.rs:4:1 | -LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | / mod derive { +LL | | mod inner { #![derive(Debug)] } +LL | | +LL | | +... | +LL | | impl S { } +LL | | } + | |_- not a `struct`, `enum` or `union` error[E0658]: inner macro attributes are unstable --> $DIR/issue-43106-gating-of-derive.rs:7:20 @@ -13,29 +22,41 @@ LL | mod inner { #![derive(Debug)] } = note: see issue #54726 for more information = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43106-gating-of-derive.rs:7:17 | LL | mod inner { #![derive(Debug)] } - | ^^^^^^^^^^^^^^^^^ + | ------------^^^^^^^^^^^^^^^^^-- + | | | + | | not applicable here + | not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43106-gating-of-derive.rs:11:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | fn derive() { } + | --------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43106-gating-of-derive.rs:24:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | type T = S; + | ----------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43106-gating-of-derive.rs:28:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | impl S { } + | ---------- not a `struct`, `enum` or `union` error: aborting due to 6 previous errors diff --git a/src/test/ui/ffi_const2.stderr b/src/test/ui/ffi_const2.stderr index 0b401942c4..0c30c9dc50 100644 --- a/src/test/ui/ffi_const2.stderr +++ b/src/test/ui/ffi_const2.stderr @@ -6,3 +6,4 @@ LL | #[ffi_pure] error: aborting due to previous error +For more information about this error, try `rustc --explain E0757`. diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs index 6c97a807b0..b30e9a47a1 100644 --- a/src/test/ui/fmt/format-args-capture.rs +++ b/src/test/ui/fmt/format-args-capture.rs @@ -16,13 +16,13 @@ fn main() { fn named_argument_takes_precedence_to_captured() { let foo = "captured"; - let s = format!("{foo}", foo="named"); + let s = format!("{foo}", foo = "named"); assert_eq!(&s, "named"); - let s = format!("{foo}-{foo}-{foo}", foo="named"); + let s = format!("{foo}-{foo}-{foo}", foo = "named"); assert_eq!(&s, "named-named-named"); - let s = format!("{}-{bar}-{foo}", "positional", bar="named"); + let s = format!("{}-{bar}-{foo}", "positional", bar = "named"); assert_eq!(&s, "positional-named-captured"); } @@ -42,10 +42,11 @@ fn panic_with_single_argument_does_not_get_formatted() { // RFC #2795 suggests that this may need to change so that captured arguments are formatted. // For stability reasons this will need to part of an edition change. - #[allow(non_fmt_panic)] + #[allow(non_fmt_panics)] let msg = std::panic::catch_unwind(|| { panic!("{foo}"); - }).unwrap_err(); + }) + .unwrap_err(); assert_eq!(msg.downcast_ref::<&str>(), Some(&"{foo}")) } @@ -55,8 +56,9 @@ fn panic_with_multiple_arguments_is_formatted() { let foo = "captured"; let msg = std::panic::catch_unwind(|| { - panic!("{}-{bar}-{foo}", "positional", bar="named"); - }).unwrap_err(); + panic!("{}-{bar}-{foo}", "positional", bar = "named"); + }) + .unwrap_err(); assert_eq!(msg.downcast_ref::(), Some(&"positional-named-captured".to_string())) } diff --git a/src/test/ui/fmt/format-concat-span.rs b/src/test/ui/fmt/format-concat-span.rs new file mode 100644 index 0000000000..ce92df0ad9 --- /dev/null +++ b/src/test/ui/fmt/format-concat-span.rs @@ -0,0 +1,15 @@ +// If the format string is another macro invocation, rustc would previously +// compute nonsensical spans, such as: +// +// error: invalid format string: unmatched `}` found +// --> test.rs:2:17 +// | +// 2 | format!(concat!("abc}")); +// | ^ unmatched `}` in format string +// +// This test checks that this behavior has been fixed. + +fn main() { + format!(concat!("abc}")); + //~^ ERROR: invalid format string: unmatched `}` found +} diff --git a/src/test/ui/fmt/format-concat-span.stderr b/src/test/ui/fmt/format-concat-span.stderr new file mode 100644 index 0000000000..da46f40abc --- /dev/null +++ b/src/test/ui/fmt/format-concat-span.stderr @@ -0,0 +1,11 @@ +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/ifmt-unimpl.stderr b/src/test/ui/fmt/ifmt-unimpl.stderr index 05305e12c0..0a68c24b60 100644 --- a/src/test/ui/fmt/ifmt-unimpl.stderr +++ b/src/test/ui/fmt/ifmt-unimpl.stderr @@ -5,7 +5,11 @@ LL | format!("{:X}", "3"); | ^^^ the trait `UpperHex` is not implemented for `str` | = note: required because of the requirements on the impl of `UpperHex` for `&str` - = note: required by `std::fmt::UpperHex::fmt` +note: required by `std::fmt::UpperHex::fmt` + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | +LL | fn fmt(&self, f: &mut Formatter<'_>) -> Result; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/fmt/issue-86085.rs b/src/test/ui/fmt/issue-86085.rs new file mode 100644 index 0000000000..63d42b7696 --- /dev/null +++ b/src/test/ui/fmt/issue-86085.rs @@ -0,0 +1,6 @@ +// Tests for an ICE with the fuzzed input below. + +fn main ( ) { +format ! ( concat ! ( r#"lJ𐏿Æ�.𐏿�"# , "r} {}" ) ) ; +//~^ ERROR: invalid format string: unmatched `}` found +} diff --git a/src/test/ui/fmt/issue-86085.stderr b/src/test/ui/fmt/issue-86085.stderr new file mode 100644 index 0000000000..ee7d8a5cc2 --- /dev/null +++ b/src/test/ui/fmt/issue-86085.stderr @@ -0,0 +1,11 @@ +error: invalid format string: unmatched `}` found + --> $DIR/issue-86085.rs:4:12 + | +LL | format ! ( concat ! ( r#"lJ𐏿Æ�.𐏿�"# , "r} {}" ) ) ; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs index 7609b1525c..550974bf77 100644 --- a/src/test/ui/fn/issue-80179.rs +++ b/src/test/ui/fn/issue-80179.rs @@ -8,7 +8,7 @@ fn returns_i32() -> i32 { } fn returns_fn_ptr() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121] +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121] //~| NOTE not allowed in type signatures //~| HELP replace with the correct return type //~| SUGGESTION fn() -> i32 @@ -16,7 +16,7 @@ fn returns_fn_ptr() -> _ { } fn returns_closure() -> _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121] +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types [E0121] //~| NOTE not allowed in type signatures //~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound //~| NOTE for more information on `Fn` traits and closure types, see diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr index 63571e71b3..96d0f02b01 100644 --- a/src/test/ui/fn/issue-80179.stderr +++ b/src/test/ui/fn/issue-80179.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80179.rs:10:24 | LL | fn returns_fn_ptr() -> _ { @@ -7,7 +7,7 @@ LL | fn returns_fn_ptr() -> _ { | not allowed in type signatures | help: replace with the correct return type: `fn() -> i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80179.rs:18:25 | LL | fn returns_closure() -> _ { diff --git a/src/test/ui/for/for-c-in-str.stderr b/src/test/ui/for/for-c-in-str.stderr index 18e46e1d7d..7eac8c9c5a 100644 --- a/src/test/ui/for/for-c-in-str.stderr +++ b/src/test/ui/for/for-c-in-str.stderr @@ -6,7 +6,11 @@ LL | for c in "asdf" { | = help: the trait `Iterator` is not implemented for `&str` = note: required because of the requirements on the impl of `IntoIterator` for `&str` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/for/for-loop-bogosity.stderr b/src/test/ui/for/for-loop-bogosity.stderr index 0d94096268..288243325c 100644 --- a/src/test/ui/for/for-loop-bogosity.stderr +++ b/src/test/ui/for/for-loop-bogosity.stderr @@ -6,7 +6,11 @@ LL | for x in bogus { | = help: the trait `Iterator` is not implemented for `MyStruct` = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs b/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs new file mode 100644 index 0000000000..a036d10e63 --- /dev/null +++ b/src/test/ui/function-pointer/function-pointer-comparison-issue-54685.rs @@ -0,0 +1,31 @@ +// min-llvm-version: 12.0 +// compile-flags: -C opt-level=3 +// run-pass + +fn foo(_i: i32) -> i32 { + 1 +} +fn bar(_i: i32) -> i32 { + 1 +} + +fn main() { + let x: fn(i32) -> i32 = foo; + let y: fn(i32) -> i32 = bar; + + let s1; + if x == y { + s1 = "same".to_string(); + } else { + s1 = format!("{:?}, {:?}", x, y); + } + + let s2; + if x == y { + s2 = "same".to_string(); + } else { + s2 = format!("{:?}, {:?}", x, y); + } + + assert_eq!(s1, s2); +} diff --git a/src/test/ui/future-incompatible-lint-group.rs b/src/test/ui/future-incompatible-lint-group.rs index 3630f08c93..bbd0e33d71 100644 --- a/src/test/ui/future-incompatible-lint-group.rs +++ b/src/test/ui/future-incompatible-lint-group.rs @@ -1,8 +1,18 @@ +// Ensure that the future_incompatible lint group only includes +// lints for changes that are not tied to an edition #![deny(future_incompatible)] trait Tr { - fn f(u8) {} //~ ERROR anonymous parameters are deprecated - //~^ WARN this was previously accepted + // Warn only since this is not a `future_incompatible` lint + fn f(u8) {} //~ WARN anonymous parameters are deprecated + //~| WARN this is accepted in the current edition +} + +pub mod submodule { + // Error since this is a `future_incompatible` lint + #![doc(test(some_test))] + //~^ ERROR this attribute can only be applied at the crate level + //~| WARN this was previously accepted by the compiler } fn main() {} diff --git a/src/test/ui/future-incompatible-lint-group.stderr b/src/test/ui/future-incompatible-lint-group.stderr index a19051e8bc..cb9be88c9e 100644 --- a/src/test/ui/future-incompatible-lint-group.stderr +++ b/src/test/ui/future-incompatible-lint-group.stderr @@ -1,17 +1,28 @@ -error: anonymous parameters are deprecated and will be removed in the next edition. - --> $DIR/future-incompatible-lint-group.rs:4:10 +warning: anonymous parameters are deprecated and will be removed in the next edition. + --> $DIR/future-incompatible-lint-group.rs:7:10 | LL | fn f(u8) {} | ^^ 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 + +error: this attribute can only be applied at the crate level + --> $DIR/future-incompatible-lint-group.rs:13:12 + | +LL | #![doc(test(some_test))] + | ^^^^^^^^^^^^^^^ + | note: the lint level is defined here - --> $DIR/future-incompatible-lint-group.rs:1:9 + --> $DIR/future-incompatible-lint-group.rs:3:9 | LL | #![deny(future_incompatible)] | ^^^^^^^^^^^^^^^^^^^ - = note: `#[deny(anonymous_parameters)]` 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 the 2018 edition! - = note: for more information, see issue #41686 + = 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 + = 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 +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index 96a8d6d70e..46d27baa54 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -29,11 +29,11 @@ LL | require_send(send_gen); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6 {()}]` + = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]` = note: required because it appears within the type `impl Generator` = note: required because it appears within the type `impl Generator` = note: required because it appears within the type `{impl Generator, ()}` - = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6 {impl Generator, ()}]` + = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]` error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/layout-error.full_tait.stderr b/src/test/ui/generator/layout-error.full_tait.stderr index 805a4d1d00..bf647d0898 100644 --- a/src/test/ui/generator/layout-error.full_tait.stderr +++ b/src/test/ui/generator/layout-error.full_tait.stderr @@ -1,26 +1,18 @@ error[E0425]: cannot find value `Foo` in this scope - --> $DIR/layout-error.rs:25:17 + --> $DIR/layout-error.rs:24:17 | LL | let a = Foo; | ^^^ not found in this scope -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes +warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/layout-error.rs:8:32 | -LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] + | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/layout-error.rs:8:56 - | -LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] - | ^^^^^^^^^^^^^^^^^^^^^ - | = note: see issue #63063 for more information -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/generator/layout-error.min_tait.stderr b/src/test/ui/generator/layout-error.min_tait.stderr index be469d781b..ed31c260cb 100644 --- a/src/test/ui/generator/layout-error.min_tait.stderr +++ b/src/test/ui/generator/layout-error.min_tait.stderr @@ -1,11 +1,11 @@ error[E0425]: cannot find value `Foo` in this scope - --> $DIR/layout-error.rs:25:17 + --> $DIR/layout-error.rs:24:17 | LL | let a = Foo; | ^^^ not found in this scope error[E0658]: type alias impl trait is not permitted here - --> $DIR/layout-error.rs:31:27 + --> $DIR/layout-error.rs:30:27 | LL | Task::spawn(&POOL, || cb()); | ^ @@ -13,28 +13,7 @@ LL | Task::spawn(&POOL, || cb()); = note: see issue #63063 for more information = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error[E0658]: type alias impl trait is not permitted here - --> $DIR/layout-error.rs:30:28 - | -LL | static POOL: Task = Task::new(); - | ^^^^^^^^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable - -error: concrete type differs from previous defining opaque type use - --> $DIR/layout-error.rs:31:24 - | -LL | Task::spawn(&POOL, || cb()); - | ^^^^^^^ expected `[type error]`, got `impl Future` - | -note: previous use here - --> $DIR/layout-error.rs:30:5 - | -LL | static POOL: Task = Task::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0425, E0658. For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/generator/layout-error.rs b/src/test/ui/generator/layout-error.rs index 9f15a6b2ec..a5efc3899d 100644 --- a/src/test/ui/generator/layout-error.rs +++ b/src/test/ui/generator/layout-error.rs @@ -5,9 +5,8 @@ // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] -#![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete use std::future::Future; pub struct Task(F); @@ -27,7 +26,6 @@ fn main() { type F = impl Future; // Check that statics are inhabited computes they layout. - static POOL: Task = Task::new(); //[min_tait]~ ERROR not permitted here + static POOL: Task = Task::new(); Task::spawn(&POOL, || cb()); //[min_tait]~ ERROR type alias impl trait is not permitted here - //[min_tait]~^ ERROR concrete type differs from previous } diff --git a/src/test/ui/generator/metadata-sufficient-for-layout.full_tait.stderr b/src/test/ui/generator/metadata-sufficient-for-layout.full_tait.stderr index ce874c1518..1e609e8388 100644 --- a/src/test/ui/generator/metadata-sufficient-for-layout.full_tait.stderr +++ b/src/test/ui/generator/metadata-sufficient-for-layout.full_tait.stderr @@ -1,25 +1,17 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/metadata-sufficient-for-layout.rs:10:32 | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/metadata-sufficient-for-layout.rs:10:55 - | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - error: fatal error triggered by #[rustc_error] - --> $DIR/metadata-sufficient-for-layout.rs:29:1 + --> $DIR/metadata-sufficient-for-layout.rs:28:1 | LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/generator/metadata-sufficient-for-layout.min_tait.stderr b/src/test/ui/generator/metadata-sufficient-for-layout.min_tait.stderr index e2b0d3622a..52d42fd59a 100644 --- a/src/test/ui/generator/metadata-sufficient-for-layout.min_tait.stderr +++ b/src/test/ui/generator/metadata-sufficient-for-layout.min_tait.stderr @@ -1,24 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/metadata-sufficient-for-layout.rs:22:23 +error: fatal error triggered by #[rustc_error] + --> $DIR/metadata-sufficient-for-layout.rs:28:1 | -LL | static A: Option = None; - | ^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable - -error: concrete type differs from previous defining opaque type use - --> $DIR/metadata-sufficient-for-layout.rs:25:1 - | -LL | fn f() -> F { metadata_sufficient_for_layout::g() } - | ^^^^^^^^^^^ expected `[type error]`, got `impl Generator` - | -note: previous use here - --> $DIR/metadata-sufficient-for-layout.rs:22:1 - | -LL | static A: Option = None; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn main() {} + | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generator/metadata-sufficient-for-layout.rs b/src/test/ui/generator/metadata-sufficient-for-layout.rs index f206093d97..c01354569f 100644 --- a/src/test/ui/generator/metadata-sufficient-for-layout.rs +++ b/src/test/ui/generator/metadata-sufficient-for-layout.rs @@ -7,9 +7,8 @@ // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait, rustc_attrs)] -#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete #![feature(generator_trait)] extern crate metadata_sufficient_for_layout; @@ -20,10 +19,10 @@ type F = impl Generator<(), Yield = (), Return = ()>; // Static queries the layout of the generator. static A: Option = None; -//[min_tait]~^ ERROR not permitted here -fn f() -> F { metadata_sufficient_for_layout::g() } -//[min_tait]~^ ERROR concrete type differs +fn f() -> F { + metadata_sufficient_for_layout::g() +} #[rustc_error] -fn main() {} //[full_tait]~ ERROR +fn main() {} //~ ERROR diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 2384ed3d24..448cb2a043 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -9,7 +9,7 @@ LL | assert_send(|| { | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Send` for `&Cell` - = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 _]` + = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6]` error: generator cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 @@ -20,7 +20,7 @@ LL | fn assert_sync(_: T) {} LL | assert_sync(|| { | ^^^^^^^^^^^ generator is not `Sync` | - = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {Cell, ()}]`, the trait `Sync` is not implemented for `Cell` + = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6]`, the trait `Sync` is not implemented for `Cell` note: generator is not `Sync` as this value is used across a yield --> $DIR/not-send-sync.rs:12:9 | 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 78100318dc..bd0d27ff3e 100644 --- a/src/test/ui/generator/print/generator-print-verbose-1.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr @@ -12,7 +12,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[317d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` + | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[70c9]::make_non_send_generator::{opaque#0}), [])` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later LL | }; @@ -30,10 +30,10 @@ LL | require_send(send_gen); = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` = note: required because it appears within the type `[make_gen2>>::{closure#0} upvar_tys=(Arc>) {()}]` - = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc>])` - = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])` - = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}` - = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}]` + = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[70c9]::make_gen2::{opaque#0}), [std::sync::Arc>])` + = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), [])` + = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}` + = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}]` error: aborting due to 2 previous errors diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.rs b/src/test/ui/generator/too-live-local-in-immovable-gen.rs index 7f118c88e5..e0b856db7a 100644 --- a/src/test/ui/generator/too-live-local-in-immovable-gen.rs +++ b/src/test/ui/generator/too-live-local-in-immovable-gen.rs @@ -15,7 +15,7 @@ fn main() { yield (); 4i32 }; - &a; + let _ = &a; }; } } 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 88dacff7b5..72a2bd4ebc 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 @@ -6,7 +6,7 @@ LL | | // Tests that the generator transformation finds out that `a` LL | | // during the yield expression. Type checking will also compute liveness LL | | // and it should also find out that `a` is not live. ... | -LL | | &a; +LL | | let _ = &a; LL | | }; | |__________^ | diff --git a/src/test/ui/generator/yield-in-initializer.rs b/src/test/ui/generator/yield-in-initializer.rs index 2f8754c957..0cab36e5f2 100644 --- a/src/test/ui/generator/yield-in-initializer.rs +++ b/src/test/ui/generator/yield-in-initializer.rs @@ -11,7 +11,7 @@ fn main() { yield; true }; - &opt; + let _ = &opt; } }; } diff --git a/src/test/ui/generator/yield-outside-generator-issue-78653.stderr b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr index f0c7cb0e5d..dff743bc35 100644 --- a/src/test/ui/generator/yield-outside-generator-issue-78653.stderr +++ b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr @@ -13,7 +13,11 @@ LL | yield || for i in 0 { } = help: the trait `Iterator` is not implemented for `{integer}` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `{integer}` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs index 5fbae02573..0944bf110c 100644 --- a/src/test/ui/generic-associated-types/collections-project-default.rs +++ b/src/test/ui/generic-associated-types/collections-project-default.rs @@ -1,9 +1,8 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] #![feature(associated_type_defaults)] // A Collection trait and collection families. Based on -// http://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// https://smallcultfollowing.com/babysteps/blog/2016/11/03/ // associated-type-constructors-part-2-family-traits/ // check that we don't normalize with trait defaults. diff --git a/src/test/ui/generic-associated-types/collections-project-default.stderr b/src/test/ui/generic-associated-types/collections-project-default.stderr index ca02b2603b..22fbc0271b 100644 --- a/src/test/ui/generic-associated-types/collections-project-default.stderr +++ b/src/test/ui/generic-associated-types/collections-project-default.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/collections-project-default.rs:60:5 + --> $DIR/collections-project-default.rs:59:5 | LL | fn floatify_sibling(ints: &C) -> >::Sibling | ------------------------------------ expected `>::Sibling` because of return type diff --git a/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs index 1b5b9c181f..f14c6dac1b 100644 --- a/src/test/ui/generic-associated-types/collections.rs +++ b/src/test/ui/generic-associated-types/collections.rs @@ -1,9 +1,8 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] #![feature(associated_type_defaults)] // A Collection trait and collection families. Based on -// http://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// https://smallcultfollowing.com/babysteps/blog/2016/11/03/ // associated-type-constructors-part-2-family-traits/ // run-pass diff --git a/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs index ab33ef6f24..afde5f3763 100644 --- a/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs +++ b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs @@ -1,6 +1,5 @@ // run-pass #![feature(generic_associated_types)] -#![allow(incomplete_features)] // This test unsures that with_opt_const_param returns the // def_id of the N param in the Foo::Assoc GAT. diff --git a/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs index ba9a82ae72..51046be79b 100644 --- a/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs +++ b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs @@ -1,6 +1,5 @@ // run-pass #![feature(generic_associated_types)] -#![allow(incomplete_features)] // This test unsures that with_opt_const_param returns the // def_id of the N param in the Foo::Assoc GAT. diff --git a/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs index 9da5334056..457fe27b3f 100644 --- a/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs +++ b/src/test/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs @@ -1,6 +1,5 @@ // run-pass #![feature(generic_associated_types)] -#![allow(incomplete_features)] // This test unsures that with_opt_const_param returns the // def_id of the N param in the Bar::Assoc GAT. diff --git a/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs index 36db3d1bb9..e315ee8421 100644 --- a/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs +++ b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.rs @@ -1,7 +1,6 @@ // Test that correct syntax is used in suggestion to constrain associated type #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete trait X { type Y; diff --git a/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr index ecf559d9e9..ad02202dfc 100644 --- a/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr +++ b/src/test/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/constraint-assoc-type-suggestion.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0308]: mismatched types - --> $DIR/constraint-assoc-type-suggestion.rs:13:23 + --> $DIR/constraint-assoc-type-suggestion.rs:12:23 | LL | let b: Vec = a; | -------- ^ expected struct `Vec`, found associated type @@ -22,6 +13,6 @@ help: consider constraining the associated type `::Y` to `Vec` LL | fn f = Vec>>(a: T::Y) { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.rs b/src/test/ui/generic-associated-types/construct_with_other_type.rs index ff9d61658f..9ae328cc48 100644 --- a/src/test/ui/generic-associated-types/construct_with_other_type.rs +++ b/src/test/ui/generic-associated-types/construct_with_other_type.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] // check-pass diff --git a/src/test/ui/generic-associated-types/empty_generics.rs b/src/test/ui/generic-associated-types/empty_generics.rs index 6eb25a92f3..772b7f2b4e 100644 --- a/src/test/ui/generic-associated-types/empty_generics.rs +++ b/src/test/ui/generic-associated-types/empty_generics.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Foo { diff --git a/src/test/ui/generic-associated-types/empty_generics.stderr b/src/test/ui/generic-associated-types/empty_generics.stderr index 1599d683ad..ac22bfc083 100644 --- a/src/test/ui/generic-associated-types/empty_generics.stderr +++ b/src/test/ui/generic-associated-types/empty_generics.stderr @@ -1,5 +1,5 @@ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` - --> $DIR/empty_generics.rs:5:14 + --> $DIR/empty_generics.rs:4:14 | LL | trait Foo { | - while parsing this item list starting here diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs index 2c543455b6..f542a7f545 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs +++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'x>; diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr index 1c7c107d78..ce9df46483 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr +++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0261]: use of undeclared lifetime name `'x` - --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:35 + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:35 | LL | fn _f(arg : Box X = &'a [u32]>>) {} | - ^^ undeclared lifetime @@ -18,12 +9,12 @@ LL | fn _f(arg : Box X = &'a [u32]>>) {} = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types - --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:33 + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:33 | LL | fn _f(arg : Box X = &'a [u32]>>) {} | ^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors Some errors have detailed explanations: E0261, E0582. For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs index 6527eb4750..fb03a86e16 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.rs +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete #![feature(associated_type_defaults)] trait Foo { diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr index 49dfce8b4b..8651789688 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr @@ -1,27 +1,18 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/gat-in-trait-path.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:22:13 + --> $DIR/gat-in-trait-path.rs:21:17 | LL | fn f(_arg : Box Foo = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | = help: consider moving `A` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/gat-in-trait-path.rs:6:10 + --> $DIR/gat-in-trait-path.rs:5:10 | LL | trait Foo { | --- this trait cannot be made into an object... LL | type A<'a> where Self: 'a; | ^ ...because it contains the generic associated type `A` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/gat-incomplete-warning.rs b/src/test/ui/generic-associated-types/gat-incomplete-warning.rs index 33593884de..607ea17598 100644 --- a/src/test/ui/generic-associated-types/gat-incomplete-warning.rs +++ b/src/test/ui/generic-associated-types/gat-incomplete-warning.rs @@ -1,6 +1,5 @@ // run-pass #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr b/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr deleted file mode 100644 index 0215ff395d..0000000000 --- a/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/gat-incomplete-warning.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs index cff5a21052..246659a268 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait Foo { type F<'a>; diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr index e83af1d0c7..310f722e12 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr @@ -1,22 +1,13 @@ error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters - --> $DIR/gat-trait-path-generic-type-arg.rs:11:12 + --> $DIR/gat-trait-path-generic-type-arg.rs:10:12 | LL | impl Foo for T { | -- first use of `T1` LL | type F = &[u8]; | ^^ already used -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/gat-trait-path-generic-type-arg.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0106]: missing lifetime specifier - --> $DIR/gat-trait-path-generic-type-arg.rs:11:18 + --> $DIR/gat-trait-path-generic-type-arg.rs:10:18 | LL | type F = &[u8]; | ^ expected named lifetime parameter @@ -26,7 +17,7 @@ help: consider introducing a named lifetime parameter LL | type F<'a, T1> = &'a [u8]; | ^^^ ^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors Some errors have detailed explanations: E0106, E0403. For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs index 484790501b..9864787f0a 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs +++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'a>; diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr index 56b5551cd3..9b63e8f307 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -1,20 +1,11 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/gat-trait-path-missing-lifetime.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0107]: missing generics for associated type `X::Y` - --> $DIR/gat-trait-path-missing-lifetime.rs:11:20 + --> $DIR/gat-trait-path-missing-lifetime.rs:10:20 | LL | fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { | ^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/gat-trait-path-missing-lifetime.rs:5:8 + --> $DIR/gat-trait-path-missing-lifetime.rs:4:8 | LL | type Y<'a>; | ^ -- @@ -24,13 +15,13 @@ LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { | ^^^^^ error[E0107]: missing generics for associated type `X::Y` - --> $DIR/gat-trait-path-missing-lifetime.rs:11:20 + --> $DIR/gat-trait-path-missing-lifetime.rs:10:20 | LL | fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { | ^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/gat-trait-path-missing-lifetime.rs:5:8 + --> $DIR/gat-trait-path-missing-lifetime.rs:4:8 | LL | type Y<'a>; | ^ -- @@ -39,6 +30,6 @@ help: add missing lifetime argument LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { | ^^^^^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs index f1af686028..48b4a4fc39 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'a>; @@ -11,6 +10,6 @@ fn foo<'a>(arg: Box>) {} //~| ERROR this associated type takes 0 generic arguments but 1 generic argument //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments //~| WARNING: trait objects without an explicit `dyn` are deprecated - //~| WARNING: this was previously accepted by the compiler + //~| WARNING: this is accepted in the current edition fn main() {} diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr index 400600a086..d6fba8b8e4 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -1,42 +1,33 @@ error: lifetime in trait object type must be followed by `+` - --> $DIR/gat-trait-path-parenthesised-args.rs:8:29 + --> $DIR/gat-trait-path-parenthesised-args.rs:7:29 | LL | fn foo<'a>(arg: Box>) {} | ^^ error: parenthesized generic arguments cannot be used in associated type constraints - --> $DIR/gat-trait-path-parenthesised-args.rs:8:27 + --> $DIR/gat-trait-path-parenthesised-args.rs:7:27 | LL | fn foo<'a>(arg: Box>) {} | ^^^^^ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/gat-trait-path-parenthesised-args.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/gat-trait-path-parenthesised-args.rs:8:29 + --> $DIR/gat-trait-path-parenthesised-args.rs:7:29 | LL | fn foo<'a>(arg: Box>) {} | ^^ help: use `dyn`: `dyn 'a` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/gat-trait-path-parenthesised-args.rs:8:27 + --> $DIR/gat-trait-path-parenthesised-args.rs:7:27 | LL | fn foo<'a>(arg: Box>) {} | ^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/gat-trait-path-parenthesised-args.rs:5:8 + --> $DIR/gat-trait-path-parenthesised-args.rs:4:8 | LL | type Y<'a>; | ^ -- @@ -46,7 +37,7 @@ LL | fn foo<'a>(arg: Box>) {} | ^^^ error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/gat-trait-path-parenthesised-args.rs:8:27 + --> $DIR/gat-trait-path-parenthesised-args.rs:7:27 | LL | fn foo<'a>(arg: Box>) {} | ^---- help: remove these generics @@ -54,11 +45,11 @@ LL | fn foo<'a>(arg: Box>) {} | expected 0 generic arguments | note: associated type defined here, with 0 generic parameters - --> $DIR/gat-trait-path-parenthesised-args.rs:5:8 + --> $DIR/gat-trait-path-parenthesised-args.rs:4:8 | LL | type Y<'a>; | ^ -error: aborting due to 4 previous errors; 2 warnings emitted +error: aborting due to 4 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs index 8094450e5e..5d3a3a8935 100644 --- a/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs +++ b/src/test/ui/generic-associated-types/generic-associated-type-bounds.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(generic_associated_types)] pub trait X { diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.rs b/src/test/ui/generic-associated-types/generic-associated-types-where.rs index 27970b15a4..592ff93992 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.rs +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] // Checking the interaction with this other feature diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr index da8b625ea7..d652654382 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr @@ -1,5 +1,5 @@ error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/generic-associated-types-where.rs:21:5 + --> $DIR/generic-associated-types-where.rs:20:5 | LL | type Assoc2 = Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter @@ -11,7 +11,7 @@ LL | type Assoc2 = Vec; | ^^^^^^^^^^^^^^^^^^^ error[E0276]: impl has stricter requirements than trait - --> $DIR/generic-associated-types-where.rs:23:5 + --> $DIR/generic-associated-types-where.rs:22:5 | LL | type Assoc3; | --------------- definition of `Assoc3` from trait diff --git a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs index 4b4e59a512..43058f7eb4 100644 --- a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs +++ b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] use std::ops::Deref; diff --git a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr index f164c0d07a..e87176e0fb 100644 --- a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr +++ b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -1,5 +1,5 @@ error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/generic_associated_type_undeclared_lifetimes.rs:9:37 + --> $DIR/generic_associated_type_undeclared_lifetimes.rs:8:37 | LL | + Deref>; | ^^ undeclared lifetime @@ -15,7 +15,7 @@ LL | type Iter<'b, 'a>: Iterator> | ^^^ error[E0261]: use of undeclared lifetime name `'undeclared` - --> $DIR/generic_associated_type_undeclared_lifetimes.rs:12:41 + --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; | ^^^^^^^^^^^ undeclared lifetime diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 50e1c50644..01edad00a8 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] #![feature(associated_type_defaults)] diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 58bcb13e68..585ba16a49 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -1,5 +1,5 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/impl_bounds.rs:16:5 + --> $DIR/impl_bounds.rs:15:5 | LL | type A<'a> where Self: 'static = (&'a ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,74 +8,84 @@ LL | type A<'a> where Self: 'static = (&'a ()); = note: ...so that the type `Fooy` will meet its required lifetime bounds error[E0478]: lifetime bound not satisfied - --> $DIR/impl_bounds.rs:18:5 + --> $DIR/impl_bounds.rs:17:5 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 18:16 - --> $DIR/impl_bounds.rs:18:16 +note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16 + --> $DIR/impl_bounds.rs:17:16 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 18:12 - --> $DIR/impl_bounds.rs:18:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12 + --> $DIR/impl_bounds.rs:17:12 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ error[E0478]: lifetime bound not satisfied - --> $DIR/impl_bounds.rs:18:5 + --> $DIR/impl_bounds.rs:17:5 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 18:12 - --> $DIR/impl_bounds.rs:18:12 +note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12 + --> $DIR/impl_bounds.rs:17:12 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 18:16 - --> $DIR/impl_bounds.rs:18:16 +note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16 + --> $DIR/impl_bounds.rs:17:16 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:21:5 + --> $DIR/impl_bounds.rs:20:5 | LL | type C where Self: Copy = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | - = note: required because of the requirements on the impl of `Copy` for `Fooy` +note: required because of the requirements on the impl of `Copy` for `Fooy` + --> $DIR/impl_bounds.rs:11:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ note: the requirement `Fooy: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type - --> $DIR/impl_bounds.rs:8:5 + --> $DIR/impl_bounds.rs:7:5 | LL | trait Foo { | --- in this trait ... LL | type C where Self: Clone; | ^^^^^^^^^^^^^^^^^^^^^^^^^ this trait associated type doesn't have the requirement `Fooy: Copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | LL | impl Foo for Fooy { | ^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:23:5 + --> $DIR/impl_bounds.rs:22:5 | LL | fn d() where Self: Copy {} | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | - = note: required because of the requirements on the impl of `Copy` for `Fooy` +note: required because of the requirements on the impl of `Copy` for `Fooy` + --> $DIR/impl_bounds.rs:11:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ note: the requirement `Fooy: Copy` appears on the impl method `d` but not on the corresponding trait method - --> $DIR/impl_bounds.rs:9:8 + --> $DIR/impl_bounds.rs:8:8 | LL | trait Foo { | --- in this trait ... LL | fn d() where Self: Clone; | ^ this trait method doesn't have the requirement `Fooy: Copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | LL | impl Foo for Fooy { diff --git a/src/test/ui/generic-associated-types/impl_bounds_ok.rs b/src/test/ui/generic-associated-types/impl_bounds_ok.rs index 98aa82aba8..08120b9670 100644 --- a/src/test/ui/generic-associated-types/impl_bounds_ok.rs +++ b/src/test/ui/generic-associated-types/impl_bounds_ok.rs @@ -1,6 +1,5 @@ // check-pass -#![allow(incomplete_features)] #![feature(generic_associated_types)] #![feature(associated_type_defaults)] diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs index de2b978460..da5fca2a65 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs @@ -1,6 +1,5 @@ // Check that this program doesn't cause the compiler to error without output. -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Foo { diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr index 439b8ab90c..5667745772 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -1,5 +1,5 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/issue-47206-where-clause.rs:13:5 + --> $DIR/issue-47206-where-clause.rs:12:5 | LL | type Assoc3; | --------------- definition of `Assoc3` from trait diff --git a/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs index 2298aa5b0b..e87a76825c 100644 --- a/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs +++ b/src/test/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs @@ -1,6 +1,5 @@ // check-pass -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Cert { diff --git a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs index 404be59a36..d74d6d056d 100644 --- a/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs +++ b/src/test/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] // check-pass diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs index 6ee865072a..99f0e84fa6 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.rs +++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'a>; diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr index 65998afa7f..b4b89ab047 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr +++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr @@ -1,27 +1,18 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-67510-pass.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0038]: the trait `X` cannot be made into an object - --> $DIR/issue-67510-pass.rs:8:19 + --> $DIR/issue-67510-pass.rs:7:23 | LL | fn _func1<'a>(_x: Box=&'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object | = help: consider moving `Y` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-67510-pass.rs:5:10 + --> $DIR/issue-67510-pass.rs:4:10 | LL | trait X { | - this trait cannot be made into an object... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-67510.rs b/src/test/ui/generic-associated-types/issue-67510.rs index 62b22089f9..e81a5b231a 100644 --- a/src/test/ui/generic-associated-types/issue-67510.rs +++ b/src/test/ui/generic-associated-types/issue-67510.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'a>; diff --git a/src/test/ui/generic-associated-types/issue-67510.stderr b/src/test/ui/generic-associated-types/issue-67510.stderr index 12755c5697..8ed2854ed3 100644 --- a/src/test/ui/generic-associated-types/issue-67510.stderr +++ b/src/test/ui/generic-associated-types/issue-67510.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-67510.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/issue-67510.rs:8:21 + --> $DIR/issue-67510.rs:7:21 | LL | fn f(x: Box=&'a ()>>) {} | - ^^ undeclared lifetime @@ -18,7 +9,7 @@ LL | fn f(x: Box=&'a ()>>) {} = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/issue-67510.rs:8:26 + --> $DIR/issue-67510.rs:7:26 | LL | fn f(x: Box=&'a ()>>) {} | - ^^ undeclared lifetime @@ -27,6 +18,6 @@ LL | fn f(x: Box=&'a ()>>) {} | = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs index 0020887eae..617d985dce 100644 --- a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.rs @@ -1,7 +1,6 @@ // Regression test for #68641 #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete and may not trait UnsafeCopy { type Item<'a>: Copy; diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr index c92800c374..7ac1ccf0f3 100644 --- a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68641-check-gat-bounds.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-68641-check-gat-bounds.rs:15:5 + --> $DIR/issue-68641-check-gat-bounds.rs:14:5 | LL | type Item<'a>: Copy; | ---- required by this bound in `UnsafeCopy::Item` @@ -21,6 +12,6 @@ help: consider restricting type parameter `T` LL | impl UnsafeCopy for T { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs index ff8d2ca05b..def0ad18f2 100644 --- a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs @@ -1,7 +1,6 @@ // Regression test for #68642 #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete and may not trait Fun { type F<'a>: Fn() -> u32; diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index e44547b10c..4e609ca548 100644 --- a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68642-broken-llvm-ir.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0277]: expected a `Fn<()>` closure, found `T` - --> $DIR/issue-68642-broken-llvm-ir.rs:15:5 + --> $DIR/issue-68642-broken-llvm-ir.rs:14:5 | LL | type F<'a>: Fn() -> u32; | ----------- required by this bound in `Fun::F` @@ -22,6 +13,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs index 2107804a8b..9af065b5d2 100644 --- a/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.rs @@ -1,7 +1,6 @@ // Regression test for #68643 #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete and may not trait Fun { type F<'a>: Fn() -> u32; diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr index fd0b4733d9..44600bfcf9 100644 --- a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68643-broken-mir.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0277]: expected a `Fn<()>` closure, found `T` - --> $DIR/issue-68643-broken-mir.rs:15:5 + --> $DIR/issue-68643-broken-mir.rs:14:5 | LL | type F<'a>: Fn() -> u32; | ----------- required by this bound in `Fun::F` @@ -22,6 +13,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs index bfe63b1be7..1d2636c260 100644 --- a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.rs @@ -1,7 +1,6 @@ // Regression test for #68644 #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete and may not trait Fun { type F<'a>: Fn() -> u32; diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr index 0c23c870f0..2c21795e16 100644 --- a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68644-codegen-selection.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0277]: expected a `Fn<()>` closure, found `T` - --> $DIR/issue-68644-codegen-selection.rs:15:5 + --> $DIR/issue-68644-codegen-selection.rs:14:5 | LL | type F<'a>: Fn() -> u32; | ----------- required by this bound in `Fun::F` @@ -22,6 +13,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs index 676dcf9023..aa505064f8 100644 --- a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs @@ -1,7 +1,6 @@ // Regression test for #68645 #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete and may not trait Fun { type F<'a>: Fn() -> u32; diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index 85d8d3f8e9..b2a2636d3e 100644 --- a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68645-codegen-fulfillment.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0277]: expected a `Fn<()>` closure, found `T` - --> $DIR/issue-68645-codegen-fulfillment.rs:15:5 + --> $DIR/issue-68645-codegen-fulfillment.rs:14:5 | LL | type F<'a>: Fn() -> u32; | ----------- required by this bound in `Fun::F` @@ -22,6 +13,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-68648-1.rs b/src/test/ui/generic-associated-types/issue-68648-1.rs index f294b22f73..17bc034b39 100644 --- a/src/test/ui/generic-associated-types/issue-68648-1.rs +++ b/src/test/ui/generic-associated-types/issue-68648-1.rs @@ -1,7 +1,6 @@ // check-pass #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait Fun { diff --git a/src/test/ui/generic-associated-types/issue-68648-1.stderr b/src/test/ui/generic-associated-types/issue-68648-1.stderr deleted file mode 100644 index 322a8f9e13..0000000000 --- a/src/test/ui/generic-associated-types/issue-68648-1.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68648-1.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/generic-associated-types/issue-68648-2.rs b/src/test/ui/generic-associated-types/issue-68648-2.rs index e55bfcd4ba..6c9a0d126a 100644 --- a/src/test/ui/generic-associated-types/issue-68648-2.rs +++ b/src/test/ui/generic-associated-types/issue-68648-2.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait Fun { type F<'a>; diff --git a/src/test/ui/generic-associated-types/issue-68648-2.stderr b/src/test/ui/generic-associated-types/issue-68648-2.stderr index b51e0bca9f..7a7d5a6c23 100644 --- a/src/test/ui/generic-associated-types/issue-68648-2.stderr +++ b/src/test/ui/generic-associated-types/issue-68648-2.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68648-2.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0308]: mismatched types - --> $DIR/issue-68648-2.rs:15:17 + --> $DIR/issue-68648-2.rs:14:17 | LL | fn bug<'a, T: Fun = T>>(t: T) -> T::F<'a> { | - this type parameter @@ -18,6 +9,6 @@ LL | T::identity(()) = note: expected type parameter `T` found unit type `()` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.rs b/src/test/ui/generic-associated-types/issue-68649-pass.rs index 396315302f..33f08faff5 100644 --- a/src/test/ui/generic-associated-types/issue-68649-pass.rs +++ b/src/test/ui/generic-associated-types/issue-68649-pass.rs @@ -1,7 +1,6 @@ // check-pass #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait Fun { type F<'a>; diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.stderr b/src/test/ui/generic-associated-types/issue-68649-pass.stderr deleted file mode 100644 index e4a2f8d2a6..0000000000 --- a/src/test/ui/generic-associated-types/issue-68649-pass.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68649-pass.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/generic-associated-types/issue-68653.rs b/src/test/ui/generic-associated-types/issue-68653.rs index 01f4c95639..1e84717e92 100644 --- a/src/test/ui/generic-associated-types/issue-68653.rs +++ b/src/test/ui/generic-associated-types/issue-68653.rs @@ -2,7 +2,6 @@ // check-pass -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Fun { diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs index f682bdd8ac..c0d9333625 100644 --- a/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.rs @@ -1,7 +1,6 @@ // Regression test for #68656 #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete and may not trait UnsafeCopy { type Item<'a>: std::ops::Deref; diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr index c4ee2c4e61..9d90d6f608 100644 --- a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-68656-unsized-values.rs:3:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0271]: type mismatch resolving `::Target == T` - --> $DIR/issue-68656-unsized-values.rs:16:5 + --> $DIR/issue-68656-unsized-values.rs:15:5 | LL | type Item<'a>: std::ops::Deref; | ---------- required by this bound in `UnsafeCopy::Item` @@ -25,6 +16,6 @@ help: consider further restricting this bound LL | impl> UnsafeCopy for T { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/generic-associated-types/issue-70303.rs b/src/test/ui/generic-associated-types/issue-70303.rs index a1cb2295b6..d238f53bde 100644 --- a/src/test/ui/generic-associated-types/issue-70303.rs +++ b/src/test/ui/generic-associated-types/issue-70303.rs @@ -1,6 +1,5 @@ // check-pass -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Document { diff --git a/src/test/ui/generic-associated-types/issue-70304.rs b/src/test/ui/generic-associated-types/issue-70304.rs index 225f61d132..ae64f9310d 100644 --- a/src/test/ui/generic-associated-types/issue-70304.rs +++ b/src/test/ui/generic-associated-types/issue-70304.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Document { diff --git a/src/test/ui/generic-associated-types/issue-70304.stderr b/src/test/ui/generic-associated-types/issue-70304.stderr index dfa8601897..fd9e1acc55 100644 --- a/src/test/ui/generic-associated-types/issue-70304.stderr +++ b/src/test/ui/generic-associated-types/issue-70304.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/issue-70304.rs:55:41 + --> $DIR/issue-70304.rs:54:41 | LL | fn create_doc() -> impl Document = DocCursorImpl<'_>> { | ^^ expected named lifetime parameter diff --git a/src/test/ui/generic-associated-types/issue-71176.rs b/src/test/ui/generic-associated-types/issue-71176.rs index c767bef155..c2f0d59f44 100644 --- a/src/test/ui/generic-associated-types/issue-71176.rs +++ b/src/test/ui/generic-associated-types/issue-71176.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Provider { diff --git a/src/test/ui/generic-associated-types/issue-71176.stderr b/src/test/ui/generic-associated-types/issue-71176.stderr index 2df800d065..f0babdaa60 100644 --- a/src/test/ui/generic-associated-types/issue-71176.stderr +++ b/src/test/ui/generic-associated-types/issue-71176.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `Provider::A` - --> $DIR/issue-71176.rs:13:27 + --> $DIR/issue-71176.rs:12:27 | LL | inner: Box>, | ^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-71176.rs:5:10 + --> $DIR/issue-71176.rs:4:10 | LL | type A<'a>; | ^ -- diff --git a/src/test/ui/generic-associated-types/issue-74684-1.rs b/src/test/ui/generic-associated-types/issue-74684-1.rs index a483da863f..0e3899a88c 100644 --- a/src/test/ui/generic-associated-types/issue-74684-1.rs +++ b/src/test/ui/generic-associated-types/issue-74684-1.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait Fun { type F<'a>: ?Sized; diff --git a/src/test/ui/generic-associated-types/issue-74684-1.stderr b/src/test/ui/generic-associated-types/issue-74684-1.stderr index 651da69682..2cd050ed8b 100644 --- a/src/test/ui/generic-associated-types/issue-74684-1.stderr +++ b/src/test/ui/generic-associated-types/issue-74684-1.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-74684-1.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0597]: `a` does not live long enough - --> $DIR/issue-74684-1.rs:16:26 + --> $DIR/issue-74684-1.rs:15:26 | LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(_ : Box) -> &'static T::F<'a> { | -- lifetime `'a` defined here @@ -22,6 +13,6 @@ LL | let _x = T::identity(&a); LL | } | - `a` dropped here while still borrowed -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generic-associated-types/issue-74684-2.rs b/src/test/ui/generic-associated-types/issue-74684-2.rs index 0caf19cb03..fca55070b5 100644 --- a/src/test/ui/generic-associated-types/issue-74684-2.rs +++ b/src/test/ui/generic-associated-types/issue-74684-2.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ WARNING: the feature `generic_associated_types` is incomplete trait Fun { type F<'a>: ?Sized; diff --git a/src/test/ui/generic-associated-types/issue-74684-2.stderr b/src/test/ui/generic-associated-types/issue-74684-2.stderr index 8c3484f9a7..23fb4285fc 100644 --- a/src/test/ui/generic-associated-types/issue-74684-2.stderr +++ b/src/test/ui/generic-associated-types/issue-74684-2.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-74684-2.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` - --> $DIR/issue-74684-2.rs:24:5 + --> $DIR/issue-74684-2.rs:23:5 | LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { | ------------ required by this bound in `bug` @@ -16,6 +7,6 @@ LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { LL | bug(Box::new(x)); | ^^^ expected slice `[u8]`, found `i32` -error: aborting due to previous error; 1 warning emitted +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/issue-74816.rs b/src/test/ui/generic-associated-types/issue-74816.rs index 754397229a..c932025d11 100644 --- a/src/test/ui/generic-associated-types/issue-74816.rs +++ b/src/test/ui/generic-associated-types/issue-74816.rs @@ -1,6 +1,5 @@ #![feature(associated_type_defaults)] #![feature(generic_associated_types)] -#![allow(incomplete_features)] trait Trait1 { fn foo(); diff --git a/src/test/ui/generic-associated-types/issue-74816.stderr b/src/test/ui/generic-associated-types/issue-74816.stderr index 64bc94d601..431182e79c 100644 --- a/src/test/ui/generic-associated-types/issue-74816.stderr +++ b/src/test/ui/generic-associated-types/issue-74816.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Trait1` is not satisfied - --> $DIR/issue-74816.rs:10:5 + --> $DIR/issue-74816.rs:9:5 | LL | type Associated: Trait1 = Self; | ^^^^^^^^^^^^^^^^^------^^^^^^^^ @@ -13,7 +13,7 @@ LL | trait Trait2: Trait1 { | ^^^^^^^^ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/issue-74816.rs:10:5 + --> $DIR/issue-74816.rs:9:5 | LL | type Associated: Trait1 = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/issue-74824.rs b/src/test/ui/generic-associated-types/issue-74824.rs index 00761a97d0..1bbf7aac5c 100644 --- a/src/test/ui/generic-associated-types/issue-74824.rs +++ b/src/test/ui/generic-associated-types/issue-74824.rs @@ -1,6 +1,5 @@ #![feature(generic_associated_types)] #![feature(associated_type_defaults)] -#![allow(incomplete_features)] use std::ops::Deref; diff --git a/src/test/ui/generic-associated-types/issue-74824.stderr b/src/test/ui/generic-associated-types/issue-74824.stderr index 7a7b5fd4f1..54cb3fba2b 100644 --- a/src/test/ui/generic-associated-types/issue-74824.stderr +++ b/src/test/ui/generic-associated-types/issue-74824.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Box: Copy` is not satisfied - --> $DIR/issue-74824.rs:8:5 + --> $DIR/issue-74824.rs:7:5 | LL | type Copy: Copy = Box; | ^^^^^^^^^^^^^^----^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | type Copy: Copy = Box; | the trait `Copy` is not implemented for `Box` error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/issue-74824.rs:8:5 + --> $DIR/issue-74824.rs:7:5 | LL | type Copy: Copy = Box; | ^^^^^^^^^^^^^^----^^^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/issue-76407.rs b/src/test/ui/generic-associated-types/issue-76407.rs new file mode 100644 index 0000000000..a8141829ba --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76407.rs @@ -0,0 +1,27 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait Marker {} + +impl Marker for u32 {} + +trait MyTrait { + type Item<'a>; +} + +struct MyStruct; + +impl MyTrait for MyStruct { + type Item<'a> = u32; +} + +fn ty_check() +where + T: MyTrait, + for<'a> T::Item<'a>: Marker +{} + +fn main() { + ty_check::(); +} diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs index 3db3c38216..1dad856d5a 100644 --- a/src/test/ui/generic-associated-types/issue-76535.rs +++ b/src/test/ui/generic-associated-types/issue-76535.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING the feature pub trait SubTrait {} diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr index d9829e5960..45af30e396 100644 --- a/src/test/ui/generic-associated-types/issue-76535.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.stderr @@ -1,20 +1,11 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-76535.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0107]: missing generics for associated type `SuperTrait::SubType` - --> $DIR/issue-76535.rs:37:33 + --> $DIR/issue-76535.rs:36:33 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-76535.rs:7:10 + --> $DIR/issue-76535.rs:6:10 | LL | type SubType<'a>: SubTrait; | ^^^^^^^ -- @@ -24,14 +15,14 @@ LL | let sub: Box = SubStruct>> = Box::new(SuperS | ^^^^^^^^^^^ error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/issue-76535.rs:37:14 + --> $DIR/issue-76535.rs:36:14 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | = help: consider moving `SubType` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-76535.rs:7:10 + --> $DIR/issue-76535.rs:6:10 | LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... @@ -39,14 +30,14 @@ LL | type SubType<'a>: SubTrait; | ^^^^^^^ ...because it contains the generic associated type `SubType` error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/issue-76535.rs:37:57 + --> $DIR/issue-76535.rs:36:57 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | = help: consider moving `SubType` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-76535.rs:7:10 + --> $DIR/issue-76535.rs:6:10 | LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... @@ -55,7 +46,7 @@ LL | type SubType<'a>: SubTrait; = note: required because of the requirements on the impl of `CoerceUnsized>>>` for `Box` = note: required by cast to type `Box>>` -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/generic-associated-types/issue-76826.rs b/src/test/ui/generic-associated-types/issue-76826.rs new file mode 100644 index 0000000000..d3201a156a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76826.rs @@ -0,0 +1,44 @@ +// run-pass + +#![feature(generic_associated_types)] + +pub trait Iter { + type Item<'a> where Self: 'a; + + fn next<'a>(&'a mut self) -> Option>; + + fn for_each(mut self, mut f: F) + where Self: Sized, F: for<'a> FnMut(Self::Item<'a>) + { + while let Some(item) = self.next() { + f(item); + } + } +} + +pub struct Windows { + items: Vec, + start: usize, + len: usize, +} + +impl Windows { + pub fn new(items: Vec, len: usize) -> Self { + Self { items, start: 0, len } + } +} + +impl Iter for Windows { + type Item<'a> where T: 'a = &'a mut [T]; + + fn next<'a>(&'a mut self) -> Option> { + let slice = self.items.get_mut(self.start..self.start + self.len)?; + self.start += 1; + Some(slice) + } +} + +fn main() { + Windows::new(vec![1, 2, 3, 4, 5], 3) + .for_each(|slice| println!("{:?}", slice)); +} diff --git a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs new file mode 100644 index 0000000000..850d83be68 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs @@ -0,0 +1,40 @@ +// Test for diagnostics when we have mismatched lifetime due to implict 'static lifetime in GATs + +// check-fail + +#![feature(generic_associated_types)] + +pub trait A {} +impl A for &dyn A {} +impl A for Box {} + +pub trait B { + type T<'a>: A; +} + +impl B for () { + // `'a` doesn't match implicit `'static`: suggest `'_` + type T<'a> = Box; //~ incompatible lifetime on type +} + +trait C {} +impl C for Box {} +pub trait D { + type T<'a>: C; +} +impl D for () { + // `'a` doesn't match explicit `'static`: we *should* suggest removing `'static` + type T<'a> = Box; //~ incompatible lifetime on type +} + +trait E {} +impl E for (Box, Box) {} +pub trait F { + type T<'a>: E; +} +impl F for () { + // `'a` doesn't match explicit `'static`: suggest `'_` + type T<'a> = (Box, Box); //~ incompatible lifetime on type +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr new file mode 100644 index 0000000000..fedc6a341c --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr @@ -0,0 +1,87 @@ +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:17:5 + | +LL | type T<'a> = Box; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:12:17 + | +LL | type T<'a>: A; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined on the associated item at 17:12... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:17:12 + | +LL | type T<'a> = Box; + | ^^ + = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:9:20 + | +LL | impl A for Box {} + | ^ +help: consider relaxing the implicit `'static` requirement + | +LL | impl A for Box {} + | ^^^^ + +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:27:5 + | +LL | type T<'a> = Box; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:23:17 + | +LL | type T<'a>: C; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined on the associated item at 27:12... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:27:12 + | +LL | type T<'a> = Box; + | ^^ +note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:21:1 + | +LL | impl C for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:37:5 + | +LL | type T<'a> = (Box, Box); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:33:17 + | +LL | type T<'a>: E; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined on the associated item at 37:12... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:37:12 + | +LL | type T<'a> = (Box, Box); + | ^^ + = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:31:21 + | +LL | impl E for (Box, Box) {} + | ^ +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:31:33 + | +LL | impl E for (Box, Box) {} + | ^ +help: consider relaxing the implicit `'static` requirement + | +LL | impl E for (Box, Box) {} + | ^^^^ +help: consider relaxing the implicit `'static` requirement + | +LL | impl E for (Box, Box) {} + | ^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/generic-associated-types/issue-78671.rs b/src/test/ui/generic-associated-types/issue-78671.rs index 310dd51ea0..7ccf376e5c 100644 --- a/src/test/ui/generic-associated-types/issue-78671.rs +++ b/src/test/ui/generic-associated-types/issue-78671.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait CollectionFamily { diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.stderr index 0a231d22b6..802621bd18 100644 --- a/src/test/ui/generic-associated-types/issue-78671.stderr +++ b/src/test/ui/generic-associated-types/issue-78671.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `CollectionFamily::Member` - --> $DIR/issue-78671.rs:8:47 + --> $DIR/issue-78671.rs:7:47 | LL | Box::new(Family) as &dyn CollectionFamily | ^^^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-78671.rs:5:10 + --> $DIR/issue-78671.rs:4:10 | LL | type Member; | ^^^^^^ - @@ -15,14 +15,14 @@ LL | Box::new(Family) as &dyn CollectionFamily=usize> | ^^^^^^^^^ error[E0038]: the trait `CollectionFamily` cannot be made into an object - --> $DIR/issue-78671.rs:8:25 + --> $DIR/issue-78671.rs:7:25 | LL | Box::new(Family) as &dyn CollectionFamily | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object | = help: consider moving `Member` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-78671.rs:5:10 + --> $DIR/issue-78671.rs:4:10 | LL | trait CollectionFamily { | ---------------- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs index 216e426ada..7f0ac34835 100644 --- a/src/test/ui/generic-associated-types/issue-79422.rs +++ b/src/test/ui/generic-associated-types/issue-79422.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait RefCont<'a, T> { diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr index 11b4a519d5..cf0a80bb2c 100644 --- a/src/test/ui/generic-associated-types/issue-79422.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `MapLike::VRefCont` - --> $DIR/issue-79422.rs:43:36 + --> $DIR/issue-79422.rs:42:36 | LL | as Box>>; | ^^^^^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-79422.rs:21:10 + --> $DIR/issue-79422.rs:20:10 | LL | type VRefCont<'a>: RefCont<'a, V>; | ^^^^^^^^ -- @@ -15,14 +15,14 @@ LL | as Box = dyn RefCont<'_, u8>>>; | ^^^^^^^^^^^^ error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:43:12 + --> $DIR/issue-79422.rs:42:12 | LL | as Box>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object | = help: consider moving `VRefCont` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-79422.rs:21:10 + --> $DIR/issue-79422.rs:20:10 | LL | trait MapLike { | ------- this trait cannot be made into an object... @@ -30,14 +30,14 @@ LL | type VRefCont<'a>: RefCont<'a, V>; | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:42:13 + --> $DIR/issue-79422.rs:41:13 | LL | let m = Box::new(std::collections::BTreeMap::::new()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object | = help: consider moving `VRefCont` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-79422.rs:21:10 + --> $DIR/issue-79422.rs:20:10 | LL | trait MapLike { | ------- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/issue-79636-1.rs b/src/test/ui/generic-associated-types/issue-79636-1.rs index 412a9f8257..6d73fd68db 100644 --- a/src/test/ui/generic-associated-types/issue-79636-1.rs +++ b/src/test/ui/generic-associated-types/issue-79636-1.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Monad { diff --git a/src/test/ui/generic-associated-types/issue-79636-1.stderr b/src/test/ui/generic-associated-types/issue-79636-1.stderr index b7a0ef0a6d..e6f9a0c754 100644 --- a/src/test/ui/generic-associated-types/issue-79636-1.stderr +++ b/src/test/ui/generic-associated-types/issue-79636-1.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `Monad::Wrapped` - --> $DIR/issue-79636-1.rs:16:34 + --> $DIR/issue-79636-1.rs:15:34 | LL | MInner: Monad>, | ^^^^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `B` - --> $DIR/issue-79636-1.rs:6:10 + --> $DIR/issue-79636-1.rs:5:10 | LL | type Wrapped; | ^^^^^^^ - diff --git a/src/test/ui/generic-associated-types/issue-79636-2.rs b/src/test/ui/generic-associated-types/issue-79636-2.rs index ef39378e78..cdaf2e4834 100644 --- a/src/test/ui/generic-associated-types/issue-79636-2.rs +++ b/src/test/ui/generic-associated-types/issue-79636-2.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait SomeTrait { diff --git a/src/test/ui/generic-associated-types/issue-79636-2.stderr b/src/test/ui/generic-associated-types/issue-79636-2.stderr index d5ba1aaeed..9a240c6545 100644 --- a/src/test/ui/generic-associated-types/issue-79636-2.stderr +++ b/src/test/ui/generic-associated-types/issue-79636-2.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `SomeTrait::Wrapped` - --> $DIR/issue-79636-2.rs:12:18 + --> $DIR/issue-79636-2.rs:11:18 | LL | W: SomeTrait, | ^^^^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `A` - --> $DIR/issue-79636-2.rs:5:10 + --> $DIR/issue-79636-2.rs:4:10 | LL | type Wrapped: SomeTrait; | ^^^^^^^ - diff --git a/src/test/ui/generic-associated-types/issue-80433-reduced.rs b/src/test/ui/generic-associated-types/issue-80433-reduced.rs index 7c1673edc5..f15d4d8b13 100644 --- a/src/test/ui/generic-associated-types/issue-80433-reduced.rs +++ b/src/test/ui/generic-associated-types/issue-80433-reduced.rs @@ -1,6 +1,5 @@ // check-pass -#![allow(incomplete_features)] #![feature(generic_associated_types)] struct E {} diff --git a/src/test/ui/generic-associated-types/issue-80433.rs b/src/test/ui/generic-associated-types/issue-80433.rs index fd81804f23..6a1fe7519a 100644 --- a/src/test/ui/generic-associated-types/issue-80433.rs +++ b/src/test/ui/generic-associated-types/issue-80433.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -#![allow(incomplete_features)] #[derive(Default)] struct E { diff --git a/src/test/ui/generic-associated-types/issue-80433.stderr b/src/test/ui/generic-associated-types/issue-80433.stderr index 31483ff0cd..26c879193b 100644 --- a/src/test/ui/generic-associated-types/issue-80433.stderr +++ b/src/test/ui/generic-associated-types/issue-80433.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `TestMut::Output` - --> $DIR/issue-80433.rs:24:47 + --> $DIR/issue-80433.rs:23:47 | LL | fn test_simpler<'a>(dst: &'a mut impl TestMut) | ^^^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-80433.rs:10:10 + --> $DIR/issue-80433.rs:9:10 | LL | type Output<'a>; | ^^^^^^ -- diff --git a/src/test/ui/generic-associated-types/issue-81487.rs b/src/test/ui/generic-associated-types/issue-81487.rs new file mode 100644 index 0000000000..7f399c4f9a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-81487.rs @@ -0,0 +1,19 @@ +// build-pass + +#![feature(generic_associated_types)] + +trait Trait { + type Ref<'a>; +} + +impl Trait for () { + type Ref<'a> = &'a i8; +} + +struct RefRef<'a, T: Trait>(&'a ::Ref<'a>); + +fn wrap<'a, T: Trait>(reff: &'a ::Ref<'a>) -> RefRef<'a, T> { + RefRef(reff) +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs index b5512ee6d6..fa2f862422 100644 --- a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs +++ b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.rs @@ -1,7 +1,6 @@ // Regression test for #81712. #![feature(generic_associated_types)] -#![allow(incomplete_features)] trait A { type BType: B; diff --git a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr index 4a7b96db30..850b434e9b 100644 --- a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr +++ b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `C::DType` - --> $DIR/issue-81712-cyclic-traits.rs:17:19 + --> $DIR/issue-81712-cyclic-traits.rs:16:19 | LL | type CType: C; | ^^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-81712-cyclic-traits.rs:14:10 + --> $DIR/issue-81712-cyclic-traits.rs:13:10 | LL | type DType: D; | ^^^^^ - diff --git a/src/test/ui/generic-associated-types/issue-81862.rs b/src/test/ui/generic-associated-types/issue-81862.rs index 02f843b07e..e457bca0c0 100644 --- a/src/test/ui/generic-associated-types/issue-81862.rs +++ b/src/test/ui/generic-associated-types/issue-81862.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait StreamingIterator { diff --git a/src/test/ui/generic-associated-types/issue-81862.stderr b/src/test/ui/generic-associated-types/issue-81862.stderr index d7b904165c..1ba21ccd79 100644 --- a/src/test/ui/generic-associated-types/issue-81862.stderr +++ b/src/test/ui/generic-associated-types/issue-81862.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `StreamingIterator::Item` - --> $DIR/issue-81862.rs:6:40 + --> $DIR/issue-81862.rs:5:40 | LL | fn next(&mut self) -> Option; | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-81862.rs:5:10 + --> $DIR/issue-81862.rs:4:10 | LL | type Item<'a>; | ^^^^ -- diff --git a/src/test/ui/generic-associated-types/issue-86483.rs b/src/test/ui/generic-associated-types/issue-86483.rs new file mode 100644 index 0000000000..a8b54c354e --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-86483.rs @@ -0,0 +1,14 @@ +// Regression test of #86483. + +#![feature(generic_associated_types)] + +pub trait IceIce //~ ERROR: the parameter type `T` may not live long enough +where + for<'a> T: 'a, +{ + type Ice<'v>: IntoIterator; + //~^ ERROR: the parameter type `T` may not live long enough + //~| ERROR: the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-86483.stderr b/src/test/ui/generic-associated-types/issue-86483.stderr new file mode 100644 index 0000000000..2106b214fe --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-86483.stderr @@ -0,0 +1,36 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/issue-86483.rs:5:1 + | +LL | pub trait IceIce + | ^ - help: consider adding an explicit lifetime bound...: `T: 'a` + | _| + | | +LL | | where +LL | | for<'a> T: 'a, +LL | | { +... | +LL | | +LL | | } + | |_^ ...so that the type `T` will meet its required lifetime bounds + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/issue-86483.rs:9:5 + | +LL | pub trait IceIce + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... +LL | type Ice<'v>: IntoIterator; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-86483.rs:9:32 + | +LL | pub trait IceIce + | - help: consider adding an explicit lifetime bound...: `T: 'v` +... +LL | type Ice<'v>: IntoIterator; + | ^^^^^^^^^^^^ ...so that the reference type `&'v T` does not outlive the data it points at + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/generic-associated-types/iterable.rs b/src/test/ui/generic-associated-types/iterable.rs index 600a69006c..952fca8ab8 100644 --- a/src/test/ui/generic-associated-types/iterable.rs +++ b/src/test/ui/generic-associated-types/iterable.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] // run-pass diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs index 2de4c7b849..6db249221b 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs @@ -2,9 +2,6 @@ // generics for a generic associated type. #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete -//~| NOTE `#[warn(incomplete_features)]` on by default -//~| NOTE see issue #44265 trait X { type Y; diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr index c94155d13c..8af9fbed87 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/method-unsatified-assoc-type-predicate.rs:4:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied - --> $DIR/method-unsatified-assoc-type-predicate.rs:29:7 + --> $DIR/method-unsatified-assoc-type-predicate.rs:26:7 | LL | struct S; | --------- @@ -24,6 +15,6 @@ LL | a.f(); `::Y = i32` which is required by `S: M` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/generic-associated-types/missing_lifetime_args.rs b/src/test/ui/generic-associated-types/missing_lifetime_args.rs index de24361dfd..cd918157f7 100644 --- a/src/test/ui/generic-associated-types/missing_lifetime_args.rs +++ b/src/test/ui/generic-associated-types/missing_lifetime_args.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` trait X { type Y<'a, 'b>; diff --git a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr index 73829594c8..95b048d36c 100644 --- a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr +++ b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr @@ -1,20 +1,11 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing_lifetime_args.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0107]: missing generics for associated type `X::Y` - --> $DIR/missing_lifetime_args.rs:14:32 + --> $DIR/missing_lifetime_args.rs:13:32 | LL | fn foo<'c, 'd>(_arg: Box>) {} | ^ expected 2 lifetime arguments | note: associated type defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/missing_lifetime_args.rs:5:10 + --> $DIR/missing_lifetime_args.rs:4:10 | LL | type Y<'a, 'b>; | ^ -- -- @@ -24,7 +15,7 @@ LL | fn foo<'c, 'd>(_arg: Box = (&'c u32, &'d u32)>>) {} | ^^^^^^^^^ error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied - --> $DIR/missing_lifetime_args.rs:17:26 + --> $DIR/missing_lifetime_args.rs:16:26 | LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} | ^^^ -- -- supplied 2 lifetime arguments @@ -32,7 +23,7 @@ LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} | expected 3 lifetime arguments | note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` - --> $DIR/missing_lifetime_args.rs:8:8 + --> $DIR/missing_lifetime_args.rs:7:8 | LL | struct Foo<'a, 'b, 'c> { | ^^^ -- -- -- @@ -42,7 +33,7 @@ LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {} | ^^^^ error[E0107]: this struct takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing_lifetime_args.rs:20:16 + --> $DIR/missing_lifetime_args.rs:19:16 | LL | fn f<'a>(_arg: Foo<'a>) {} | ^^^ -- supplied 1 lifetime argument @@ -50,7 +41,7 @@ LL | fn f<'a>(_arg: Foo<'a>) {} | expected 3 lifetime arguments | note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` - --> $DIR/missing_lifetime_args.rs:8:8 + --> $DIR/missing_lifetime_args.rs:7:8 | LL | struct Foo<'a, 'b, 'c> { | ^^^ -- -- -- @@ -59,6 +50,6 @@ help: add missing lifetime arguments LL | fn f<'a>(_arg: Foo<'a, 'b, 'c>) {} | ^^^^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/missing_lifetime_const.rs b/src/test/ui/generic-associated-types/missing_lifetime_const.rs index 37cb7cab12..e3e78dd96f 100644 --- a/src/test/ui/generic-associated-types/missing_lifetime_const.rs +++ b/src/test/ui/generic-associated-types/missing_lifetime_const.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING the feature trait Foo { type Assoc<'a, const N: usize>; diff --git a/src/test/ui/generic-associated-types/missing_lifetime_const.stderr b/src/test/ui/generic-associated-types/missing_lifetime_const.stderr index 6c66312e7b..02d3cd2e8d 100644 --- a/src/test/ui/generic-associated-types/missing_lifetime_const.stderr +++ b/src/test/ui/generic-associated-types/missing_lifetime_const.stderr @@ -1,20 +1,11 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing_lifetime_const.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/missing_lifetime_const.rs:9:24 + --> $DIR/missing_lifetime_const.rs:8:24 | LL | let _: ::Assoc<3>; | ^^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/missing_lifetime_const.rs:5:10 + --> $DIR/missing_lifetime_const.rs:4:10 | LL | type Assoc<'a, const N: usize>; | ^^^^^ -- @@ -23,6 +14,6 @@ help: add missing lifetime argument LL | let _: ::Assoc<'a, 3>; | ^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs index 3f92c031e1..0508cc2dae 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind.rs +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] #![feature(associated_type_defaults)] diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr index b6f600964c..db469597f9 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind.stderr @@ -1,5 +1,5 @@ error[E0107]: this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied - --> $DIR/parameter_number_and_kind.rs:13:24 + --> $DIR/parameter_number_and_kind.rs:12:24 | LL | type FErr1 = Self::E<'static, 'static>; | ^ ------- help: remove this lifetime argument @@ -7,19 +7,19 @@ LL | type FErr1 = Self::E<'static, 'static>; | expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/parameter_number_and_kind.rs:10:10 + --> $DIR/parameter_number_and_kind.rs:9:10 | LL | type E<'a, T>; | ^ -- error[E0107]: this associated type takes 1 generic argument but 0 generic arguments were supplied - --> $DIR/parameter_number_and_kind.rs:13:24 + --> $DIR/parameter_number_and_kind.rs:12:24 | LL | type FErr1 = Self::E<'static, 'static>; | ^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/parameter_number_and_kind.rs:10:10 + --> $DIR/parameter_number_and_kind.rs:9:10 | LL | type E<'a, T>; | ^ - @@ -29,7 +29,7 @@ LL | type FErr1 = Self::E<'static, 'static, T>; | ^^^ error[E0107]: this associated type takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/parameter_number_and_kind.rs:16:27 + --> $DIR/parameter_number_and_kind.rs:15:27 | LL | type FErr2 = Self::E<'static, T, u32>; | ^ --- help: remove this generic argument @@ -37,7 +37,7 @@ LL | type FErr2 = Self::E<'static, T, u32>; | expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/parameter_number_and_kind.rs:10:10 + --> $DIR/parameter_number_and_kind.rs:9:10 | LL | type E<'a, T>; | ^ - diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs index 74b9cec1da..6ca0bc6ddb 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] #![feature(associated_type_defaults)] diff --git a/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr index bdd1c895fd..1458bf0c4a 100644 --- a/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr +++ b/src/test/ui/generic-associated-types/parameter_number_and_kind_impl.stderr @@ -1,5 +1,5 @@ error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration - --> $DIR/parameter_number_and_kind_impl.rs:16:11 + --> $DIR/parameter_number_and_kind_impl.rs:15:11 | LL | type A<'a>; | ---- lifetimes in impl do not match this type in trait @@ -8,7 +8,7 @@ LL | type A = u32; | ^ lifetimes do not match type in trait error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters - --> $DIR/parameter_number_and_kind_impl.rs:18:12 + --> $DIR/parameter_number_and_kind_impl.rs:17:12 | LL | type B<'a, 'b>; | -- -- @@ -21,7 +21,7 @@ LL | type B<'a, T> = Vec; | found 1 type parameter error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration - --> $DIR/parameter_number_and_kind_impl.rs:20:11 + --> $DIR/parameter_number_and_kind_impl.rs:19:11 | LL | type C; | - lifetimes in impl do not match this type in trait @@ -30,7 +30,7 @@ LL | type C<'a> = u32; | ^^^^ lifetimes do not match type in trait error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters - --> $DIR/parameter_number_and_kind_impl.rs:27:12 + --> $DIR/parameter_number_and_kind_impl.rs:26:12 | LL | type A<'a>; | -- expected 0 type parameters @@ -39,7 +39,7 @@ LL | type A = u32; | ^ found 1 type parameter error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration - --> $DIR/parameter_number_and_kind_impl.rs:29:11 + --> $DIR/parameter_number_and_kind_impl.rs:28:11 | LL | type B<'a, 'b>; | -------- lifetimes in impl do not match this type in trait @@ -48,7 +48,7 @@ LL | type B<'a> = u32; | ^^^^ lifetimes do not match type in trait error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters - --> $DIR/parameter_number_and_kind_impl.rs:31:12 + --> $DIR/parameter_number_and_kind_impl.rs:30:12 | LL | type C; | - expected 0 type parameters diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs index b10bfea9fe..be85598b7b 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'a>; diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr index 8abc4ccc9a..2b265e9216 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-expected-token.stderr @@ -1,19 +1,10 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` - --> $DIR/trait-path-expected-token.rs:8:33 + --> $DIR/trait-path-expected-token.rs:7:33 | LL | fn f1<'a>(arg : Box>) {} | - ^ expected one of 7 possible tokens | | | maybe try to close unmatched angle bracket -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-path-expected-token.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs b/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs index 5e50c6b35c..d57c2813b3 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING: the feature `generic_associated_types` is incomplete mod error1 { trait X { diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr index 27e1a750b2..b1fea6d33a 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -1,5 +1,5 @@ error: expected expression, found `)` - --> $DIR/trait-path-expressions.rs:9:39 + --> $DIR/trait-path-expressions.rs:8:39 | LL | fn f1<'a>(arg : Box>) {} | - ^ expected expression @@ -7,21 +7,12 @@ LL | fn f1<'a>(arg : Box>) {} | while parsing a const generic argument starting here error: expected one of `,`, `:`, or `>`, found `=` - --> $DIR/trait-path-expressions.rs:19:36 + --> $DIR/trait-path-expressions.rs:18:36 | LL | fn f2<'a>(arg : Box>) {} | - ^ expected one of `,`, `:`, or `>` | | | maybe try to close unmatched angle bracket -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-path-expressions.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs index 94dda17aad..7914864807 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'a>; diff --git a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr index f6038566e5..c290815042 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -1,5 +1,5 @@ error: expected one of `>`, a const expression, lifetime, or type, found `:` - --> $DIR/trait-path-missing-gen_arg.rs:9:30 + --> $DIR/trait-path-missing-gen_arg.rs:8:30 | LL | fn f1<'a>(arg : Box>) {} | ^ expected one of `>`, a const expression, lifetime, or type @@ -10,13 +10,13 @@ LL | fn f1<'a>(arg : Box<{ dyn X< : 32 } >>) {} | ^ ^ error: expected parameter name, found `>` - --> $DIR/trait-path-missing-gen_arg.rs:9:36 + --> $DIR/trait-path-missing-gen_arg.rs:8:36 | LL | fn f1<'a>(arg : Box>) {} | ^ expected parameter name error: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` - --> $DIR/trait-path-missing-gen_arg.rs:9:36 + --> $DIR/trait-path-missing-gen_arg.rs:8:36 | LL | fn f1<'a>(arg : Box>) {} | ^ @@ -25,28 +25,19 @@ LL | fn f1<'a>(arg : Box>) {} | help: missing `,` error: expected one of `>`, a const expression, lifetime, or type, found `=` - --> $DIR/trait-path-missing-gen_arg.rs:17:30 + --> $DIR/trait-path-missing-gen_arg.rs:16:30 | LL | fn f1<'a>(arg : Box>) {} | - ^ expected one of `>`, a const expression, lifetime, or type | | | maybe try to close unmatched angle bracket -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-path-missing-gen_arg.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0747]: constant provided when a type was expected - --> $DIR/trait-path-missing-gen_arg.rs:9:23 + --> $DIR/trait-path-missing-gen_arg.rs:8:23 | LL | fn f1<'a>(arg : Box>) {} | ^^^^^^^^^^^ -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.rs b/src/test/ui/generic-associated-types/parse/trait-path-segments.rs index eba30e1438..e943f075f5 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-segments.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING: the feature `generic_associated_types` is incomplete const _: () = { trait X { diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr index c82953aaed..bfb109fbfa 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` - --> $DIR/trait-path-segments.rs:9:36 + --> $DIR/trait-path-segments.rs:8:36 | LL | fn f1<'a>(arg : Box>) {} | - ^ expected one of 8 possible tokens @@ -7,7 +7,7 @@ LL | fn f1<'a>(arg : Box>) {} | maybe try to close unmatched angle bracket error: expected one of `,`, `::`, `:`, or `>`, found `=` - --> $DIR/trait-path-segments.rs:20:35 + --> $DIR/trait-path-segments.rs:19:35 | LL | impl::Y<'a> = &'a u32>> Z for T {} | - ^ expected one of `,`, `::`, `:`, or `>` @@ -15,21 +15,12 @@ LL | impl::Y<'a> = &'a u32>> Z for T {} | maybe try to close unmatched angle bracket error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` - --> $DIR/trait-path-segments.rs:31:25 + --> $DIR/trait-path-segments.rs:30:25 | LL | impl = &'a u32>> Z for T {} | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` | | | maybe try to close unmatched angle bracket -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-path-segments.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs index d7a0ef4916..4846af96d3 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] - //~^ the feature `generic_associated_types` is incomplete trait X { type Y<'a>; diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr index 5685e5208c..59b53c7038 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr @@ -1,20 +1,11 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-path-type-error-once-implemented.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/trait-path-type-error-once-implemented.rs:9:29 + --> $DIR/trait-path-type-error-once-implemented.rs:8:29 | LL | fn f2<'a>(arg : Box = &'a ()>>) {} | ^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/trait-path-type-error-once-implemented.rs:5:10 + --> $DIR/trait-path-type-error-once-implemented.rs:4:10 | LL | type Y<'a>; | ^ -- @@ -24,7 +15,7 @@ LL | fn f2<'a>(arg : Box = &'a ()>>) {} | ^^^ error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/trait-path-type-error-once-implemented.rs:9:29 + --> $DIR/trait-path-type-error-once-implemented.rs:8:29 | LL | fn f2<'a>(arg : Box = &'a ()>>) {} | ^--- help: remove these generics @@ -32,11 +23,11 @@ LL | fn f2<'a>(arg : Box = &'a ()>>) {} | expected 0 generic arguments | note: associated type defined here, with 0 generic parameters - --> $DIR/trait-path-type-error-once-implemented.rs:5:10 + --> $DIR/trait-path-type-error-once-implemented.rs:4:10 | LL | type Y<'a>; | ^ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.rs b/src/test/ui/generic-associated-types/parse/trait-path-types.rs index 522b3edc63..856253cc7f 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-types.rs +++ b/src/test/ui/generic-associated-types/parse/trait-path-types.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARNING: the feature `generic_associated_types` is incomplete trait X { type Y<'a>; diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr index ac791c2248..c0fa41b9e0 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr @@ -1,5 +1,5 @@ error: expected one of `,`, `:`, or `>`, found `=` - --> $DIR/trait-path-types.rs:9:37 + --> $DIR/trait-path-types.rs:8:37 | LL | fn f<'a>(arg : Box>) {} | - ^ expected one of `,`, `:`, or `>` @@ -7,7 +7,7 @@ LL | fn f<'a>(arg : Box>) {} | maybe try to close unmatched angle bracket error: expected one of `,`, `:`, or `>`, found `=` - --> $DIR/trait-path-types.rs:14:37 + --> $DIR/trait-path-types.rs:13:37 | LL | fn f1<'a>(arg : Box) = &'a ()>>) {} | - ^ expected one of `,`, `:`, or `>` @@ -15,21 +15,12 @@ LL | fn f1<'a>(arg : Box) = &'a ()>>) {} | maybe try to close unmatched angle bracket error: expected one of `,`, `:`, or `>`, found `=` - --> $DIR/trait-path-types.rs:19:33 + --> $DIR/trait-path-types.rs:18:33 | LL | fn f1<'a>(arg : Box>) {} | -- ^ expected one of `,`, `:`, or `>` | | | maybe try to close unmatched angle bracket -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/trait-path-types.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors diff --git a/src/test/ui/generic-associated-types/pointer_family.rs b/src/test/ui/generic-associated-types/pointer_family.rs index b322b752a1..da86e7f274 100644 --- a/src/test/ui/generic-associated-types/pointer_family.rs +++ b/src/test/ui/generic-associated-types/pointer_family.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] // check-pass diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs index 0cd676a9b3..7517e1fa9d 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -2,7 +2,6 @@ // `feature(trivial_bounds)`. #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete trait Print { fn print(); diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr index d27e46f683..d5e9caf9ec 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/projection-bound-cycle-generic.rs:4:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0275]: overflow evaluating the requirement `::Item: Sized` - --> $DIR/projection-bound-cycle-generic.rs:45:5 + --> $DIR/projection-bound-cycle-generic.rs:44:5 | LL | struct OnlySized where T: Sized { f: T } | - required by this bound in `OnlySized` @@ -16,6 +7,6 @@ LL | struct OnlySized where T: Sized { f: T } LL | type Assoc = OnlySized<::Item>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs index 5043fe5c08..8f8cb679e9 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -3,7 +3,6 @@ // proven when a bound and a where clause of an associated type are the same. #![feature(generic_associated_types)] -//~^ WARNING the feature `generic_associated_types` is incomplete #![feature(trivial_bounds)] trait Print { diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr index 400b664f97..fac62fef1e 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -1,14 +1,5 @@ -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/projection-bound-cycle.rs:5:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0275]: overflow evaluating the requirement `::Item: Sized` - --> $DIR/projection-bound-cycle.rs:47:5 + --> $DIR/projection-bound-cycle.rs:46:5 | LL | struct OnlySized where T: Sized { f: T } | - required by this bound in `OnlySized` @@ -16,6 +7,6 @@ LL | struct OnlySized where T: Sized { f: T } LL | type Assoc = OnlySized<::Item>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs index 0024e127a9..b976ee3261 100644 --- a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs +++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] pub trait X { diff --git a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr index aec8786256..315bef16c5 100644 --- a/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr +++ b/src/test/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr @@ -1,17 +1,17 @@ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/projection-type-lifetime-mismatch.rs:18:5 + --> $DIR/projection-type-lifetime-mismatch.rs:17:5 | LL | x.m() | ^^^^^ lifetime `'static` required error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/projection-type-lifetime-mismatch.rs:23:5 + --> $DIR/projection-type-lifetime-mismatch.rs:22:5 | LL | x.m() | ^^^^^ lifetime `'static` required error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/projection-type-lifetime-mismatch.rs:28:5 + --> $DIR/projection-type-lifetime-mismatch.rs:27:5 | LL | x.m() | ^^^^^ lifetime `'static` required diff --git a/src/test/ui/generic-associated-types/shadowing.rs b/src/test/ui/generic-associated-types/shadowing.rs index 44528ca1da..2a9763457d 100644 --- a/src/test/ui/generic-associated-types/shadowing.rs +++ b/src/test/ui/generic-associated-types/shadowing.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait Shadow<'a> { diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr index d45ef83873..857757f894 100644 --- a/src/test/ui/generic-associated-types/shadowing.stderr +++ b/src/test/ui/generic-associated-types/shadowing.stderr @@ -1,5 +1,5 @@ error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters - --> $DIR/shadowing.rs:19:14 + --> $DIR/shadowing.rs:18:14 | LL | trait ShadowT { | - first use of `T` @@ -7,7 +7,7 @@ LL | type Bar; | ^ already used error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters - --> $DIR/shadowing.rs:28:14 + --> $DIR/shadowing.rs:27:14 | LL | impl NoShadowT for Option { | - first use of `T` @@ -15,7 +15,7 @@ LL | type Bar = i32; | ^ already used error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope - --> $DIR/shadowing.rs:14:14 + --> $DIR/shadowing.rs:13:14 | LL | impl<'a> NoShadow<'a> for &'a u32 { | -- first declared here @@ -23,7 +23,7 @@ LL | type Bar<'a> = i32; | ^^ lifetime `'a` already in scope error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope - --> $DIR/shadowing.rs:5:14 + --> $DIR/shadowing.rs:4:14 | LL | trait Shadow<'a> { | -- first declared here diff --git a/src/test/ui/generic-associated-types/streaming_iterator.rs b/src/test/ui/generic-associated-types/streaming_iterator.rs index d814f7140d..2feff9f4c6 100644 --- a/src/test/ui/generic-associated-types/streaming_iterator.rs +++ b/src/test/ui/generic-associated-types/streaming_iterator.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(generic_associated_types)] use std::fmt::Display; diff --git a/src/test/ui/generic-associated-types/trait-objects.rs b/src/test/ui/generic-associated-types/trait-objects.rs index 997a550b0e..559e6758a3 100644 --- a/src/test/ui/generic-associated-types/trait-objects.rs +++ b/src/test/ui/generic-associated-types/trait-objects.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -#![allow(incomplete_features)] trait StreamingIterator { type Item<'a> where Self: 'a; diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr index a8f1768ba2..6429bb8159 100644 --- a/src/test/ui/generic-associated-types/trait-objects.stderr +++ b/src/test/ui/generic-associated-types/trait-objects.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `StreamingIterator` cannot be made into an object - --> $DIR/trait-objects.rs:11:16 + --> $DIR/trait-objects.rs:10:21 | LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object | = help: consider moving `Item` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/trait-objects.rs:5:10 + --> $DIR/trait-objects.rs:4:10 | LL | trait StreamingIterator { | ----------------- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs index 7bcc7ba752..8b40dac574 100644 --- a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs +++ b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] pub trait X { diff --git a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr index 1c81d33ccf..772d027685 100644 --- a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr +++ b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr @@ -1,5 +1,5 @@ warning: unnecessary lifetime parameter `'a` - --> $DIR/unsatified-item-lifetime-bound.rs:5:12 + --> $DIR/unsatified-item-lifetime-bound.rs:4:12 | LL | type Y<'a: 'static>; | ^^^^^^^^^^^ @@ -7,39 +7,39 @@ LL | type Y<'a: 'static>; = help: you can use the `'static` lifetime directly, in place of `'a` error[E0478]: lifetime bound not satisfied - --> $DIR/unsatified-item-lifetime-bound.rs:14:8 + --> $DIR/unsatified-item-lifetime-bound.rs:13:8 | LL | f: ::Y<'a>, | ^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 13:10 - --> $DIR/unsatified-item-lifetime-bound.rs:13:10 +note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 12:10 + --> $DIR/unsatified-item-lifetime-bound.rs:12:10 | LL | struct B<'a, T: for<'r> X = &'r ()>> { | ^^ = note: but lifetime parameter must outlive the static lifetime error[E0478]: lifetime bound not satisfied - --> $DIR/unsatified-item-lifetime-bound.rs:19:8 + --> $DIR/unsatified-item-lifetime-bound.rs:18:8 | LL | f: ::Y<'a>, | ^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 18:10 - --> $DIR/unsatified-item-lifetime-bound.rs:18:10 +note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 17:10 + --> $DIR/unsatified-item-lifetime-bound.rs:17:10 | LL | struct C<'a, T: X> { | ^^ = note: but lifetime parameter must outlive the static lifetime error[E0478]: lifetime bound not satisfied - --> $DIR/unsatified-item-lifetime-bound.rs:24:8 + --> $DIR/unsatified-item-lifetime-bound.rs:23:8 | LL | f: <() as X>::Y<'a>, | ^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 23:10 - --> $DIR/unsatified-item-lifetime-bound.rs:23:10 +note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 22:10 + --> $DIR/unsatified-item-lifetime-bound.rs:22:10 | LL | struct D<'a> { | ^^ diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs index 99d5bcf2ba..6466bf98df 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(generic_associated_types)] trait ATy { diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr index 5d612284a2..d2482b2998 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -1,17 +1,17 @@ error[E0477]: the type `&'b ()` does not fulfill the required lifetime - --> $DIR/unsatisfied-outlives-bound.rs:9:5 + --> $DIR/unsatisfied-outlives-bound.rs:8:5 | LL | type Item<'a> = &'b (); | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: type must outlive the lifetime `'a` as defined on the associated item at 9:15 - --> $DIR/unsatisfied-outlives-bound.rs:9:15 +note: type must outlive the lifetime `'a` as defined on the associated item at 8:15 + --> $DIR/unsatisfied-outlives-bound.rs:8:15 | LL | type Item<'a> = &'b (); | ^^ error[E0477]: the type `&'a ()` does not fulfill the required lifetime - --> $DIR/unsatisfied-outlives-bound.rs:18:5 + --> $DIR/unsatisfied-outlives-bound.rs:17:5 | LL | type Item<'a> = &'a (); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/variance_constraints.rs b/src/test/ui/generic-associated-types/variance_constraints.rs index 36db80706b..7bc250ee87 100644 --- a/src/test/ui/generic-associated-types/variance_constraints.rs +++ b/src/test/ui/generic-associated-types/variance_constraints.rs @@ -1,7 +1,6 @@ // check-pass // issue #69184 #![feature(generic_associated_types)] -#![allow(incomplete_features)] trait A { type B<'a>; diff --git a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs b/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs index b560cc2ce7..12db143e47 100644 --- a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs +++ b/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs @@ -11,25 +11,25 @@ // compatibility concern. struct Snobound<'a, P = Self> { x: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] enum Enobound<'a, P = Self> { A, B(Option<&'a P>) } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] // Disallowing `Self` in defaults sidesteps need to check the bounds // on the defaults in cases like these. struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> } -//~^ ERROR type parameters cannot use `Self` in their defaults [E0735] +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] fn demo_usages() { // An ICE means you only get the error from the first line of the diff --git a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr b/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr index 689ffbd0fe..f3a550801b 100644 --- a/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr +++ b/src/test/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr @@ -1,38 +1,38 @@ -error[E0735]: type parameters cannot use `Self` in their defaults +error[E0735]: generic parameters cannot use `Self` in their defaults --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25 | LL | struct Snobound<'a, P = Self> { x: Option<&'a P> } - | ^^^^ `Self` in type parameter default + | ^^^^ `Self` in generic parameter default -error[E0735]: type parameters cannot use `Self` in their defaults +error[E0735]: generic parameters cannot use `Self` in their defaults --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23 | LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) } - | ^^^^ `Self` in type parameter default + | ^^^^ `Self` in generic parameter default -error[E0735]: type parameters cannot use `Self` in their defaults +error[E0735]: generic parameters cannot use `Self` in their defaults --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24 | LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> } - | ^^^^ `Self` in type parameter default + | ^^^^ `Self` in generic parameter default -error[E0735]: type parameters cannot use `Self` in their defaults +error[E0735]: generic parameters cannot use `Self` in their defaults --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31 | LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> } - | ^^^^ `Self` in type parameter default + | ^^^^ `Self` in generic parameter default -error[E0735]: type parameters cannot use `Self` in their defaults +error[E0735]: generic parameters cannot use `Self` in their defaults --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29 | LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) } - | ^^^^ `Self` in type parameter default + | ^^^^ `Self` in generic parameter default -error[E0735]: type parameters cannot use `Self` in their defaults +error[E0735]: generic parameters cannot use `Self` in their defaults --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30 | LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> } - | ^^^^ `Self` in type parameter default + | ^^^^ `Self` in generic parameter default error: aborting due to 6 previous errors 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 index 1733012b9c..9281dda678 100644 --- 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 @@ -11,12 +11,8 @@ fn foo() { //~| ERROR range-to patterns with `...` are not allowed if let ..5 = 0 {} //~^ ERROR half-open range patterns are unstable - if let 5.. = 0 {} - //~^ ERROR half-open range patterns are unstable if let 5..= = 0 {} - //~^ ERROR half-open range patterns are unstable - //~| ERROR inclusive range with no end + //~^ ERROR inclusive range with no end if let 5... = 0 {} - //~^ ERROR half-open range patterns are unstable - //~| ERROR inclusive range with no end + //~^ 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 index 62d54463a4..a04883ae14 100644 --- 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 @@ -5,7 +5,7 @@ LL | if let ...5 = 0 {} | ^^^ help: use `..=` instead error[E0586]: inclusive range with no end - --> $DIR/feature-gate-half-open-range-patterns.rs:16:13 + --> $DIR/feature-gate-half-open-range-patterns.rs:14:13 | LL | if let 5..= = 0 {} | ^^^ help: use `..` instead @@ -13,7 +13,7 @@ LL | if let 5..= = 0 {} = 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:19:13 + --> $DIR/feature-gate-half-open-range-patterns.rs:16:13 | LL | if let 5... = 0 {} | ^^^ help: use `..` instead @@ -47,34 +47,7 @@ LL | if let ..5 = 0 {} = note: see issue #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:14:12 - | -LL | if let 5.. = 0 {} - | ^^^ - | - = note: see issue #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:16:12 - | -LL | if let 5..= = 0 {} - | ^^^^ - | - = note: see issue #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:19:12 - | -LL | if let 5... = 0 {} - | ^^^^ - | - = note: see issue #67264 for more information - = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable - -error: aborting due to 9 previous errors +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/range_pat_interactions0.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs new file mode 100644 index 0000000000..4f478a6988 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(incomplete_features)] +#![feature(exclusive_range_pattern)] +#![feature(half_open_range_patterns)] +#![feature(inline_const)] + +fn main() { + let mut if_lettable = vec![]; + let mut first_or = vec![]; + let mut or_two = vec![]; + let mut range_from = vec![]; + let mut bottom = vec![]; + + for x in -9 + 1..=(9 - 2) { + if let -1..=0 | 2..3 | 4 = x { + if_lettable.push(x) + } + match x { + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } + assert_eq!(if_lettable, [-1, 0, 2, 4]); + assert_eq!(first_or, [-3, -2, -1, 1]); + assert_eq!(or_two, [0, 2, 3, 4, 6]); + assert_eq!(range_from, [-5, -4, 7]); + assert_eq!(bottom, [-7, -6]); +} diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs new file mode 100644 index 0000000000..55353999b6 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -0,0 +1,29 @@ +fn main() { + let mut if_lettable = Vec::::new(); + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + let mut errors_only = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + if let n @ 2..3|4 = x { + //~^ error: variable `n` is not bound in all patterns + //~| exclusive range pattern syntax is experimental + errors_only.push(x); + } else if let 2..3 | 4 = x { + //~^ exclusive range pattern syntax is experimental + if_lettable.push(x); + } + match x as i32 { + 0..5+1 => errors_only.push(x), + //~^ error: expected one of `=>`, `if`, or `|`, found `+` + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } +} diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr new file mode 100644 index 0000000000..19ebcaf0f3 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -0,0 +1,36 @@ +error: expected one of `=>`, `if`, or `|`, found `+` + --> $DIR/range_pat_interactions1.rs:19:17 + | +LL | 0..5+1 => errors_only.push(x), + | ^ expected one of `=>`, `if`, or `|` + +error[E0408]: variable `n` is not bound in all patterns + --> $DIR/range_pat_interactions1.rs:10:25 + | +LL | if let n @ 2..3|4 = x { + | - ^ pattern doesn't bind `n` + | | + | variable not in all patterns + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:10:20 + | +LL | if let n @ 2..3|4 = x { + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:14:23 + | +LL | } else if let 2..3 | 4 = x { + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0408, E0658. +For more information about an error, try `rustc --explain E0408`. diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs new file mode 100644 index 0000000000..4615ebd688 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions2.rs @@ -0,0 +1,21 @@ +fn main() { + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + let mut errors_only = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + match x as i32 { + 0..=(5+1) => errors_only.push(x), + //~^ error: inclusive range with no end + //~| error: expected one of `=>`, `if`, or `|`, found `(` + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } +} diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr new file mode 100644 index 0000000000..13a5542a47 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -0,0 +1,17 @@ +error[E0586]: inclusive range with no end + --> $DIR/range_pat_interactions2.rs:10:14 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: expected one of `=>`, `if`, or `|`, found `(` + --> $DIR/range_pat_interactions2.rs:10:17 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^ expected one of `=>`, `if`, or `|` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0586`. 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 new file mode 100644 index 0000000000..0afb512605 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs @@ -0,0 +1,24 @@ +fn main() { + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + match x as i32 { + 8.. => bottom.push(x), + 1 | -3..0 => first_or.push(x), + //~^ exclusive range pattern syntax is experimental + y @ (0..5 | 6) => or_two.push(y), + //~^ exclusive range pattern syntax is experimental + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + //~^ inline-const is experimental + //~| 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 + 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 new file mode 100644 index 0000000000..8278e7cc6c --- /dev/null +++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr @@ -0,0 +1,57 @@ +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 for more information + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: inline-const is experimental + --> $DIR/range_pat_interactions3.rs:14:20 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:10:17 + | +LL | 1 | -3..0 => first_or.push(x), + | ^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:12:18 + | +LL | y @ (0..5 | 6) => or_two.push(y), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:14:17 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:18:17 + | +LL | y @ ..-7 => assert_eq!(y, -8), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` 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/half-open-range-patterns/slice_pattern_syntax_problem0.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs new file mode 100644 index 0000000000..2884a27349 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs @@ -0,0 +1,16 @@ +#![feature(half_open_range_patterns)] +#![feature(exclusive_range_pattern)] + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a, b, c, rest @ ..] = xs; + // Consider the following example: + assert!(a == 13 && b == 1 && c == 5 && rest.len() == 5); + + // What if we wanted to pull this apart without individually binding a, b, and c? + let [first_three @ ..3, rest @ 2..] = xs; + //~^ pattern requires 2 elements but array has 8 + // This is somewhat unintuitive and makes slice patterns exceedingly verbose. + // We want to stabilize half-open RangeFrom (`X..`) patterns + // but without banning us from using them for a more efficient slice pattern syntax. +} diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr new file mode 100644 index 0000000000..ec3472a503 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr @@ -0,0 +1,9 @@ +error[E0527]: pattern requires 2 elements but array has 8 + --> $DIR/slice_pattern_syntax_problem0.rs:11:9 + | +LL | let [first_three @ ..3, rest @ 2..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 8 elements + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0527`. 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 new file mode 100644 index 0000000000..9e289b591d --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs @@ -0,0 +1,9 @@ +// Instead of allowing the previous case, maintain the feature gate for slice patterns for now. +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 new file mode 100644 index 0000000000..eadaf87767 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr @@ -0,0 +1,39 @@ +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 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 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:23 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:32 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs new file mode 100644 index 0000000000..6e7df30949 --- /dev/null +++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs @@ -0,0 +1,10 @@ +// run-pass + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + if let [3..=14, ..] = xs { + /* this variant must pass for now, unfortunately. + * This test is included here to help inform a future plan for these. + */ + }; +} diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout index e3445a4b80..ffb9f9eed4 100644 --- a/src/test/ui/hygiene/unpretty-debug.stdout +++ b/src/test/ui/hygiene/unpretty-debug.stdout @@ -8,7 +8,7 @@ #![feature /* 0#0 */(no_core)] #![no_core /* 0#0 */] -macro_rules! foo /* 0#0 */ { ($ x : ident) => { y + $ x } } +macro_rules! foo /* 0#0 */ { ($x : ident) => { y + $x } } fn bar /* 0#0 */() { let x /* 0#0 */ = 1; @@ -19,10 +19,10 @@ fn y /* 0#0 */() { } /* Expansions: -0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root -1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "foo", proc_macro: false } +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo") SyntaxContexts: -#0: parent: #0, outer_mark: (ExpnId(0), Opaque) -#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent) +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiTransparent) */ diff --git a/src/test/ui/impl-header-lifetime-elision/path-elided.stderr b/src/test/ui/impl-header-lifetime-elision/path-elided.stderr index 6500a2a55f..1c81c69620 100644 --- a/src/test/ui/impl-header-lifetime-elision/path-elided.stderr +++ b/src/test/ui/impl-header-lifetime-elision/path-elided.stderr @@ -3,6 +3,8 @@ error[E0726]: implicit elided lifetime not allowed here | LL | impl MyTrait for Foo { | ^^^- help: indicate the anonymous lifetime: `<'_>` + | + = note: assuming a `'static` lifetime... error: aborting due to previous error diff --git a/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr b/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr index ad97cb0abd..735f01379f 100644 --- a/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr +++ b/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr @@ -3,6 +3,8 @@ error[E0726]: implicit elided lifetime not allowed here | LL | impl MyTrait for u32 { | ^^^^^^^- help: indicate the anonymous lifetime: `<'_>` + | + = note: assuming a `'static` lifetime... error: aborting due to previous error diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs index 087f4582b2..c2fbbf94fd 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.rs +++ b/src/test/ui/impl-trait/auto-trait-leak.rs @@ -12,7 +12,6 @@ fn main() { fn cycle1() -> impl Clone { //~^ ERROR cycle detected send(cycle2().clone()); - //~^ ERROR cannot be sent between threads safely Rc::new(Cell::new(5)) } diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index e578c4b4f8..3eb141cc2b 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -36,37 +36,37 @@ LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... note: ...which requires computing type of `cycle2::{opaque#0}`... - --> $DIR/auto-trait-leak.rs:20:16 + --> $DIR/auto-trait-leak.rs:19:16 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires borrow-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:20:1 + --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:20:1 + --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing MIR for `cycle2`... - --> $DIR/auto-trait-leak.rs:20:1 + --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires unsafety-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:20:1 + --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires building MIR for `cycle2`... - --> $DIR/auto-trait-leak.rs:20:1 + --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:20:1 + --> $DIR/auto-trait-leak.rs:19:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,22 +84,6 @@ LL | | Rc::new(String::from("foo")) LL | | } | |_^ -error[E0277]: `Rc` cannot be sent between threads safely - --> $DIR/auto-trait-leak.rs:14:5 - | -LL | fn send(_: T) {} - | ---- required by this bound in `send` -... -LL | send(cycle2().clone()); - | ^^^^ `Rc` cannot be sent between threads safely -... -LL | fn cycle2() -> impl Clone { - | ---------- within this `impl Clone` - | - = help: within `impl Clone`, the trait `Send` is not implemented for `Rc` - = note: required because it appears within the type `impl Clone` - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0391. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/impl-trait/binding-without-value.rs b/src/test/ui/impl-trait/binding-without-value.rs deleted file mode 100644 index 6a97f28ff5..0000000000 --- a/src/test/ui/impl-trait/binding-without-value.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![allow(incomplete_features)] -#![feature(impl_trait_in_bindings)] - -fn foo() { - let _ : impl Copy; - //~^ ERROR cannot resolve opaque type -} - -fn main() {} diff --git a/src/test/ui/impl-trait/binding-without-value.stderr b/src/test/ui/impl-trait/binding-without-value.stderr deleted file mode 100644 index 0d2faeaf85..0000000000 --- a/src/test/ui/impl-trait/binding-without-value.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0720]: cannot resolve opaque type - --> $DIR/binding-without-value.rs:5:13 - | -LL | let _ : impl Copy; - | - ^^^^^^^^^ cannot resolve opaque type - | | - | this binding might not have a concrete type - | -help: set the binding to a value for a concrete type to be resolved - | -LL | let _ : impl Copy = /* value */; - | ^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/bindings-opaque.rs b/src/test/ui/impl-trait/bindings-opaque.rs deleted file mode 100644 index d1f42be077..0000000000 --- a/src/test/ui/impl-trait/bindings-opaque.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete - -const FOO: impl Copy = 42; - -static BAR: impl Copy = 42; - -fn main() { - let foo: impl Copy = 42; - - let _ = FOO.count_ones(); -//~^ ERROR no method - let _ = BAR.count_ones(); -//~^ ERROR no method - let _ = foo.count_ones(); -//~^ ERROR no method -} diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr deleted file mode 100644 index 170bd46123..0000000000 --- a/src/test/ui/impl-trait/bindings-opaque.stderr +++ /dev/null @@ -1,30 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bindings-opaque.rs:1:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -error[E0599]: no method named `count_ones` found for opaque type `impl Copy` in the current scope - --> $DIR/bindings-opaque.rs:11:17 - | -LL | let _ = FOO.count_ones(); - | ^^^^^^^^^^ method not found in `impl Copy` - -error[E0599]: no method named `count_ones` found for opaque type `impl Copy` in the current scope - --> $DIR/bindings-opaque.rs:13:17 - | -LL | let _ = BAR.count_ones(); - | ^^^^^^^^^^ method not found in `impl Copy` - -error[E0599]: no method named `count_ones` found for opaque type `impl Copy` in the current scope - --> $DIR/bindings-opaque.rs:15:17 - | -LL | let _ = foo.count_ones(); - | ^^^^^^^^^^ method not found in `impl Copy` - -error: aborting due to 3 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/impl-trait/bindings.rs b/src/test/ui/impl-trait/bindings.rs deleted file mode 100644 index fd79ba68fb..0000000000 --- a/src/test/ui/impl-trait/bindings.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete - -fn a(x: T) { - const foo: impl Clone = x; - //~^ ERROR attempt to use a non-constant value in a constant -} - -fn b(x: T) { - let _ = move || { - const foo: impl Clone = x; - //~^ ERROR attempt to use a non-constant value in a constant - }; -} - -trait Foo { - fn a(x: T) { - const foo: impl Clone = x; - //~^ ERROR attempt to use a non-constant value in a constant - } -} - -impl Foo for i32 { - fn a(x: T) { - const foo: impl Clone = x; - //~^ ERROR attempt to use a non-constant value in a constant - } -} - -fn main() { } diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr deleted file mode 100644 index 4da49f4dc7..0000000000 --- a/src/test/ui/impl-trait/bindings.stderr +++ /dev/null @@ -1,44 +0,0 @@ -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:5:29 - | -LL | const foo: impl Clone = x; - | --------- ^ non-constant value - | | - | help: consider using `let` instead of `const`: `let foo` - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:11:33 - | -LL | const foo: impl Clone = x; - | --------- ^ non-constant value - | | - | help: consider using `let` instead of `const`: `let foo` - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:18:33 - | -LL | const foo: impl Clone = x; - | --------- ^ non-constant value - | | - | help: consider using `let` instead of `const`: `let foo` - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/bindings.rs:25:33 - | -LL | const foo: impl Clone = x; - | --------- ^ non-constant value - | | - | help: consider using `let` instead of `const`: `let foo` - -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bindings.rs:1:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -error: aborting due to 4 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index d3056fb885..8ec06e534d 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -1,15 +1,14 @@ // edition:2018 -#![feature(impl_trait_in_bindings)] -//~^ WARNING the feature `impl_trait_in_bindings` is incomplete - // See issue 60414 // Reduction to `impl Trait` struct Foo(T); -trait FooLike { type Output; } +trait FooLike { + type Output; +} impl FooLike for Foo { type Output = T; @@ -23,7 +22,7 @@ mod impl_trait { } /// `T::Assoc` can't be normalized any further here. - fn foo_fail() -> impl FooLike { + fn foo_fail() -> impl FooLike { //~^ ERROR: type mismatch Foo(()) } @@ -39,9 +38,9 @@ mod lifetimes { } /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. - fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ ERROR: type mismatch - //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + //~^ ERROR: type mismatch + //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope Foo(()) } } diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index ba3a2e7f8d..611543a192 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -1,45 +1,36 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bound-normalization-fail.rs:3:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` - --> $DIR/bound-normalization-fail.rs:26:32 + --> $DIR/bound-normalization-fail.rs:25:32 | -LL | fn foo_fail() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` +LL | fn foo_fail() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | = note: expected associated type `::Assoc` found type `()` help: consider constraining the associated type `::Assoc` to `()` | -LL | fn foo_fail>() -> impl FooLike { +LL | fn foo_fail>() -> impl FooLike { | ^^^^^^^^^^^^ error[E0760]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/bound-normalization-fail.rs:42:41 + --> $DIR/bound-normalization-fail.rs:41:41 | -LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` - --> $DIR/bound-normalization-fail.rs:42:41 + --> $DIR/bound-normalization-fail.rs:41:41 | -LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | = note: expected associated type `>::Assoc` found type `()` help: consider constraining the associated type `>::Assoc` to `()` | -LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { +LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { | ^^^^^^^^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0271, E0760. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/impl-trait/bound-normalization-pass.default.stderr b/src/test/ui/impl-trait/bound-normalization-pass.default.stderr deleted file mode 100644 index ef3cb74011..0000000000 --- a/src/test/ui/impl-trait/bound-normalization-pass.default.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bound-normalization-pass.rs:8:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/impl-trait/bound-normalization-pass.rs b/src/test/ui/impl-trait/bound-normalization-pass.rs index 6a01753b4c..4218bc5206 100644 --- a/src/test/ui/impl-trait/bound-normalization-pass.rs +++ b/src/test/ui/impl-trait/bound-normalization-pass.rs @@ -5,8 +5,6 @@ //-^ To make this the regression test for #75962. #![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] -//~^ WARNING the feature `impl_trait_in_bindings` is incomplete // See issue 60414 @@ -14,7 +12,9 @@ struct Foo(T); -trait FooLike { type Output; } +trait FooLike { + type Output; +} impl FooLike for Foo { type Output = T; @@ -28,7 +28,7 @@ mod impl_trait { } /// `T::Assoc` should be normalized to `()` here. - fn foo_pass>() -> impl FooLike { + fn foo_pass>() -> impl FooLike { Foo(()) } } @@ -45,40 +45,20 @@ mod lifetimes { /// Like above. /// /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here - fn foo2_pass<'a, T: Trait<'a, Assoc=()> + 'a>( - ) -> impl FooLike>::Assoc> + 'a { + fn foo2_pass<'a, T: Trait<'a, Assoc = ()> + 'a>() + -> impl FooLike>::Assoc> + 'a { Foo(()) } /// Normalization to type containing bound region. /// /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here - fn foo2_pass2<'a, T: Trait<'a, Assoc=&'a ()> + 'a>( - ) -> impl FooLike>::Assoc> + 'a { + fn foo2_pass2<'a, T: Trait<'a, Assoc = &'a ()> + 'a>() + -> impl FooLike>::Assoc> + 'a { Foo(&()) } } -// Reduction using `impl Trait` in bindings - -mod impl_trait_in_bindings { - struct Foo; - - trait FooLike { type Output; } - - impl FooLike for Foo { - type Output = u32; - } - - trait Trait { - type Assoc; - } - - fn foo>() { - let _: impl FooLike = Foo; - } -} - // The same applied to `type Foo = impl Bar`s mod opaque_types { diff --git a/src/test/ui/impl-trait/bound-normalization-pass.sa.stderr b/src/test/ui/impl-trait/bound-normalization-pass.sa.stderr deleted file mode 100644 index ef3cb74011..0000000000 --- a/src/test/ui/impl-trait/bound-normalization-pass.sa.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bound-normalization-pass.rs:8:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs deleted file mode 100644 index fd8fe5f48d..0000000000 --- a/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs +++ /dev/null @@ -1,8 +0,0 @@ -// check-pass - -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete - -const _: impl Fn() = ||(); - -fn main() {} diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr deleted file mode 100644 index 715671c8ad..0000000000 --- a/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/impl-trait-in-bindings-issue-73003.rs:3:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings.rs b/src/test/ui/impl-trait/impl-trait-in-bindings.rs deleted file mode 100644 index c7fae45d5c..0000000000 --- a/src/test/ui/impl-trait/impl-trait-in-bindings.rs +++ /dev/null @@ -1,49 +0,0 @@ -// run-pass - -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete - -use std::fmt::Debug; - -const FOO: impl Debug + Clone + PartialEq = 42; - -static BAR: impl Debug + Clone + PartialEq = 42; - -fn a(x: T) { - let y: impl Clone = x; - let _ = y.clone(); -} - -fn b(x: T) { - let f = move || { - let y: impl Clone = x; - let _ = y.clone(); - }; - f(); -} - -trait Foo { - fn a(x: T) { - let y: impl Clone = x; - let _ = y.clone(); - } -} - -impl Foo for i32 { - fn a(x: T) { - let y: impl Clone = x; - let _ = y.clone(); - } -} - -fn main() { - let foo: impl Debug + Clone + PartialEq = 42; - - assert_eq!(FOO.clone(), 42); - assert_eq!(BAR.clone(), 42); - assert_eq!(foo.clone(), 42); - - a(42); - b(42); - i32::a(42); -} diff --git a/src/test/ui/impl-trait/impl-trait-in-bindings.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings.stderr deleted file mode 100644 index bf739d4722..0000000000 --- a/src/test/ui/impl-trait/impl-trait-in-bindings.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/impl-trait-in-bindings.rs:3:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: 1 warning emitted - diff --git a/src/test/ui/impl-trait/issue-57200.rs b/src/test/ui/impl-trait/issue-57200.rs deleted file mode 100644 index e0c71d1ac9..0000000000 --- a/src/test/ui/impl-trait/issue-57200.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Regression test for #57200 -// FIXME: The error is temporary hack, we'll revisit here at some point. - -#![feature(impl_trait_in_bindings)] -#![allow(incomplete_features)] - -fn bug<'a, 'b, T>() -where - 'a: 'b, -{ - let f: impl Fn(&'a T) -> &'b T = |x| x; - //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported -} - -fn main() {} diff --git a/src/test/ui/impl-trait/issue-57200.stderr b/src/test/ui/impl-trait/issue-57200.stderr deleted file mode 100644 index b44f332d58..0000000000 --- a/src/test/ui/impl-trait/issue-57200.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: lifetimes in impl Trait types in bindings are not currently supported - --> $DIR/issue-57200.rs:11:12 - | -LL | let f: impl Fn(&'a T) -> &'b T = |x| x; - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/impl-trait/issue-57201.rs b/src/test/ui/impl-trait/issue-57201.rs deleted file mode 100644 index c1a98d8897..0000000000 --- a/src/test/ui/impl-trait/issue-57201.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Regression test for #57201 -// FIXME: The error is temporary hack, we'll revisit here at some point. - -#![feature(impl_trait_in_bindings)] -#![allow(incomplete_features)] - -fn bug<'a, 'b, T>() -where - 'a: 'b, -{ - let f: &impl Fn(&'a T) -> &'b T = &|x| x; - //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported -} - -fn main() {} diff --git a/src/test/ui/impl-trait/issue-57201.stderr b/src/test/ui/impl-trait/issue-57201.stderr deleted file mode 100644 index 462b17bf45..0000000000 --- a/src/test/ui/impl-trait/issue-57201.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: lifetimes in impl Trait types in bindings are not currently supported - --> $DIR/issue-57201.rs:11:13 - | -LL | let f: &impl Fn(&'a T) -> &'b T = &|x| x; - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/impl-trait/issue-60473.rs b/src/test/ui/impl-trait/issue-60473.rs deleted file mode 100644 index 2ef86f03d3..0000000000 --- a/src/test/ui/impl-trait/issue-60473.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Regression test for #60473 - -#![feature(impl_trait_in_bindings)] -#![allow(incomplete_features)] - -struct A<'a>(&'a ()); - -trait Trait {} - -impl Trait for () {} - -fn main() { - let x: impl Trait = (); - //~^ ERROR: missing lifetime specifier -} diff --git a/src/test/ui/impl-trait/issue-60473.stderr b/src/test/ui/impl-trait/issue-60473.stderr deleted file mode 100644 index 367b5db5d2..0000000000 --- a/src/test/ui/impl-trait/issue-60473.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0106]: missing lifetime specifier - --> $DIR/issue-60473.rs:13:23 - | -LL | let x: impl Trait = (); - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | fn main<'a>() { -LL | let x: impl Trait> = (); - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/impl-trait/issue-67166.rs b/src/test/ui/impl-trait/issue-67166.rs deleted file mode 100644 index efa67558bd..0000000000 --- a/src/test/ui/impl-trait/issue-67166.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Regression test for #67166 - -#![feature(impl_trait_in_bindings)] -#![allow(incomplete_features)] - -pub fn run() { - let _foo: Box = Box::new(()); - //~^ ERROR: missing lifetime specifier -} - -fn main() {} diff --git a/src/test/ui/impl-trait/issue-67166.stderr b/src/test/ui/impl-trait/issue-67166.stderr deleted file mode 100644 index 14c78684e3..0000000000 --- a/src/test/ui/impl-trait/issue-67166.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0106]: missing lifetime specifier - --> $DIR/issue-67166.rs:7:31 - | -LL | let _foo: Box = Box::new(()); - | ^^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | pub fn run<'a>() { -LL | let _foo: Box = Box::new(()); - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/impl-trait/issue-69840.rs b/src/test/ui/impl-trait/issue-69840.rs deleted file mode 100644 index b270f88b68..0000000000 --- a/src/test/ui/impl-trait/issue-69840.rs +++ /dev/null @@ -1,16 +0,0 @@ -// check-pass - -#![feature(impl_trait_in_bindings)] -#![allow(incomplete_features)] - -struct A<'a>(&'a ()); - -trait Trait {} - -impl Trait for () {} - -pub fn foo<'a>() { - let _x: impl Trait> = (); -} - -fn main() {} diff --git a/src/test/ui/impl-trait/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs new file mode 100644 index 0000000000..23a3748c12 --- /dev/null +++ b/src/test/ui/impl-trait/issue-86465.rs @@ -0,0 +1,10 @@ +#![feature(min_type_alias_impl_trait)] + +type X<'a, 'b> = impl std::fmt::Debug; + +fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) { + //~^ ERROR concrete type differs from previous defining opaque type use + (a, a) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr new file mode 100644 index 0000000000..595b16aa68 --- /dev/null +++ b/src/test/ui/impl-trait/issue-86465.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/issue-86465.rs:5:1 + | +LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&'a u32`, got `&'b u32` + | +note: previous use here + --> $DIR/issue-86465.rs:5:1 + | +LL | fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/issues/issue-54600.rs b/src/test/ui/impl-trait/issues/issue-54600.rs new file mode 100644 index 0000000000..7a64799302 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-54600.rs @@ -0,0 +1,7 @@ +use std::fmt::Debug; + +fn main() { + let x: Option = Some(44_u32); + //~^ `impl Trait` not allowed outside of function and method return types + println!("{:?}", x); +} diff --git a/src/test/ui/impl-trait/issues/issue-54600.stderr b/src/test/ui/impl-trait/issues/issue-54600.stderr new file mode 100644 index 0000000000..4d0c32c6bb --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-54600.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-54600.rs:4:19 + | +LL | let x: Option = Some(44_u32); + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-54840.rs b/src/test/ui/impl-trait/issues/issue-54840.rs new file mode 100644 index 0000000000..030d5715d5 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-54840.rs @@ -0,0 +1,7 @@ +use std::ops::Add; + +fn main() { + let i: i32 = 0; + let j: &impl Add = &i; + //~^ `impl Trait` not allowed outside of function and method return types +} diff --git a/src/test/ui/impl-trait/issues/issue-54840.stderr b/src/test/ui/impl-trait/issues/issue-54840.stderr new file mode 100644 index 0000000000..b8046b7482 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-54840.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-54840.rs:5:13 + | +LL | let j: &impl Add = &i; + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-58504.rs b/src/test/ui/impl-trait/issues/issue-58504.rs new file mode 100644 index 0000000000..aac33b3b3e --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-58504.rs @@ -0,0 +1,12 @@ +#![feature(generators, generator_trait, never_type)] + +use std::ops::Generator; + +fn mk_gen() -> impl Generator { + || { loop { yield; } } +} + +fn main() { + let gens: [impl Generator;2] = [ mk_gen(), mk_gen() ]; + //~^ `impl Trait` not allowed outside of function and method return types +} diff --git a/src/test/ui/impl-trait/issues/issue-58504.stderr b/src/test/ui/impl-trait/issues/issue-58504.stderr new file mode 100644 index 0000000000..ff1010f066 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-58504.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-58504.rs:10:16 + | +LL | let gens: [impl Generator;2] = [ mk_gen(), mk_gen() ]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-58956.rs b/src/test/ui/impl-trait/issues/issue-58956.rs new file mode 100644 index 0000000000..5fe18b6e9b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-58956.rs @@ -0,0 +1,14 @@ +trait Lam {} + +pub struct B; +impl Lam for B {} +pub struct Wrap(T); + +const _A: impl Lam = { + //~^ `impl Trait` not allowed outside of function and method return types + let x: Wrap = Wrap(B); + //~^ `impl Trait` not allowed outside of function and method return types + x.0 +}; + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-58956.stderr b/src/test/ui/impl-trait/issues/issue-58956.stderr new file mode 100644 index 0000000000..00ebf170ab --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-58956.stderr @@ -0,0 +1,15 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-58956.rs:7:11 + | +LL | const _A: impl Lam = { + | ^^^^^^^^ + +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-58956.rs:9:17 + | +LL | let x: Wrap = Wrap(B); + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr index 8e42b9d46d..1f4e3f78af 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:11:12 + --> $DIR/issue-70877.rs:10:12 | LL | type FooRet = impl std::fmt::Debug; | -------------------- the found opaque type diff --git a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr index 8e42b9d46d..1f4e3f78af 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `::Item == Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option + 'static)>` - --> $DIR/issue-70877.rs:11:12 + --> $DIR/issue-70877.rs:10:12 | LL | type FooRet = impl std::fmt::Debug; | -------------------- the found opaque type diff --git a/src/test/ui/impl-trait/issues/issue-70877.rs b/src/test/ui/impl-trait/issues/issue-70877.rs index 7ca0f90e2d..29aa705ef9 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.rs +++ b/src/test/ui/impl-trait/issues/issue-70877.rs @@ -1,7 +1,6 @@ // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] -#![feature(impl_trait_in_bindings)] #![allow(incomplete_features)] type FooArg<'a> = &'a dyn ToString; diff --git a/src/test/ui/impl-trait/issues/issue-70971.rs b/src/test/ui/impl-trait/issues/issue-70971.rs new file mode 100644 index 0000000000..d4dc2fd877 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-70971.rs @@ -0,0 +1,4 @@ +fn main() { + let x : (impl Copy,) = (true,); + //~^ `impl Trait` not allowed outside of function and method return types +} diff --git a/src/test/ui/impl-trait/issues/issue-70971.stderr b/src/test/ui/impl-trait/issues/issue-70971.stderr new file mode 100644 index 0000000000..31993da3e3 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-70971.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-70971.rs:2:14 + | +LL | let x : (impl Copy,) = (true,); + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-78721.rs b/src/test/ui/impl-trait/issues/issue-78721.rs deleted file mode 100644 index f7dbef9e3f..0000000000 --- a/src/test/ui/impl-trait/issues/issue-78721.rs +++ /dev/null @@ -1,15 +0,0 @@ -// edition:2018 - -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete - -struct Bug { - V1: [(); { - let f: impl core::future::Future = async { 1 }; - //~^ ERROR `async` blocks are not allowed in constants - //~| ERROR destructors cannot be evaluated at compile-time - 1 - }], -} - -fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-78721.stderr b/src/test/ui/impl-trait/issues/issue-78721.stderr deleted file mode 100644 index d5712dd920..0000000000 --- a/src/test/ui/impl-trait/issues/issue-78721.stderr +++ /dev/null @@ -1,31 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-78721.rs:3:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -error[E0658]: `async` blocks are not allowed in constants - --> $DIR/issue-78721.rs:8:57 - | -LL | let f: impl core::future::Future = async { 1 }; - | ^^^^^^^^^^^ - | - = note: see issue #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 - --> $DIR/issue-78721.rs:8:13 - | -LL | let f: impl core::future::Future = async { 1 }; - | ^ constants cannot evaluate destructors -... -LL | }], - | - value is dropped here - -error: aborting due to 2 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0493, E0658. -For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/impl-trait/issues/issue-78722.full_tait.stderr b/src/test/ui/impl-trait/issues/issue-78722.full_tait.stderr index 7a4be1d5f6..728644f757 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.full_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.full_tait.stderr @@ -7,33 +7,26 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-78722.rs:7:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - -error[E0658]: `async` blocks are not allowed in constants - --> $DIR/issue-78722.rs:17:20 +error[E0308]: mismatched types + --> $DIR/issue-78722.rs:15:20 | +LL | type F = impl core::future::Future; + | -------------------------------------- the expected opaque type +... LL | let f: F = async { 1 }; - | ^^^^^^^^^^^ + | - ^^^^^^^^^^^ expected opaque type, found a different opaque type + | | + | expected due to this + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL | - = note: see issue #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 - --> $DIR/issue-78722.rs:17:13 +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type | -LL | let f: F = async { 1 }; - | ^ constants cannot evaluate destructors -... -LL | }], - | - value is dropped here + = note: expected opaque type `impl Future` (opaque type at <$DIR/issue-78722.rs:8:10>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + = note: distinct uses of `impl Trait` result in different opaque types -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted -Some errors have detailed explanations: E0493, E0658. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/issues/issue-78722.min_tait.stderr b/src/test/ui/impl-trait/issues/issue-78722.min_tait.stderr index 131033063d..221b23ae3d 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.min_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.min_tait.stderr @@ -1,31 +1,23 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-78722.rs:7:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -error[E0658]: `async` blocks are not allowed in constants - --> $DIR/issue-78722.rs:17:20 +error[E0308]: mismatched types + --> $DIR/issue-78722.rs:15:20 | +LL | type F = impl core::future::Future; + | -------------------------------------- the expected opaque type +... LL | let f: F = async { 1 }; - | ^^^^^^^^^^^ + | - ^^^^^^^^^^^ expected opaque type, found a different opaque type + | | + | expected due to this + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL | - = note: see issue #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 - --> $DIR/issue-78722.rs:17:13 +LL | pub const fn from_generator(gen: T) -> impl Future + | ------------------------------- the found opaque type | -LL | let f: F = async { 1 }; - | ^ constants cannot evaluate destructors -... -LL | }], - | - value is dropped here + = note: expected opaque type `impl Future` (opaque type at <$DIR/issue-78722.rs:8:10>) + found opaque type `impl Future` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>) + = note: distinct uses of `impl Trait` result in different opaque types -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error -Some errors have detailed explanations: E0493, E0658. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs index 0999ec63e0..480b55eed2 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.rs +++ b/src/test/ui/impl-trait/issues/issue-78722.rs @@ -4,8 +4,6 @@ #![feature(min_type_alias_impl_trait)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete type F = impl core::future::Future; @@ -15,8 +13,7 @@ struct Bug { async {} } let f: F = async { 1 }; - //~^ ERROR `async` blocks are not allowed in constants - //~| ERROR destructors cannot be evaluated at compile-time + //~^ ERROR mismatched types [E0308] 1 }], } diff --git a/src/test/ui/impl-trait/issues/issue-79099.rs b/src/test/ui/impl-trait/issues/issue-79099.rs new file mode 100644 index 0000000000..f72533d42e --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-79099.rs @@ -0,0 +1,10 @@ +struct Bug { + V1: [(); { + let f: impl core::future::Future = async { 1 }; + //~^ `impl Trait` not allowed outside of function and method return types + //~| expected identifier + 1 + }], +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-79099.stderr b/src/test/ui/impl-trait/issues/issue-79099.stderr new file mode 100644 index 0000000000..121536d3f6 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-79099.stderr @@ -0,0 +1,20 @@ +error: expected identifier, found `1` + --> $DIR/issue-79099.rs:3:65 + | +LL | let f: impl core::future::Future = async { 1 }; + | ----- ^ expected identifier + | | + | `async` blocks are only allowed in Rust 2018 or later + | + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-79099.rs:3:16 + | +LL | let f: impl core::future::Future = async { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs index d9d2e3929b..773cd0b81c 100644 --- a/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs +++ b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs @@ -1,8 +1,8 @@ struct Foo(T); -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types type Result = std::result::Result; -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // should not cause ICE fn x() -> Foo { diff --git a/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr index eef6844adf..d44dcf1f7f 100644 --- a/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr +++ b/src/test/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr @@ -1,10 +1,10 @@ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16 | LL | struct Foo(T); | ^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20 | LL | type Result = std::result::Result; diff --git a/src/test/ui/impl-trait/issues/issue-84919.rs b/src/test/ui/impl-trait/issues/issue-84919.rs new file mode 100644 index 0000000000..479bad97cd --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-84919.rs @@ -0,0 +1,9 @@ +trait Trait {} +impl Trait for () {} + +fn foo<'a: 'a>() { + let _x: impl Trait = (); + //~^ `impl Trait` not allowed outside of function and method return types +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-84919.stderr b/src/test/ui/impl-trait/issues/issue-84919.stderr new file mode 100644 index 0000000000..bb1bcfefe6 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-84919.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-84919.rs:5:13 + | +LL | let _x: impl Trait = (); + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-86201.rs b/src/test/ui/impl-trait/issues/issue-86201.rs new file mode 100644 index 0000000000..8dc76f4f75 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86201.rs @@ -0,0 +1,13 @@ +#![feature(unboxed_closures)] +#![feature(min_type_alias_impl_trait)] + +type FunType = impl Fn<()>; +//~^ could not find defining uses +static STATIC_FN: FunType = some_fn; +//~^ mismatched types + +fn some_fn() {} + +fn main() { + let _: >::Output = STATIC_FN(); +} diff --git a/src/test/ui/impl-trait/issues/issue-86201.stderr b/src/test/ui/impl-trait/issues/issue-86201.stderr new file mode 100644 index 0000000000..b1460096de --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86201.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-86201.rs:6:29 + | +LL | type FunType = impl Fn<()>; + | ----------- the expected opaque type +LL | +LL | static STATIC_FN: FunType = some_fn; + | ^^^^^^^ expected opaque type, found fn item + | + = note: expected opaque type `impl Fn<()>` + found fn item `fn() {some_fn}` + +error: could not find defining uses + --> $DIR/issue-86201.rs:4:16 + | +LL | type FunType = impl Fn<()>; + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/issues/issue-86642.rs b/src/test/ui/impl-trait/issues/issue-86642.rs new file mode 100644 index 0000000000..8953ff8158 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86642.rs @@ -0,0 +1,8 @@ +static x: impl Fn(&str) -> Result<&str, ()> = move |source| { + //~^ `impl Trait` not allowed outside of function and method return types + let res = (move |source| Ok(source))(source); + let res = res.or((move |source| Ok(source))(source)); + res +}; + +fn main() {} diff --git a/src/test/ui/impl-trait/issues/issue-86642.stderr b/src/test/ui/impl-trait/issues/issue-86642.stderr new file mode 100644 index 0000000000..2fc0a6fe1f --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-86642.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-86642.rs:1:11 + | +LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/issue-87295.rs b/src/test/ui/impl-trait/issues/issue-87295.rs new file mode 100644 index 0000000000..2f2bfe147b --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-87295.rs @@ -0,0 +1,18 @@ +trait Trait { + type Output; +} +impl Trait for () { + type Output = i32; +} + +struct Struct(F); +impl Struct { + pub fn new(_: F) -> Self { + todo!() + } +} + +fn main() { + let _do_not_waste: Struct> = Struct::new(()); + //~^ `impl Trait` not allowed outside of function and method return types +} diff --git a/src/test/ui/impl-trait/issues/issue-87295.stderr b/src/test/ui/impl-trait/issues/issue-87295.stderr new file mode 100644 index 0000000000..f5c7603ce4 --- /dev/null +++ b/src/test/ui/impl-trait/issues/issue-87295.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/issue-87295.rs:16:31 + | +LL | let _do_not_waste: Struct> = Struct::new(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr index 8f05ab3c49..6800b37b5b 100644 --- a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr +++ b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr @@ -6,3 +6,4 @@ LL | foo::('a'); error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr index c980e9463e..db66d46109 100644 --- a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr +++ b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr @@ -8,3 +8,4 @@ LL | evt.handle_event::(|_evt| { error: aborting due to previous error +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 4372de2450..e9d6208773 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -9,7 +9,7 @@ LL | fn elided(x: &i32) -> impl Copy { x } help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound | LL | fn elided(x: &i32) -> impl Copy + '_ { x } - | ^^^^^^^^^^^^^^ + | ^^^^ error: lifetime may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:5:32 @@ -23,7 +23,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } - | ^^^^^^^^^^^^^^ + | ^^^^ error: lifetime may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:7:46 diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 3749c268a6..59c7e4d5f4 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr @@ -34,13 +34,13 @@ LL | fn bad(x: impl Into) -> impl Into { x } | | nested `impl Trait` here | outer `impl Trait` -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/nested_impl_trait.rs:8:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/nested_impl_trait.rs:25:42 | LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index 0f89ec2475..b9b2ce249f 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -95,7 +95,7 @@ LL | / move || { LL | | yield; LL | | x; LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 {()}]` + | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:67:35 @@ -117,7 +117,7 @@ LL | | let x = generator_hold(); LL | | yield; LL | | x; LL | | } - | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]` + | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6]` error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:86:26 diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index 65178cc9d2..6c5264671a 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -9,7 +9,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator { help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: lifetime may not live long enough --> $DIR/static-return-lifetime-infered.rs:9:37 @@ -23,7 +23,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index c3e21c81f0..4605e76ac9 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -13,61 +13,61 @@ fn in_adt_in_parameters(_: Vec) { panic!() } // Disallowed fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types //~^^ ERROR nested `impl Trait` is not allowed // Disallowed fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types //~| ERROR nested `impl Trait` is not allowed // Disallowed fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_Fn_parameter_in_generics (_: F) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Allowed @@ -80,22 +80,22 @@ fn in_impl_Trait_in_return() -> impl IntoIterator { // Disallowed struct InBraceStructField { x: impl Debug } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed struct InAdtInBraceStructField { x: Vec } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed struct InTupleStructField(impl Debug); -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed enum InEnum { InBraceVariant { x: impl Debug }, - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types InTupleVariant(impl Debug), - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Allowed @@ -106,7 +106,7 @@ trait InTraitDefnParameters { // Disallowed trait InTraitDefnReturn { fn in_return() -> impl Debug; - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Allowed and disallowed in trait impls @@ -123,7 +123,7 @@ impl DummyTrait for () { // Allowed fn in_trait_impl_return() -> impl Debug { () } - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Allowed @@ -136,10 +136,10 @@ impl DummyType { // Disallowed extern "C" { fn in_foreign_parameters(_: impl Debug); - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types fn in_foreign_return() -> impl Debug; - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Allowed @@ -155,96 +155,96 @@ type InTypeAlias = impl Debug; //~^ ERROR `impl Trait` in type aliases is unstable type InReturnInTypeAlias = fn() -> impl Debug; -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types //~| ERROR `impl Trait` in type aliases is unstable // Disallowed in impl headers impl PartialEq for () { - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Disallowed in impl headers impl PartialEq<()> for impl Debug { - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Disallowed in inherent impls impl impl Debug { - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Disallowed in inherent impls struct InInherentImplAdt { t: T } impl InInherentImplAdt { - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } // Disallowed in where clauses fn in_fn_where_clause() where impl Debug: Debug -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types { } // Disallowed in where clauses fn in_adt_in_fn_where_clause() where Vec: Debug -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types { } // Disallowed fn in_trait_parameter_in_fn_where_clause() where T: PartialEq -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types { } // Disallowed fn in_Fn_parameter_in_fn_where_clause() where T: Fn(impl Debug) -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types { } // Disallowed fn in_Fn_return_in_fn_where_clause() where T: Fn() -> impl Debug -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types { } // Disallowed struct InStructGenericParamDefault(T); -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed enum InEnumGenericParamDefault { Variant(T) } -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed trait InTraitGenericParamDefault {} -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed type InTypeAliasGenericParamDefault = T; -//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types +//~^ ERROR `impl Trait` not allowed outside of function and method return types // Disallowed impl T {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` not allowed outside of function and inherent method return types +//~| ERROR `impl Trait` not allowed outside of function and method return types // Disallowed fn in_method_generic_param_default(_: T) {} //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| WARNING this was previously accepted by the compiler but is being phased out -//~| ERROR `impl Trait` not allowed outside of function and inherent method return types +//~| ERROR `impl Trait` not allowed outside of function and method return types fn main() { let _in_local_variable: impl Fn() = || {}; - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types let _in_return_in_local_variable = || -> impl Fn() { || {} }; - //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types + //~^ ERROR `impl Trait` not allowed outside of function and method return types } diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 09ec4d5b20..93a3de61cc 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -43,249 +43,247 @@ LL | type InReturnInTypeAlias = fn() -> impl Debug; = note: see issue #63063 for more information = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:15:40 | LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:19:42 | LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:23:38 | LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:27:40 | LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:31:49 | LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:35:51 | LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:39:55 | LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:43:57 | LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:47:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:52:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:56:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:61:59 | LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:65:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:69:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:82:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:86:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:90:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:95:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:97:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:108:23 | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:125:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:138:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:141:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:157:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:162:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:167:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:172:6 | LL | impl impl Debug { | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:178:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:184:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:191:15 | LL | where Vec: Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:198:24 | LL | where T: PartialEq | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:205:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:212:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:218:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:222:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:226:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:230:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:234:11 | LL | impl T {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:240:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:246:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ - | - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/where-allowed.rs:248:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs deleted file mode 100644 index 7beb2db396..0000000000 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs +++ /dev/null @@ -1,17 +0,0 @@ -// edition:2018 -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete - -use std::io::Error; - -fn make_unit() -> Result<(), Error> { - Ok(()) -} - -fn main() { - let fut = async { - make_unit()?; - - Ok(()) //~ ERROR type annotations needed - }; -} diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr deleted file mode 100644 index 8e632fbc1d..0000000000 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr +++ /dev/null @@ -1,21 +0,0 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:2:12 - | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -error[E0282]: type annotations needed for `impl Future` - --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:15:9 - | -LL | let fut = async { - | --- consider giving `fut` the explicit type `impl Future`, where the type parameter `E` is specified -... -LL | Ok(()) - | ^^ cannot infer type for type parameter `E` declared on the enum `Result` - -error: aborting due to previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/inference-variable-behind-raw-pointer.rs b/src/test/ui/inference/inference-variable-behind-raw-pointer.rs index 1d508e8e82..6662e46b1c 100644 --- a/src/test/ui/inference/inference-variable-behind-raw-pointer.rs +++ b/src/test/ui/inference/inference-variable-behind-raw-pointer.rs @@ -7,5 +7,5 @@ fn main() { let _ = &data as *const *const (); if data.is_null() {} //~^ WARNING type annotations needed - //~| WARNING this was previously accepted by the compiler but is being phased out + //~| WARNING this is accepted in the current edition } 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 12848982b8..c38f57912a 100644 --- a/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr +++ b/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr @@ -5,7 +5,7 @@ LL | if data.is_null() {} | ^^^^^^^ | = note: `#[warn(tyvar_behind_raw_pointer)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 warning: 1 warning emitted diff --git a/src/test/ui/inference/issue-70703.rs b/src/test/ui/inference/issue-70703.rs new file mode 100644 index 0000000000..d90498e96e --- /dev/null +++ b/src/test/ui/inference/issue-70703.rs @@ -0,0 +1,26 @@ +// check-pass + +trait Factory { + type Product; +} + +impl Factory for () { + type Product = (); +} + +trait ProductConsumer

{ + fn consume(self, product: P); +} + +impl

ProductConsumer

for () { + fn consume(self, _: P) {} +} + +fn make_product_consumer(_: F) -> impl ProductConsumer { + () +} + +fn main() { + let consumer = make_product_consumer(()); + consumer.consume(()); +} diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs new file mode 100644 index 0000000000..a205a8730a --- /dev/null +++ b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs @@ -0,0 +1,11 @@ +#![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)) +//~^ ERROR evaluation of constant value failed +}; + +pub fn main() { +} diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr new file mode 100644 index 0000000000..ff78c25273 --- /dev/null +++ b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/intrinsic-raw_eq-const-padding.rs:6:5 + | +LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading 4 bytes of memory starting at alloc3, but 1 byte is uninitialized starting at alloc3+0x1, and this operation requires initialized memory + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs b/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs new file mode 100644 index 0000000000..8ea9546730 --- /dev/null +++ b/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(core_intrinsics)] +#![feature(const_intrinsic_raw_eq)] +#![deny(const_err)] + +pub fn main() { + use std::intrinsics::raw_eq; + + const RAW_EQ_I32_TRUE: bool = unsafe { raw_eq(&42_i32, &42) }; + assert!(RAW_EQ_I32_TRUE); + + const RAW_EQ_I32_FALSE: bool = unsafe { raw_eq(&4_i32, &2) }; + assert!(!RAW_EQ_I32_FALSE); + + const RAW_EQ_CHAR_TRUE: bool = unsafe { raw_eq(&'a', &'a') }; + assert!(RAW_EQ_CHAR_TRUE); + + const RAW_EQ_CHAR_FALSE: bool = unsafe { raw_eq(&'a', &'A') }; + assert!(!RAW_EQ_CHAR_FALSE); + + const RAW_EQ_ARRAY_TRUE: bool = unsafe { raw_eq(&[13_u8, 42], &[13, 42]) }; + assert!(RAW_EQ_ARRAY_TRUE); + + const RAW_EQ_ARRAY_FALSE: bool = unsafe { raw_eq(&[13_u8, 42], &[42, 13]) }; + assert!(!RAW_EQ_ARRAY_FALSE); +} diff --git a/src/test/ui/non-integer-atomic.rs b/src/test/ui/intrinsics/non-integer-atomic.rs similarity index 100% rename from src/test/ui/non-integer-atomic.rs rename to src/test/ui/intrinsics/non-integer-atomic.rs diff --git a/src/test/ui/non-integer-atomic.stderr b/src/test/ui/intrinsics/non-integer-atomic.stderr similarity index 100% rename from src/test/ui/non-integer-atomic.stderr rename to src/test/ui/intrinsics/non-integer-atomic.stderr diff --git a/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs b/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs new file mode 100644 index 0000000000..7bbf47a383 --- /dev/null +++ b/src/test/ui/invalid-compile-flags/codegen-option-without-group.rs @@ -0,0 +1 @@ +// compile-flags: --llvm-args diff --git a/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr b/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr new file mode 100644 index 0000000000..c5a0c29cad --- /dev/null +++ b/src/test/ui/invalid-compile-flags/codegen-option-without-group.stderr @@ -0,0 +1,2 @@ +error: Unrecognized option: 'llvm-args'. Did you mean `-C llvm-args`? + diff --git a/src/test/ui/invalid-compile-flags/debug-option-without-group.rs b/src/test/ui/invalid-compile-flags/debug-option-without-group.rs new file mode 100644 index 0000000000..86e40c1785 --- /dev/null +++ b/src/test/ui/invalid-compile-flags/debug-option-without-group.rs @@ -0,0 +1 @@ +// compile-flags: --unpretty=hir diff --git a/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr b/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr new file mode 100644 index 0000000000..0e57e31ad3 --- /dev/null +++ b/src/test/ui/invalid-compile-flags/debug-option-without-group.stderr @@ -0,0 +1,2 @@ +error: Unrecognized option: 'unpretty'. Did you mean `-Z unpretty`? + diff --git a/src/test/ui/issues/issue-10412.stderr b/src/test/ui/issues/issue-10412.stderr index 2a6e241459..9d181eab7f 100644 --- a/src/test/ui/issues/issue-10412.stderr +++ b/src/test/ui/issues/issue-10412.stderr @@ -45,6 +45,8 @@ error[E0726]: implicit elided lifetime not allowed here | LL | impl<'self> Serializable for &'self str { | ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>` + | + = note: assuming a `'static` lifetime... error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/issue-10412.rs:6:13 diff --git a/src/test/ui/issues/issue-12997-2.stderr b/src/test/ui/issues/issue-12997-2.stderr index 695d657cb5..3b89e8bc45 100644 --- a/src/test/ui/issues/issue-12997-2.stderr +++ b/src/test/ui/issues/issue-12997-2.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-12997-2.rs:8:1 | +LL | #[bench] + | -------- in this procedural macro expansion LL | fn bar(x: isize) { } | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&mut Bencher` | diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr index 69817f10c9..ee1464fd84 100644 --- a/src/test/ui/issues/issue-17651.stderr +++ b/src/test/ui/issues/issue-17651.stderr @@ -5,7 +5,11 @@ LL | (|| Box::new(*(&[0][..])))(); | ^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[{integer}]` - = note: required by `Box::::new` +note: required by `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + | +LL | pub fn new(x: T) -> Self { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time --> $DIR/issue-17651.rs:5:9 diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/issues/issue-18294.rs index 1c2229fb9e..77355f0d7c 100644 --- a/src/test/ui/issues/issue-18294.rs +++ b/src/test/ui/issues/issue-18294.rs @@ -1,5 +1,5 @@ fn main() { const X: u32 = 1; - const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable + const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers println!("{}", Y); } diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr index 52df558bfc..432e9a6518 100644 --- a/src/test/ui/issues/issue-18294.stderr +++ b/src/test/ui/issues/issue-18294.stderr @@ -1,12 +1,11 @@ -error[E0658]: casting pointers to integers in constants is unstable +error: pointers cannot be cast to integers during const eval. --> $DIR/issue-18294.rs:3:31 | LL | const Y: usize = unsafe { &X as *const u32 as usize }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr index 22c3470b61..0e942e80e2 100644 --- a/src/test/ui/issues/issue-18611.stderr +++ b/src/test/ui/issues/issue-18611.stderr @@ -1,10 +1,11 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied - --> $DIR/issue-18611.rs:1:1 + --> $DIR/issue-18611.rs:1:18 | -LL | / fn add_state(op: ::State) { -LL | | -LL | | } - | |_^ the trait `HasState` is not implemented for `isize` +LL | fn add_state(op: ::State) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` +... +LL | trait HasState { + | -------------- required by this bound in `HasState` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr index 86b530e85a..2a5416ce85 100644 --- a/src/test/ui/issues/issue-18959.stderr +++ b/src/test/ui/issues/issue-18959.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-18959.rs:11:11 + --> $DIR/issue-18959.rs:11:12 | LL | fn foo(b: &dyn Bar) { - | ^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` cannot be made into an object | = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit diff --git a/src/test/ui/issues/issue-19380.stderr b/src/test/ui/issues/issue-19380.stderr index c3a5d3dfee..4400b6179c 100644 --- a/src/test/ui/issues/issue-19380.stderr +++ b/src/test/ui/issues/issue-19380.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Qiz` cannot be made into an object - --> $DIR/issue-19380.rs:11:9 + --> $DIR/issue-19380.rs:11:29 | LL | foos: &'static [&'static (dyn Qiz + 'static)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object + | ^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-19380.rs:2:6 diff --git a/src/test/ui/issues/issue-20427.rs b/src/test/ui/issues/issue-20427.rs index 41922c6229..cfd8b2191a 100644 --- a/src/test/ui/issues/issue-20427.rs +++ b/src/test/ui/issues/issue-20427.rs @@ -7,7 +7,6 @@ #![allow(deprecated, deprecated_in_future)] // aux-build:i8.rs -// ignore-pretty issue #37201 extern crate i8; use std::string as i16; diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index 9940f43cc4..25a90df456 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -6,7 +6,11 @@ LL | for item in *things { *item = 0 } | = help: the trait `Sized` is not implemented for `dyn Iterator` = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20644.rs b/src/test/ui/issues/issue-20644.rs index 71c6746e0e..1b90727fbc 100644 --- a/src/test/ui/issues/issue-20644.rs +++ b/src/test/ui/issues/issue-20644.rs @@ -19,9 +19,7 @@ use std::path::Path; pub fn parse_summary(_: R, _: &Path) { let path_from_root = Path::new(""); - Path::new(&iter::repeat("../") - .take(path_from_root.components().count() - 1) - .collect::()); + Path::new(&"../".repeat(path_from_root.components().count() - 1)); } fn foo() { diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index e68482d1ca..03e3311e0f 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -1,8 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/issue-20831-debruijn.rs:28:33 + --> $DIR/issue-20831-debruijn.rs:28:8 | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 28:58... --> $DIR/issue-20831-debruijn.rs:28:58 @@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined on LL | impl<'a> Publisher<'a> for MyStruct<'a> { | ^^ note: ...so that the types are compatible - --> $DIR/issue-20831-debruijn.rs:28:33 + --> $DIR/issue-20831-debruijn.rs:28:8 | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ = note: expected `Publisher<'_>` found `Publisher<'_>` diff --git a/src/test/ui/issues/issue-21160.stderr b/src/test/ui/issues/issue-21160.stderr index 4cef23ac42..c864381e6b 100644 --- a/src/test/ui/issues/issue-21160.stderr +++ b/src/test/ui/issues/issue-21160.stderr @@ -1,6 +1,8 @@ error[E0277]: the trait bound `Bar: Hash` is not satisfied --> $DIR/issue-21160.rs:8:12 | +LL | #[derive(Hash)] + | ---- in this derive macro expansion LL | struct Foo(Bar); | ^^^ the trait `Hash` is not implemented for `Bar` | diff --git a/src/test/ui/issues/issue-21202.stderr b/src/test/ui/issues/issue-21202.stderr index 9b3b7a72e0..47f28d7c44 100644 --- a/src/test/ui/issues/issue-21202.stderr +++ b/src/test/ui/issues/issue-21202.stderr @@ -3,6 +3,11 @@ error[E0624]: associated function `foo` is private | LL | Foo::foo(&f); | ^^^ private associated function + | + ::: $DIR/auxiliary/issue-21202.rs:4:9 + | +LL | fn foo(&self) { } + | ------------- private associated function defined here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22992.rs b/src/test/ui/issues/issue-22992.rs index e2ae1f96ee..292a0ae298 100644 --- a/src/test/ui/issues/issue-22992.rs +++ b/src/test/ui/issues/issue-22992.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37201 struct X { val: i32 } impl std::ops::Deref for X { diff --git a/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs b/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs index 823be8c832..a99f260dde 100644 --- a/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs +++ b/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs @@ -1,8 +1,6 @@ // run-pass #![allow(non_upper_case_globals)] -// ignore-pretty issue #37201 - // This test is ensuring that parameters are indeed dropped after // temporaries in a fn body. diff --git a/src/test/ui/issues/issue-27401-dropflag-reinit.rs b/src/test/ui/issues/issue-27401-dropflag-reinit.rs index e137575c2f..ab54af29bd 100644 --- a/src/test/ui/issues/issue-27401-dropflag-reinit.rs +++ b/src/test/ui/issues/issue-27401-dropflag-reinit.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-pretty issue #37201 // Check that when a `let`-binding occurs in a loop, its associated // drop-flag is reinitialized (to indicate "needs-drop" at the end of diff --git a/src/test/ui/issues/issue-27895.rs b/src/test/ui/issues/issue-27895.rs deleted file mode 100644 index 0018ac1bdf..0000000000 --- a/src/test/ui/issues/issue-27895.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - let i = 5; - let index = 6; - - match i { - 0..=index => println!("winner"), - //~^ ERROR runtime values cannot be referenced in patterns - _ => println!("hello"), - } -} diff --git a/src/test/ui/issues/issue-27895.stderr b/src/test/ui/issues/issue-27895.stderr deleted file mode 100644 index 55bd938b0b..0000000000 --- a/src/test/ui/issues/issue-27895.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: runtime values cannot be referenced in patterns - --> $DIR/issue-27895.rs:6:13 - | -LL | 0..=index => println!("winner"), - | ^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr index 4c927a0cb4..70caeb0ea3 100644 --- a/src/test/ui/issues/issue-28098.stderr +++ b/src/test/ui/issues/issue-28098.stderr @@ -5,7 +5,11 @@ LL | let _ = Iterator::next(&mut ()); | ^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` - = note: required by `std::iter::Iterator::next` +note: required by `std::iter::Iterator::next` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn next(&mut self) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `bool` is not an iterator --> $DIR/issue-28098.rs:6:14 @@ -15,7 +19,11 @@ LL | for _ in false {} | = help: the trait `Iterator` is not implemented for `bool` = note: required because of the requirements on the impl of `IntoIterator` for `bool` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:9:28 @@ -24,7 +32,11 @@ LL | let _ = Iterator::next(&mut ()); | ^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` - = note: required by `std::iter::Iterator::next` +note: required by `std::iter::Iterator::next` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn next(&mut self) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:2:13 @@ -41,7 +53,11 @@ LL | let _ = Iterator::next(&mut ()); | ^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` - = note: required by `std::iter::Iterator::next` +note: required by `std::iter::Iterator::next` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn next(&mut self) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:22:28 @@ -50,7 +66,11 @@ LL | let _ = Iterator::next(&mut ()); | ^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` - = note: required by `std::iter::Iterator::next` +note: required by `std::iter::Iterator::next` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn next(&mut self) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `bool` is not an iterator --> $DIR/issue-28098.rs:25:14 @@ -60,7 +80,11 @@ LL | for _ in false {} | = help: the trait `Iterator` is not implemented for `bool` = note: required because of the requirements on the impl of `IntoIterator` for `bool` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:18:13 diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr index 94aff59635..f00d5d32bb 100644 --- a/src/test/ui/issues/issue-29147.stderr +++ b/src/test/ui/issues/issue-29147.stderr @@ -1,13 +1,15 @@ error[E0283]: type annotations needed --> $DIR/issue-29147.rs:21:13 | -LL | trait Foo { fn xxx(&self); } - | -------------- required by `Foo::xxx` -... LL | let _ = >::xxx; | ^^^^^^^^^^^^ cannot infer type for struct `S5<_>` | = note: cannot satisfy `S5<_>: Foo` +note: required by `Foo::xxx` + --> $DIR/issue-29147.rs:10:13 + | +LL | trait Foo { fn xxx(&self); } + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31109.rs b/src/test/ui/issues/issue-31109.rs deleted file mode 100644 index 37c2390581..0000000000 --- a/src/test/ui/issues/issue-31109.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - // FIXME(#31407) this error should go away, but in the meantime we test that it - // is accompanied by a somewhat useful error message. - let _: f64 = 1234567890123456789012345678901234567890e-340; - //~^ ERROR could not evaluate float literal (see issue #31407) -} diff --git a/src/test/ui/issues/issue-31109.stderr b/src/test/ui/issues/issue-31109.stderr deleted file mode 100644 index d354f61a50..0000000000 --- a/src/test/ui/issues/issue-31109.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: could not evaluate float literal (see issue #31407) - --> $DIR/issue-31109.rs:4:18 - | -LL | let _: f64 = 1234567890123456789012345678901234567890e-340; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index 2d02018819..bc7eb0688e 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -8,7 +8,11 @@ LL | Err(5)?; | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required because of the requirements on the impl of `FromResidual>` for `Result` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3290.rs b/src/test/ui/issues/issue-3290.rs index 63e1b28a60..840c7ff835 100644 --- a/src/test/ui/issues/issue-3290.rs +++ b/src/test/ui/issues/issue-3290.rs @@ -1,5 +1,6 @@ // run-pass #![feature(box_syntax)] +#![allow(dead_code)] pub fn main() { let mut x: Box<_> = box 3; diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index 043658c950..d588214f50 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -17,7 +17,11 @@ LL | for _ in HashMap::new().iter().cloned() {} found tuple `(&_, &_)` = note: required because of the requirements on the impl of `Iterator` for `Cloned>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving ` as Iterator>::Item == &_` --> $DIR/issue-33941.rs:4:14 @@ -28,7 +32,11 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected reference `&_` found tuple `(&_, &_)` = note: required because of the requirements on the impl of `Iterator` for `Cloned>` - = note: required by `std::iter::Iterator::next` +note: required by `std::iter::Iterator::next` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn next(&mut self) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-34229.stderr b/src/test/ui/issues/issue-34229.stderr index c32fe7e0ec..fba75de8cc 100644 --- a/src/test/ui/issues/issue-34229.stderr +++ b/src/test/ui/issues/issue-34229.stderr @@ -2,10 +2,16 @@ error[E0277]: can't compare `Comparable` with `Comparable` --> $DIR/issue-34229.rs:2:46 | LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable); - | ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable` + | ---------- ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable` + | | + | in this derive macro expansion | = help: the trait `PartialOrd` is not implemented for `Comparable` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3763.stderr b/src/test/ui/issues/issue-3763.stderr index 7f54c9f8a6..6f4567546d 100644 --- a/src/test/ui/issues/issue-3763.stderr +++ b/src/test/ui/issues/issue-3763.stderr @@ -13,12 +13,18 @@ LL | let _woohoo = (Box::new(my_struct)).priv_field; error[E0624]: associated function `happyfun` is private --> $DIR/issue-3763.rs:24:18 | +LL | fn happyfun(&self) {} + | ------------------ private associated function defined here +... LL | (&my_struct).happyfun(); | ^^^^^^^^ private associated function error[E0624]: associated function `happyfun` is private --> $DIR/issue-3763.rs:26:27 | +LL | fn happyfun(&self) {} + | ------------------ private associated function defined here +... LL | (Box::new(my_struct)).happyfun(); | ^^^^^^^^ private associated function diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr index 2a0693a581..f609e47e81 100644 --- a/src/test/ui/issues/issue-39970.stderr +++ b/src/test/ui/issues/issue-39970.stderr @@ -1,9 +1,6 @@ error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` --> $DIR/issue-39970.rs:19:5 | -LL | fn visit() {} - | ---------- required by `Visit::visit` -... LL | <() as Visit>::visit(); | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&()` | @@ -12,6 +9,11 @@ note: required because of the requirements on the impl of `Visit` for `()` | LL | impl Visit for () where | ^^^^^ ^^ +note: required by `Visit::visit` + --> $DIR/issue-39970.rs:6:5 + | +LL | fn visit() {} + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/issues/issue-41255.rs index 5b95a73791..9d7072f166 100644 --- a/src/test/ui/issues/issue-41255.rs +++ b/src/test/ui/issues/issue-41255.rs @@ -10,47 +10,27 @@ fn main() { match x { 5.0 => {}, //~ ERROR floating-point types cannot be used in patterns //~| WARNING hard error - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler but is being 5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error //~| WARNING hard error -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error //~| WARNING hard error 1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns //~| WARNING hard error //~| ERROR floating-point types cannot be used in patterns //~| WARNING hard error - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - //~| ERROR floating-point types cannot be used in patterns //~| ERROR floating-point types cannot be used in patterns //~| WARNING hard error //~| WARNING hard error - //~| WARNING hard error ..71.0 => {} //~^ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error //~| WARNING this was previously accepted by the compiler ..=72.0 => {} //~^ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error //~| WARNING this was previously accepted by the compiler 71.0.. => {} //~^ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error //~| WARNING this was previously accepted by the compiler _ => {}, }; @@ -58,8 +38,6 @@ fn main() { // Same for tuples match (x, 5) { (3.14, 1) => {}, //~ ERROR floating-point types cannot be used - //~| ERROR floating-point types cannot be used - //~| WARNING hard error //~| WARNING hard error _ => {}, } @@ -67,8 +45,6 @@ fn main() { struct Foo { x: f32 }; match (Foo { x }) { Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used - //~| ERROR floating-point types cannot be used - //~| WARNING hard error //~| WARNING hard error _ => {}, } diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/issues/issue-41255.stderr index b6e57afcd1..bf81c8d371 100644 --- a/src/test/ui/issues/issue-41255.stderr +++ b/src/test/ui/issues/issue-41255.stderr @@ -13,7 +13,7 @@ LL | #![forbid(illegal_floating_point_literal_pattern)] = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:15:9 + --> $DIR/issue-41255.rs:13:9 | LL | 5.0f32 => {}, | ^^^^^^ @@ -22,7 +22,7 @@ LL | 5.0f32 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:19:10 + --> $DIR/issue-41255.rs:15:10 | LL | -5.0 => {}, | ^^^ @@ -31,7 +31,7 @@ LL | -5.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:23:9 + --> $DIR/issue-41255.rs:17:9 | LL | 1.0 .. 33.0 => {}, | ^^^ @@ -40,7 +40,7 @@ LL | 1.0 .. 33.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:23:16 + --> $DIR/issue-41255.rs:17:16 | LL | 1.0 .. 33.0 => {}, | ^^^^ @@ -49,7 +49,7 @@ LL | 1.0 .. 33.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:31:9 + --> $DIR/issue-41255.rs:21:9 | LL | 39.0 ..= 70.0 => {}, | ^^^^ @@ -58,7 +58,7 @@ LL | 39.0 ..= 70.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:31:18 + --> $DIR/issue-41255.rs:21:18 | LL | 39.0 ..= 70.0 => {}, | ^^^^ @@ -67,7 +67,7 @@ LL | 39.0 ..= 70.0 => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:40:11 + --> $DIR/issue-41255.rs:26:11 | LL | ..71.0 => {} | ^^^^ @@ -76,7 +76,7 @@ LL | ..71.0 => {} = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:45:12 + --> $DIR/issue-41255.rs:29:12 | LL | ..=72.0 => {} | ^^^^ @@ -85,7 +85,7 @@ LL | ..=72.0 => {} = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:50:9 + --> $DIR/issue-41255.rs:32:9 | LL | 71.0.. => {} | ^^^^ @@ -94,7 +94,7 @@ LL | 71.0.. => {} = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:60:10 + --> $DIR/issue-41255.rs:40:10 | LL | (3.14, 1) => {}, | ^^^^ @@ -103,7 +103,7 @@ LL | (3.14, 1) => {}, = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:69:18 + --> $DIR/issue-41255.rs:47:18 | LL | Foo { x: 2.0 } => {}, | ^^^ @@ -111,113 +111,5 @@ LL | Foo { x: 2.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 -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:11: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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:15:9 - | -LL | 5.0f32 => {}, - | ^^^^^^ - | - = warning: this was previously accepted 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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:19:10 - | -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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:23:9 - | -LL | 1.0 .. 33.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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:23:16 - | -LL | 1.0 .. 33.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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:31:9 - | -LL | 39.0 ..= 70.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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:31:18 - | -LL | 39.0 ..= 70.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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:40:11 - | -LL | ..71.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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:45:12 - | -LL | ..=72.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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:50:9 - | -LL | 71.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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:60:10 - | -LL | (3.14, 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 #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:69:18 - | -LL | Foo { x: 2.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 - -error: aborting due to 24 previous errors +error: aborting due to 12 previous errors diff --git a/src/test/ui/issues/issue-43023.rs b/src/test/ui/issues/issue-43023.rs index 072243d881..c0208e6808 100644 --- a/src/test/ui/issues/issue-43023.rs +++ b/src/test/ui/issues/issue-43023.rs @@ -1,19 +1,19 @@ struct S; impl S { - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s fn f() { file!(); } } trait Tr1 { - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s fn f(); } trait Tr2 { - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s type F; } diff --git a/src/test/ui/issues/issue-43023.stderr b/src/test/ui/issues/issue-43023.stderr index f5f51cdcd4..007eb25959 100644 --- a/src/test/ui/issues/issue-43023.stderr +++ b/src/test/ui/issues/issue-43023.stderr @@ -1,20 +1,28 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43023.rs:4:5 | -LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | / fn f() { +LL | | file!(); +LL | | } + | |_____- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43023.rs:11:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | fn f(); + | ------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-43023.rs:16:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | type F; + | ------- not a `struct`, `enum` or `union` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-43205.rs b/src/test/ui/issues/issue-43205.rs index 894a61f3ef..f47d5a347b 100644 --- a/src/test/ui/issues/issue-43205.rs +++ b/src/test/ui/issues/issue-43205.rs @@ -1,5 +1,5 @@ // run-pass fn main() { - &&[()][0]; + let _ = &&[()][0]; println!("{:?}", &[(),()][1]); } diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index 80aca482b3..4bc5eb03e9 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -10,7 +10,7 @@ LL | { LL | break_me::; | ^^^^^^^^^^^^^^^^^^^^^^^ | | - | expected signature of `fn(>::Assoc) -> _` + | expected signature of `for<'b> fn(>::Assoc) -> _` | found signature of `fn(()) -> _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43988.rs b/src/test/ui/issues/issue-43988.rs index 4b3a0269ba..b114e8e033 100644 --- a/src/test/ui/issues/issue-43988.rs +++ b/src/test/ui/issues/issue-43988.rs @@ -13,13 +13,13 @@ fn main() { #[repr(nothing)] let _x = 0; - //~^^ ERROR attribute should be applied to a struct, enum, or union + //~^^ ERROR E0552 #[repr(something_not_real)] loop { () }; - //~^^^^ ERROR attribute should be applied to a struct, enum, or union + //~^^^^ ERROR E0552 #[repr] let _y = "123"; diff --git a/src/test/ui/issues/issue-43988.stderr b/src/test/ui/issues/issue-43988.stderr index f1205d447e..03aa37f520 100644 --- a/src/test/ui/issues/issue-43988.stderr +++ b/src/test/ui/issues/issue-43988.stderr @@ -26,23 +26,17 @@ LL | #[inline(XYZ)] LL | let _b = 4; | ----------- not a function or closure -error[E0517]: attribute should be applied to a struct, enum, or union +error[E0552]: unrecognized representation hint --> $DIR/issue-43988.rs:14:12 | LL | #[repr(nothing)] | ^^^^^^^ -LL | let _x = 0; - | ----------- not a struct, enum, or union -error[E0517]: attribute should be applied to a struct, enum, or union +error[E0552]: unrecognized representation hint --> $DIR/issue-43988.rs:18:12 | -LL | #[repr(something_not_real)] - | ^^^^^^^^^^^^^^^^^^ -LL | / loop { -LL | | () -LL | | }; - | |_____- not a struct, enum, or union +LL | #[repr(something_not_real)] + | ^^^^^^^^^^^^^^^^^^ error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43988.rs:30:5 @@ -54,5 +48,5 @@ LL | foo(); error: aborting due to 7 previous errors -Some errors have detailed explanations: E0517, E0518. -For more information about an error, try `rustc --explain E0517`. +Some errors have detailed explanations: E0518, E0552. +For more information about an error, try `rustc --explain E0518`. diff --git a/src/test/ui/issues/issue-47412.mir.stderr b/src/test/ui/issues/issue-47412.mir.stderr index 96e50ba679..305f482e8c 100644 --- a/src/test/ui/issues/issue-47412.mir.stderr +++ b/src/test/ui/issues/issue-47412.mir.stderr @@ -7,7 +7,7 @@ LL | match u.void {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/issue-47412.rs:21:11 + --> $DIR/issue-47412.rs:20:11 | LL | match *ptr {} | ^^^^ dereference of raw pointer diff --git a/src/test/ui/issues/issue-47412.rs b/src/test/ui/issues/issue-47412.rs index d395285eee..df6d6e4222 100644 --- a/src/test/ui/issues/issue-47412.rs +++ b/src/test/ui/issues/issue-47412.rs @@ -12,8 +12,7 @@ fn union_field() { union Union { unit: (), void: Void } let u = Union { unit: () }; match u.void {} - //[mir]~^ ERROR access to union field is unsafe - // FIXME(thir-unsafeck): AccessToUnionField unimplemented + //~^ ERROR access to union field is unsafe } fn raw_ptr_deref() { diff --git a/src/test/ui/issues/issue-47412.thir.stderr b/src/test/ui/issues/issue-47412.thir.stderr index 66a0cfcd71..305f482e8c 100644 --- a/src/test/ui/issues/issue-47412.thir.stderr +++ b/src/test/ui/issues/issue-47412.thir.stderr @@ -1,11 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-47412.rs:14:11 + | +LL | match u.void {} + | ^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/issue-47412.rs:21:11 + --> $DIR/issue-47412.rs:20:11 | LL | match *ptr {} | ^^^^ dereference of raw pointer | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/issues/issue-47715.stderr b/src/test/ui/issues/issue-47715.stderr index 296de362db..63a28d997e 100644 --- a/src/test/ui/issues/issue-47715.stderr +++ b/src/test/ui/issues/issue-47715.stderr @@ -1,22 +1,22 @@ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/issue-47715.rs:9:37 | LL | struct Container> { | ^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/issue-47715.rs:14:30 | LL | enum Enum> { | ^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/issue-47715.rs:19:32 | LL | union Union + Copy> { | ^^^^^^^^ -error[E0562]: `impl Trait` not allowed outside of function and inherent method return types +error[E0562]: `impl Trait` not allowed outside of function and method return types --> $DIR/issue-47715.rs:24:30 | LL | type Type> = T; diff --git a/src/test/ui/issues/issue-49934.rs b/src/test/ui/issues/issue-49934.rs index ec73e67063..119d84a068 100644 --- a/src/test/ui/issues/issue-49934.rs +++ b/src/test/ui/issues/issue-49934.rs @@ -7,24 +7,24 @@ fn main() { struct Foo; // fold_stmt (Mac) - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s println!("Hello, world!"); // fold_stmt (Semi) - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s "Hello, world!"; // fold_stmt (Local) - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s let _ = "Hello, world!"; // visit_expr let _ = #[derive(Debug)] "Hello, world!"; - //~^ ERROR `derive` may only be applied to structs, enums and unions + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s let _ = [ // filter_map_expr - #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s "Hello, world!", ]; } diff --git a/src/test/ui/issues/issue-49934.stderr b/src/test/ui/issues/issue-49934.stderr index 7746ad287a..f2ff541bb9 100644 --- a/src/test/ui/issues/issue-49934.stderr +++ b/src/test/ui/issues/issue-49934.stderr @@ -1,32 +1,42 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-49934.rs:10:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | println!("Hello, world!"); + | -------------------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-49934.rs:14:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | "Hello, world!"; + | ---------------- not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-49934.rs:18:5 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | let _ = "Hello, world!"; + | ------------------------ not a `struct`, `enum` or `union` -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-49934.rs:22:13 | LL | let _ = #[derive(Debug)] "Hello, world!"; - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ --------------- not a `struct`, `enum` or `union` + | | + | not applicable here -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/issue-49934.rs:27:9 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | "Hello, world!", + | --------------- not a `struct`, `enum` or `union` error: aborting due to 5 previous errors diff --git a/src/test/ui/issues/issue-51244.rs b/src/test/ui/issues/issue-51244.rs index 509060e1ad..d634b8bf80 100644 --- a/src/test/ui/issues/issue-51244.rs +++ b/src/test/ui/issues/issue-51244.rs @@ -1,4 +1,4 @@ fn main() { let ref my_ref @ _ = 0; - *my_ref = 0; //~ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594] + *my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594] } diff --git a/src/test/ui/issues/issue-51244.stderr b/src/test/ui/issues/issue-51244.stderr index c91083955b..19f0223a35 100644 --- a/src/test/ui/issues/issue-51244.stderr +++ b/src/test/ui/issues/issue-51244.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference +error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference --> $DIR/issue-51244.rs:3:5 | LL | let ref my_ref @ _ = 0; diff --git a/src/test/ui/issues/issue-51515.rs b/src/test/ui/issues/issue-51515.rs index 8eab7b2fa3..54fd176de7 100644 --- a/src/test/ui/issues/issue-51515.rs +++ b/src/test/ui/issues/issue-51515.rs @@ -3,10 +3,10 @@ fn main() { //~^ HELP consider changing this to be a mutable reference //~| SUGGESTION &mut 16 *foo = 32; - //~^ ERROR cannot assign to `*foo` which is behind a `&` reference + //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference let bar = foo; //~^ HELP consider changing this to be a mutable reference //~| SUGGESTION &mut i32 *bar = 64; - //~^ ERROR cannot assign to `*bar` which is behind a `&` reference + //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference } diff --git a/src/test/ui/issues/issue-51515.stderr b/src/test/ui/issues/issue-51515.stderr index 3c208935f3..62bb462faa 100644 --- a/src/test/ui/issues/issue-51515.stderr +++ b/src/test/ui/issues/issue-51515.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*foo` which is behind a `&` reference +error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/issue-51515.rs:5:5 | LL | let foo = &16; @@ -7,7 +7,7 @@ LL | let foo = &16; LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*bar` which is behind a `&` reference +error[E0594]: cannot assign to `*bar`, which is behind a `&` reference --> $DIR/issue-51515.rs:10:5 | LL | let bar = foo; diff --git a/src/test/ui/issues/issue-51714.rs b/src/test/ui/issues/issue-51714.rs index 0dc588d75c..8716524d6f 100644 --- a/src/test/ui/issues/issue-51714.rs +++ b/src/test/ui/issues/issue-51714.rs @@ -1,13 +1,21 @@ fn main() { +//~^ NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body |_: [_; return || {}] | {}; - //~^ ERROR return statement outside of function body + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... [(); return || {}]; - //~^ ERROR return statement outside of function body + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... [(); return |ice| {}]; - //~^ ERROR return statement outside of function body + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... [(); return while let Some(n) = Some(0) {}]; - //~^ ERROR return statement outside of function body + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... } diff --git a/src/test/ui/issues/issue-51714.stderr b/src/test/ui/issues/issue-51714.stderr index 023d9013ab..514d69c1c7 100644 --- a/src/test/ui/issues/issue-51714.stderr +++ b/src/test/ui/issues/issue-51714.stderr @@ -1,26 +1,62 @@ error[E0572]: return statement outside of function body - --> $DIR/issue-51714.rs:2:14 + --> $DIR/issue-51714.rs:6:14 | -LL | |_: [_; return || {}] | {}; - | ^^^^^^^^^^^^ +LL | / fn main() { +LL | | +LL | | +LL | | +LL | | +LL | | |_: [_; return || {}] | {}; + | | ^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body error[E0572]: return statement outside of function body - --> $DIR/issue-51714.rs:5:10 + --> $DIR/issue-51714.rs:10:10 | -LL | [(); return || {}]; - | ^^^^^^^^^^^^ +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return || {}]; + | | ^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body error[E0572]: return statement outside of function body - --> $DIR/issue-51714.rs:8:10 + --> $DIR/issue-51714.rs:14:10 | -LL | [(); return |ice| {}]; - | ^^^^^^^^^^^^^^^ +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return |ice| {}]; + | | ^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body error[E0572]: return statement outside of function body - --> $DIR/issue-51714.rs:11:10 + --> $DIR/issue-51714.rs:18:10 | -LL | [(); return while let Some(n) = Some(0) {}]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return while let Some(n) = Some(0) {}]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_- ...not the enclosing function body error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-5280.rs b/src/test/ui/issues/issue-5280.rs index 3c97dad6b1..5c5ce6c987 100644 --- a/src/test/ui/issues/issue-5280.rs +++ b/src/test/ui/issues/issue-5280.rs @@ -9,7 +9,7 @@ trait FontTableTagConversions { impl FontTableTagConversions for FontTableTag { fn tag_to_string(self) { - &self; + let _ = &self; } } diff --git a/src/test/ui/issues/issue-53498.stderr b/src/test/ui/issues/issue-53498.stderr index 3c0f7f2b55..b28fbff62b 100644 --- a/src/test/ui/issues/issue-53498.stderr +++ b/src/test/ui/issues/issue-53498.stderr @@ -1,6 +1,9 @@ error[E0624]: associated function `foo` is private --> $DIR/issue-53498.rs:16:27 | +LL | fn foo() {} + | -------- private associated function defined here +... LL | test::Foo::::foo(); | ^^^ private associated function diff --git a/src/test/ui/issues/issue-54696.rs b/src/test/ui/issues/issue-54696.rs index d8408ed854..15355d30db 100644 --- a/src/test/ui/issues/issue-54696.rs +++ b/src/test/ui/issues/issue-54696.rs @@ -2,7 +2,7 @@ fn main() { // We shouldn't promote this - &(main as fn() == main as fn()); + let _ = &(main as fn() == main as fn()); // Also check nested case - &(&(main as fn()) == &(main as fn())); + let _ = &(&(main as fn()) == &(main as fn())); } diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr index fb31467ec4..a1715bd99e 100644 --- a/src/test/ui/issues/issue-58022.stderr +++ b/src/test/ui/issues/issue-58022.stderr @@ -7,9 +7,6 @@ LL | Foo(Box::new(*slice)) error[E0283]: type annotations needed --> $DIR/issue-58022.rs:4:25 | -LL | const SIZE: usize; - | ------------------ required by `Foo::SIZE` -LL | LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; | ^^^^^^^^^ | | @@ -18,6 +15,11 @@ LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; | = note: cannot satisfy `_: Foo` = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` +note: required by `Foo::SIZE` + --> $DIR/issue-58022.rs:2:5 + | +LL | const SIZE: usize; + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index 93d2f3001f..46d1f99241 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -84,11 +84,6 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` | LL | assert_eq!(Foo::Bar, i); | ^^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - ::: $SRC_DIR/core/src/panicking.rs:LL:COL - | -LL | T: fmt::Debug + ?Sized, - | ---------- required by this bound in `core::panicking::assert_failed` | = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index 650570b647..149562f8fb 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -10,7 +10,7 @@ LL | F: for<'a> FnMut(>::Item), LL | foo((), drop) | ^^^^ | | - | expected signature of `fn(<() as Trait<'a>>::Item) -> _` + | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` | found signature of `fn(()) -> _` error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time diff --git a/src/test/ui/issues/issue-66353.stderr b/src/test/ui/issues/issue-66353.stderr index 8fd50300ca..59a521c736 100644 --- a/src/test/ui/issues/issue-66353.stderr +++ b/src/test/ui/issues/issue-66353.stderr @@ -7,11 +7,14 @@ LL | _Func::< <() as _A>::AssocT >::func(()); error[E0277]: the trait bound `(): _Func<_>` is not satisfied --> $DIR/issue-66353.rs:12:41 | -LL | fn func(_: Self); - | ----------------- required by `_Func::func` -... LL | _Func::< <() as _A>::AssocT >::func(()); | ^^ the trait `_Func<_>` is not implemented for `()` + | +note: required by `_Func::func` + --> $DIR/issue-66353.rs:4:5 + | +LL | fn func(_: Self); + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-6804.rs b/src/test/ui/issues/issue-6804.rs index 6d950c424e..0260caa82c 100644 --- a/src/test/ui/issues/issue-6804.rs +++ b/src/test/ui/issues/issue-6804.rs @@ -9,16 +9,12 @@ fn main() { let x = NAN; match x { NAN => {}, //~ ERROR floating-point types cannot be used - //~^ WARN this was previously accepted by the compiler but is being phased out - //~| ERROR floating-point types cannot be used in patterns //~| WARN this was previously accepted by the compiler but is being phased out _ => {}, }; match [x, 1.0] { [NAN, _] => {}, //~ ERROR floating-point types cannot be used - //~| ERROR floating-point types cannot be used - //~| 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/issues/issue-6804.stderr b/src/test/ui/issues/issue-6804.stderr index c7411e27c2..4e2961e5e2 100644 --- a/src/test/ui/issues/issue-6804.stderr +++ b/src/test/ui/issues/issue-6804.stderr @@ -13,7 +13,7 @@ LL | #![deny(illegal_floating_point_literal_pattern)] = note: for more information, see issue #41620 error: floating-point types cannot be used in patterns - --> $DIR/issue-6804.rs:19:10 + --> $DIR/issue-6804.rs:17:10 | LL | [NAN, _] => {}, | ^^^ @@ -21,23 +21,5 @@ 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 -error: floating-point types cannot be used in patterns - --> $DIR/issue-6804.rs:11:9 - | -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 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-6804.rs:19:10 - | -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 - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs b/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs index 69fc0c1cbb..6880e1a462 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs @@ -4,7 +4,7 @@ macro_rules! suite { const A = "A".$fn(); //~^ ERROR the name `A` is defined multiple times //~| ERROR missing type for `const` item - //~| ERROR the type placeholder `_` is not allowed within types + //~| ERROR the type placeholder `_` is not allowed within types on item signatures for constants )* } } diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr index a84c048fab..34c2073db0 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -20,7 +20,7 @@ error: missing type for `const` item --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19 | LL | const A = "A".$fn(); - | ^ help: provide a type for the item: `A: usize` + | ^ help: provide a type for the constant: `A: usize` ... LL | / suite! { LL | | len; @@ -30,7 +30,7 @@ LL | | } | = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19 | LL | const A = "A".$fn(); 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 0f095f5a77..f074a99e5e 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 @@ -28,11 +28,6 @@ LL | fn a() -> i32 { ... LL | assert_eq!(a, 0); | ^^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - ::: $SRC_DIR/core/src/panicking.rs:LL:COL - | -LL | T: fmt::Debug + ?Sized, - | ---------- required by this bound in `core::panicking::assert_failed` | = help: the trait `Debug` is not implemented for `fn() -> i32 {a}` = help: use parentheses to call the function: `a()` diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr index 3443cca5f3..af3459a7d2 100644 --- a/src/test/ui/issues/issue-72690.stderr +++ b/src/test/ui/issues/issue-72690.stderr @@ -5,7 +5,11 @@ LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0282]: type annotations needed --> $DIR/issue-72690.rs:11:6 @@ -30,7 +34,11 @@ LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:25:5 @@ -39,7 +47,11 @@ LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:33:5 @@ -48,7 +60,11 @@ LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:41:5 @@ -57,7 +73,11 @@ LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:47:5 @@ -66,7 +86,11 @@ LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:55:5 @@ -75,7 +99,11 @@ LL | String::from("x".as_ref()); | ^^^^^^^^^^^^ cannot infer type for reference `&_` | = note: cannot satisfy `String: From<&_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/src/test/ui/issues/issue-73886.stderr b/src/test/ui/issues/issue-73886.stderr index 31f642ea66..a6f8ba65ab 100644 --- a/src/test/ui/issues/issue-73886.stderr +++ b/src/test/ui/issues/issue-73886.stderr @@ -8,7 +8,9 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>` --> $DIR/issue-73886.rs:4:13 | LL | let _ = 7u32 as Option<_>; - | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)` + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-87199.rs b/src/test/ui/issues/issue-87199.rs new file mode 100644 index 0000000000..a80a64a2f8 --- /dev/null +++ b/src/test/ui/issues/issue-87199.rs @@ -0,0 +1,20 @@ +// Regression test for issue #87199, where attempting to relax a bound +// other than the only supported `?Sized` would still cause the compiler +// to assume that the `Sized` bound was relaxed. + +// check-fail + +// Check that these function definitions only emit warnings, not errors +fn arg(_: T) {} +//~^ warning: default bound relaxed for a type parameter, but this does nothing +fn ref_arg(_: &T) {} +//~^ warning: default bound relaxed for a type parameter, but this does nothing +fn ret() -> impl Iterator + ?Send { std::iter::empty() } +//~^ warning: default bound relaxed for a type parameter, but this does nothing + +// Check that there's no `?Sized` relaxation! +fn main() { + ref_arg::(&5); + ref_arg::<[i32]>(&[5]); + //~^ the size for values of type `[i32]` cannot be known +} diff --git a/src/test/ui/issues/issue-87199.stderr b/src/test/ui/issues/issue-87199.stderr new file mode 100644 index 0000000000..e3a8e82a09 --- /dev/null +++ b/src/test/ui/issues/issue-87199.stderr @@ -0,0 +1,36 @@ +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/issue-87199.rs:8:8 + | +LL | fn arg(_: T) {} + | ^ + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/issue-87199.rs:10:12 + | +LL | fn ref_arg(_: &T) {} + | ^ + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/issue-87199.rs:12:13 + | +LL | fn ret() -> impl Iterator + ?Send { std::iter::empty() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-87199.rs:18:22 + | +LL | fn ref_arg(_: &T) {} + | - required by this bound in `ref_arg` +... +LL | ref_arg::<[i32]>(&[5]); + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn ref_arg(_: &T) {} + | ^^^^^^^^ + +error: aborting due to previous error; 3 warnings emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/iterators/integral.stderr b/src/test/ui/iterators/integral.stderr index e31ee59785..60b2cbfdf4 100644 --- a/src/test/ui/iterators/integral.stderr +++ b/src/test/ui/iterators/integral.stderr @@ -7,7 +7,11 @@ LL | for _ in 42 {} = help: the trait `Iterator` is not implemented for `{integer}` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `{integer}` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u8` is not an iterator --> $DIR/integral.rs:4:14 @@ -18,7 +22,11 @@ LL | for _ in 42 as u8 {} = help: the trait `Iterator` is not implemented for `u8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u8` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i8` is not an iterator --> $DIR/integral.rs:6:14 @@ -29,7 +37,11 @@ LL | for _ in 42 as i8 {} = help: the trait `Iterator` is not implemented for `i8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i8` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u16` is not an iterator --> $DIR/integral.rs:8:14 @@ -40,7 +52,11 @@ LL | for _ in 42 as u16 {} = help: the trait `Iterator` is not implemented for `u16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u16` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i16` is not an iterator --> $DIR/integral.rs:10:14 @@ -51,7 +67,11 @@ LL | for _ in 42 as i16 {} = help: the trait `Iterator` is not implemented for `i16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i16` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u32` is not an iterator --> $DIR/integral.rs:12:14 @@ -62,7 +82,11 @@ LL | for _ in 42 as u32 {} = help: the trait `Iterator` is not implemented for `u32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u32` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i32` is not an iterator --> $DIR/integral.rs:14:14 @@ -73,7 +97,11 @@ LL | for _ in 42 as i32 {} = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i32` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `u64` is not an iterator --> $DIR/integral.rs:16:14 @@ -84,7 +112,11 @@ LL | for _ in 42 as u64 {} = help: the trait `Iterator` is not implemented for `u64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `u64` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `i64` is not an iterator --> $DIR/integral.rs:18:14 @@ -95,7 +127,11 @@ LL | for _ in 42 as i64 {} = help: the trait `Iterator` is not implemented for `i64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `i64` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `usize` is not an iterator --> $DIR/integral.rs:20:14 @@ -106,7 +142,11 @@ LL | for _ in 42 as usize {} = help: the trait `Iterator` is not implemented for `usize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `usize` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `isize` is not an iterator --> $DIR/integral.rs:22:14 @@ -117,7 +157,11 @@ LL | for _ in 42 as isize {} = help: the trait `Iterator` is not implemented for `isize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `isize` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `{float}` is not an iterator --> $DIR/integral.rs:24:14 @@ -127,7 +171,11 @@ LL | for _ in 42.0 {} | = help: the trait `Iterator` is not implemented for `{float}` = note: required because of the requirements on the impl of `IntoIterator` for `{float}` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.rs b/src/test/ui/iterators/into-iter-on-arrays-2018.rs index 5661397b3c..e56c2956a6 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.rs @@ -12,12 +12,12 @@ fn main() { // Before 2021, the method dispatched to `IntoIterator for &[T; N]`, // which we continue to support for compatibility. let _: Iter<'_, i32> = array.into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning let _: Iter<'_, i32> = Box::new(array).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning // The `array_into_iter` lint doesn't cover other wrappers that deref to an array. let _: Iter<'_, i32> = Rc::new(array).into_iter(); @@ -25,6 +25,10 @@ fn main() { // But you can always use the trait method explicitly as an array. let _: IntoIter = IntoIterator::into_iter(array); + + for _ in [1, 2, 3].into_iter() {} + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning } /// User type that dereferences to an array. 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 b43338382f..3bd3ca6e87 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr @@ -1,42 +1,54 @@ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. --> $DIR/into-iter-on-arrays-2018.rs:14:34 | LL | let _: Iter<'_, i32> = array.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = note: `#[warn(array_into_iter)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | let _: Iter<'_, i32> = array.iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | let _: Iter<'_, i32> = IntoIterator::into_iter(array); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. --> $DIR/into-iter-on-arrays-2018.rs:18:44 | LL | let _: Iter<'_, i32> = Box::new(array).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -warning: 2 warnings emitted - -Future incompatibility report: Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-2018.rs:14:34 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | let _: Iter<'_, i32> = array.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | let _: Iter<'_, i32> = Box::new(array).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = note: `#[warn(array_into_iter)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-2018.rs:18:44 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-2018.rs:29:24 | -LL | let _: Iter<'_, i32> = Box::new(array).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | for _ in [1, 2, 3].into_iter() {} + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | for _ in [1, 2, 3].iter() {} + | ^^^^ +help: or remove `.into_iter()` to iterate by value + | +LL | for _ in [1, 2, 3] {} + | -- + +warning: 3 warnings emitted diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed index 7f511bde3c..0055758a6a 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed @@ -1,5 +1,6 @@ // run-pass // run-rustfix +// rustfix-only-machine-applicable fn main() { let small = [1, 2]; @@ -7,43 +8,43 @@ fn main() { // Expressions that should trigger the lint small.iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning [1, 2].iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning big.iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning [0u8; 33].iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(small).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new([1, 2]).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(big).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new([0u8; 33]).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new(small)).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new([1, 2])).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new(big)).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new([0u8; 33])).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning // Expressions that should not (&[1, 2]).into_iter(); diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.rs b/src/test/ui/iterators/into-iter-on-arrays-lint.rs index d5fe83a783..01857c78a7 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs @@ -1,5 +1,6 @@ // run-pass // run-rustfix +// rustfix-only-machine-applicable fn main() { let small = [1, 2]; @@ -7,43 +8,43 @@ fn main() { // Expressions that should trigger the lint small.into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning [1, 2].into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning big.into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning [0u8; 33].into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(small).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new([1, 2]).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(big).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new([0u8; 33]).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new(small)).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new([1, 2])).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new(big)).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning Box::new(Box::new([0u8; 33])).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` - //~| WARNING this was previously accepted by the compiler but is being phased out + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning // Expressions that should not (&[1, 2]).into_iter(); diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr index 211315c3fc..01789e0e25 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -1,247 +1,207 @@ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:9:11 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:10:11 | LL | small.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = note: `#[warn(array_into_iter)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:12:12 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | [1, 2].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | small.iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(small); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:15:9 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:13:12 | -LL | big.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | [1, 2].into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:18:15 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | [0u8; 33].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | [1, 2].iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter([1, 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:22:21 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:16:9 | -LL | Box::new(small).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | big.into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:25:22 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | Box::new([1, 2]).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | big.iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(big); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:28:19 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:19:15 | -LL | Box::new(big).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 - -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:31:25 - | -LL | Box::new([0u8; 33]).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | [0u8; 33].into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:35:31 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | Box::new(Box::new(small)).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | [0u8; 33].iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter([0u8; 33]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:38:32 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:23:21 | -LL | Box::new(Box::new([1, 2])).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(small).into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:41:29 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | Box::new(Box::new(big)).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(small).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new(small)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:44:35 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:26:22 | -LL | Box::new(Box::new([0u8; 33])).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new([1, 2]).into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -warning: 12 warnings emitted - -Future incompatibility report: Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:9:11 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | small.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new([1, 2]).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = note: `#[warn(array_into_iter)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new([1, 2])); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:12:12 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:29:19 | -LL | [1, 2].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(big).into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:15:9 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | big.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(big).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new(big)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:18:15 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:32:25 | -LL | [0u8; 33].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new([0u8; 33]).into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:22:21 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | Box::new(small).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new([0u8; 33]).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new([0u8; 33])); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:25:22 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:36:31 | -LL | Box::new([1, 2]).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(Box::new(small)).into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:28:19 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | Box::new(big).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(Box::new(small)).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new(Box::new(small))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:31:25 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:39:32 | -LL | Box::new([0u8; 33]).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(Box::new([1, 2])).into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:35:31 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | Box::new(Box::new(small)).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(Box::new([1, 2])).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new(Box::new([1, 2]))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:38:32 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:42:29 | -LL | Box::new(Box::new([1, 2])).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(Box::new(big)).into_iter(); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:41:29 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | Box::new(Box::new(big)).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(Box::new(big)).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new(Box::new(big))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:44:35 +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. + --> $DIR/into-iter-on-arrays-lint.rs:45:35 | LL | Box::new(Box::new([0u8; 33])).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 - -Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/into-iter-on-arrays-lint.rs:60:12 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | -LL | [0, 1].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` +LL | Box::new(Box::new([0u8; 33])).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value | -note: the lint level is defined here - --> $DIR/into-iter-on-arrays-lint.rs:59:13 - | -LL | #[allow(array_into_iter)] - | ^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #66145 +LL | IntoIterator::into_iter(Box::new(Box::new([0u8; 33]))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ + +warning: 12 warnings emitted diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr index 73844329e3..fdc33862c0 100644 --- a/src/test/ui/iterators/ranges.stderr +++ b/src/test/ui/iterators/ranges.stderr @@ -7,7 +7,11 @@ LL | for _ in ..10 {} = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator --> $DIR/ranges.rs:4:14 @@ -18,7 +22,11 @@ LL | for _ in ..=10 {} = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr index 1d77bcb753..f7089be277 100644 --- a/src/test/ui/iterators/string.stderr +++ b/src/test/ui/iterators/string.stderr @@ -6,7 +6,11 @@ LL | for _ in "".to_owned() {} | = help: the trait `Iterator` is not implemented for `String` = note: required because of the requirements on the impl of `IntoIterator` for `String` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `&str` is not an iterator --> $DIR/string.rs:4:14 @@ -16,7 +20,11 @@ LL | for _ in "" {} | = help: the trait `Iterator` is not implemented for `&str` = note: required because of the requirements on the impl of `IntoIterator` for `&str` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-36638.rs b/src/test/ui/keyword/keyword-self-as-type-param.rs similarity index 85% rename from src/test/ui/issues/issue-36638.rs rename to src/test/ui/keyword/keyword-self-as-type-param.rs index 2e64853697..785d64ec8e 100644 --- a/src/test/ui/issues/issue-36638.rs +++ b/src/test/ui/keyword/keyword-self-as-type-param.rs @@ -1,3 +1,5 @@ +// Regression test of #36638. + struct Foo(Self); //~^ ERROR expected identifier, found keyword `Self` //~^^ ERROR E0392 diff --git a/src/test/ui/issues/issue-36638.stderr b/src/test/ui/keyword/keyword-self-as-type-param.stderr similarity index 83% rename from src/test/ui/issues/issue-36638.stderr rename to src/test/ui/keyword/keyword-self-as-type-param.stderr index 733fc4af53..cc3df2e36f 100644 --- a/src/test/ui/issues/issue-36638.stderr +++ b/src/test/ui/keyword/keyword-self-as-type-param.stderr @@ -1,17 +1,17 @@ error: expected identifier, found keyword `Self` - --> $DIR/issue-36638.rs:1:12 + --> $DIR/keyword-self-as-type-param.rs:3:12 | LL | struct Foo(Self); | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/issue-36638.rs:5:11 + --> $DIR/keyword-self-as-type-param.rs:7:11 | LL | trait Bar {} | ^^^^ expected identifier, found keyword error[E0392]: parameter `Self` is never used - --> $DIR/issue-36638.rs:1:12 + --> $DIR/keyword-self-as-type-param.rs:3:12 | LL | struct Foo(Self); | ^^^^ unused parameter diff --git a/src/test/ui/lang-items/issue-86238.rs b/src/test/ui/lang-items/issue-86238.rs new file mode 100644 index 0000000000..509f94f383 --- /dev/null +++ b/src/test/ui/lang-items/issue-86238.rs @@ -0,0 +1,16 @@ +// Regression test for the ICE described in issue #86238. + +#![feature(lang_items)] +#![feature(no_core)] + +#![no_core] +fn main() { + let one = || {}; + one() + //~^ ERROR: failed to find an overloaded call trait for closure call + //~| HELP: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined +} +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} diff --git a/src/test/ui/lang-items/issue-86238.stderr b/src/test/ui/lang-items/issue-86238.stderr new file mode 100644 index 0000000000..767e6de226 --- /dev/null +++ b/src/test/ui/lang-items/issue-86238.stderr @@ -0,0 +1,10 @@ +error: failed to find an overloaded call trait for closure call + --> $DIR/issue-86238.rs:9:5 + | +LL | one() + | ^^^^^ + | + = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have associated `call`/`call_mut`/`call_once` functions + +error: aborting due to previous error + diff --git a/src/test/ui/limits/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/limits/issue-69485-var-size-diffs-too-large.stderr index c229458da4..f7923bd474 100644 --- a/src/test/ui/limits/issue-69485-var-size-diffs-too-large.stderr +++ b/src/test/ui/limits/issue-69485-var-size-diffs-too-large.stderr @@ -1,8 +1,8 @@ error: values of the type `[u8; 18446744073709551615]` are too big for the current architecture - --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:12 + --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:5 | LL | Bug::V([0; !0]); - | ^^^^^^^ + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lint/bare-trait-objects-path.rs b/src/test/ui/lint/bare-trait-objects-path.rs index 74f838e9ed..0a7c5a8dbd 100644 --- a/src/test/ui/lint/bare-trait-objects-path.rs +++ b/src/test/ui/lint/bare-trait-objects-path.rs @@ -13,12 +13,12 @@ impl Assoc for dyn Dyn {} fn main() { Dyn::func(); //~^ WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition ::Dyn::func(); //~^ WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition Dyn::CONST; //~^ WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition let _: Dyn::Ty; //~ ERROR ambiguous associated type } diff --git a/src/test/ui/lint/bare-trait-objects-path.stderr b/src/test/ui/lint/bare-trait-objects-path.stderr index 55c9ea234d..40fafc4b3b 100644 --- a/src/test/ui/lint/bare-trait-objects-path.stderr +++ b/src/test/ui/lint/bare-trait-objects-path.stderr @@ -11,7 +11,7 @@ LL | Dyn::func(); | ^^^ help: use `dyn`: `` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 warning: trait objects without an explicit `dyn` are deprecated @@ -20,7 +20,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | ::Dyn::func(); | ^^^^^ help: use `dyn`: `` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 warning: trait objects without an explicit `dyn` are deprecated @@ -29,7 +29,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | Dyn::CONST; | ^^^ help: use `dyn`: `` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: aborting due to previous error; 3 warnings emitted diff --git a/src/test/ui/lint/cli-lint-override.forbid_warn.stderr b/src/test/ui/lint/cli-lint-override.forbid_warn.stderr new file mode 100644 index 0000000000..ff4dc4abc7 --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.forbid_warn.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +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 + +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 new file mode 100644 index 0000000000..74e7823e1f --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr @@ -0,0 +1,11 @@ +warning: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +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 + +warning: 1 warning emitted + diff --git a/src/test/ui/lint/cli-lint-override.rs b/src/test/ui/lint/cli-lint-override.rs new file mode 100644 index 0000000000..a0a96d01be --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.rs @@ -0,0 +1,17 @@ +// Tests that subsequent lints specified via the command line override +// each other, except for ForceWarn and Forbid, which cannot be overriden. +// +// revisions: warn_deny forbid_warn force_warn_deny +// +//[warn_deny] compile-flags: --warn missing_abi --deny missing_abi +//[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi +//[force_warn_deny] compile-flags: -Z unstable-options --force-warn missing_abi --allow missing_abi +//[force_warn_deny] check-pass + + +extern fn foo() {} +//[warn_deny]~^ ERROR extern declarations without an explicit ABI are deprecated +//[forbid_warn]~^^ ERROR extern declarations without an explicit ABI are deprecated +//[force_warn_deny]~^^^ WARN extern declarations without an explicit ABI are deprecated + +fn main() {} diff --git a/src/test/ui/lint/cli-lint-override.warn_deny.stderr b/src/test/ui/lint/cli-lint-override.warn_deny.stderr new file mode 100644 index 0000000000..2d869adfd3 --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.warn_deny.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +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 + +error: aborting due to previous error + diff --git a/src/test/ui/lint/cli-unknown-force-warn.rs b/src/test/ui/lint/cli-unknown-force-warn.rs new file mode 100644 index 0000000000..55544cc737 --- /dev/null +++ b/src/test/ui/lint/cli-unknown-force-warn.rs @@ -0,0 +1,7 @@ +// Checks that rustc correctly errors when passed an invalid lint with +// `--force-warn`. This is a regression test for issue #86958. +// +// compile-flags: -Z unstable-options --force-warn foo-qux +// error-pattern: unknown lint: `foo_qux` + +fn main() {} diff --git a/src/test/ui/lint/cli-unknown-force-warn.stderr b/src/test/ui/lint/cli-unknown-force-warn.stderr new file mode 100644 index 0000000000..4367c3b450 --- /dev/null +++ b/src/test/ui/lint/cli-unknown-force-warn.stderr @@ -0,0 +1,15 @@ +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/lint/command-line-register-lint-tool.rs b/src/test/ui/lint/command-line-register-lint-tool.rs new file mode 100644 index 0000000000..d6e95fd3ec --- /dev/null +++ b/src/test/ui/lint/command-line-register-lint-tool.rs @@ -0,0 +1,7 @@ +// compile-flags: -A known_tool::foo +// check-pass + +#![feature(register_tool)] +#![register_tool(known_tool)] + +fn main() {} diff --git a/src/test/ui/lint/command-line-register-unknown-lint-tool.rs b/src/test/ui/lint/command-line-register-unknown-lint-tool.rs new file mode 100644 index 0000000000..59fc020009 --- /dev/null +++ b/src/test/ui/lint/command-line-register-unknown-lint-tool.rs @@ -0,0 +1,4 @@ +// compile-flags: -A unknown_tool::foo +// error-pattern: unknown lint tool: `unknown_tool` + +fn main() {} diff --git a/src/test/ui/lint/command-line-register-unknown-lint-tool.stderr b/src/test/ui/lint/command-line-register-unknown-lint-tool.stderr new file mode 100644 index 0000000000..c9a2aff213 --- /dev/null +++ b/src/test/ui/lint/command-line-register-unknown-lint-tool.stderr @@ -0,0 +1,11 @@ +error[E0602]: unknown lint tool: `unknown_tool` + | + = note: requested on the command line with `-A unknown_tool::foo` + +error[E0602]: unknown lint tool: `unknown_tool` + | + = note: requested on the command line with `-A unknown_tool::foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/lint/dead-code/self-assign.rs b/src/test/ui/lint/dead-code/self-assign.rs new file mode 100644 index 0000000000..ea7ce98d88 --- /dev/null +++ b/src/test/ui/lint/dead-code/self-assign.rs @@ -0,0 +1,52 @@ +// Test that dead code warnings are issued for superfluous assignments of +// fields or variables to themselves (issue #75356). + +// ignore-test FIXME(81658, 83171) + +// check-pass +#![allow(unused_assignments)] +#![warn(dead_code)] + +fn main() { + let mut x = 0; + x = x; + //~^ WARNING: useless assignment of variable of type `i32` to itself + + x = (x); + //~^ WARNING: useless assignment of variable of type `i32` to itself + + x = {x}; + // block expressions don't count as self-assignments + + + struct S<'a> { f: &'a str } + let mut s = S { f: "abc" }; + s = s; + //~^ WARNING: useless assignment of variable of type `S` to itself + + s.f = s.f; + //~^ WARNING: useless assignment of field of type `&str` to itself + + + struct N0 { x: Box } + struct N1 { n: N0 } + struct N2(N1); + struct N3 { n: N2 }; + let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) }; + n3.n.0.n.x = n3.n.0.n.x; + //~^ WARNING: useless assignment of field of type `Box` to itself + + let mut t = (1, ((2, 3, (4, 5)),)); + t.1.0.2.1 = t.1.0.2.1; + //~^ WARNING: useless assignment of field of type `i32` to itself + + + let mut y = 0; + macro_rules! assign_to_y { + ($cur:expr) => {{ + y = $cur; + }}; + } + assign_to_y!(y); + // self-assignments in macro expansions are not reported either +} diff --git a/src/test/ui/lint/dead-code/self-assign.stderr b/src/test/ui/lint/dead-code/self-assign.stderr new file mode 100644 index 0000000000..bb79c0ec72 --- /dev/null +++ b/src/test/ui/lint/dead-code/self-assign.stderr @@ -0,0 +1,44 @@ +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:10:5 + | +LL | x = x; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/self-assign.rs:6:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:13:5 + | +LL | x = (x); + | ^^^^^^^ + +warning: useless assignment of variable of type `S` to itself + --> $DIR/self-assign.rs:22:5 + | +LL | s = s; + | ^^^^^ + +warning: useless assignment of field of type `&str` to itself + --> $DIR/self-assign.rs:25:5 + | +LL | s.f = s.f; + | ^^^^^^^^^ + +warning: useless assignment of field of type `Box` to itself + --> $DIR/self-assign.rs:34:5 + | +LL | n3.n.0.n.x = n3.n.0.n.x; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: useless assignment of field of type `i32` to itself + --> $DIR/self-assign.rs:38:5 + | +LL | t.1.0.2.1 = t.1.0.2.1; + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: 6 warnings emitted + diff --git a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs index 0a3e20b4f7..4799429ea2 100644 --- a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs +++ b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns elided_lifetimes_in_paths -Zunstable-options +// compile-flags: --force-warn elided_lifetimes_in_paths -Zunstable-options // check-pass struct Foo<'a> { diff --git a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr index 0e0e934c76..05513de81d 100644 --- a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr @@ -4,7 +4,7 @@ warning: hidden lifetime parameters in types are deprecated LL | fn foo(x: &Foo) {} | ^^^- help: indicate the anonymous lifetime: `<'_>` | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warn elided-lifetimes-in-paths` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs index 0abc491372..d066feba86 100644 --- a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs +++ b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns const_err -Zunstable-options +// compile-flags: --force-warn const_err -Zunstable-options // check-pass #![allow(const_err)] diff --git a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr index bad12f94b1..dd4f88a3b5 100644 --- a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr @@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0; | | | attempt to divide `1_i32` by zero | - = note: warning forced by `force-warns` commandline option + = 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 diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.rs b/src/test/ui/lint/force-warn/force-allowed-warning.rs index bac0e4f8f8..280de50647 100644 --- a/src/test/ui/lint/force-warn/force-allowed-warning.rs +++ b/src/test/ui/lint/force-warn/force-allowed-warning.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns dead_code -Zunstable-options +// compile-flags: --force-warn dead_code -Zunstable-options // check-pass #![allow(dead_code)] diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.stderr b/src/test/ui/lint/force-warn/force-allowed-warning.stderr index 145798a32a..fced147254 100644 --- a/src/test/ui/lint/force-warn/force-allowed-warning.stderr +++ b/src/test/ui/lint/force-warn/force-allowed-warning.stderr @@ -4,7 +4,7 @@ warning: function is never used: `dead_function` LL | fn dead_function() {} | ^^^^^^^^^^^^^ | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warn dead-code` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs index e721760ab2..8331df02da 100644 --- a/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs +++ b/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns const_err -Zunstable-options +// compile-flags: --force-warn const_err -Zunstable-options // check-pass const C: i32 = 1 / 0; diff --git a/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr index 4b004cf367..68cd3a392f 100644 --- a/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr +++ b/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr @@ -6,7 +6,7 @@ LL | const C: i32 = 1 / 0; | | | attempt to divide `1_i32` by zero | - = note: warning forced by `force-warns` commandline option + = 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 diff --git a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs index 0dc1ce28ac..0e8a65a411 100644 --- a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs +++ b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns dead_code -Zunstable-options +// compile-flags: --force-warn dead_code -Zunstable-options // check-pass #![allow(warnings)] diff --git a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr index 577dbe1fea..3305f2c028 100644 --- a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr +++ b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr @@ -4,7 +4,7 @@ warning: function is never used: `dead_function` LL | fn dead_function() {} | ^^^^^^^^^^^^^ | - = note: warning forced by `force-warns` commandline option + = note: requested on the command line with `--force-warn dead-code` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs index 4f637c7fef..aaca59a2a2 100644 --- a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs +++ b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns nonstandard_style -Zunstable-options +// compile-flags: --force-warn nonstandard_style -Zunstable-options // check-pass #![allow(warnings)] diff --git a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr index 8665fa2610..065a8f6a55 100644 --- a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr +++ b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr @@ -4,7 +4,7 @@ warning: function `FUNCTION` should have a snake case name LL | pub fn FUNCTION() {} | ^^^^^^^^ help: convert the identifier to snake case: `function` | - = note: warning forced by `force-warns` commandline option + = note: `--force-warn non-snake-case` implied by `--force-warn nonstandard-style` warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs index bb2f394aef..d8447bd238 100644 --- a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs +++ b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns bare_trait_objects -Zunstable-options +// compile-flags: --force-warn bare_trait_objects -Zunstable-options // check-pass #![allow(rust_2018_idioms)] @@ -7,6 +7,6 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this was previously accepted by the compiler +//~| WARN this is accepted in the current edition fn main() {} diff --git a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr index 40750ffea8..185c0e8e3d 100644 --- a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr +++ b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr @@ -4,8 +4,8 @@ warning: trait objects without an explicit `dyn` are deprecated LL | pub fn function(_x: Box) {} | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = note: warning forced by `force-warns` commandline option - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = 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 issue #80165 warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs new file mode 100644 index 0000000000..e10d161e7c --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.rs @@ -0,0 +1,10 @@ +// compile-flags: --cap-lints allow --force-warn bare_trait_objects -Zunstable-options +// check-pass + +pub trait SomeTrait {} + +pub fn function(_x: Box) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr new file mode 100644 index 0000000000..a899705877 --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr @@ -0,0 +1,12 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/force-warn-cap-lints-allow.rs:6:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ help: use `dyn`: `dyn 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 issue #80165 + +warning: 1 warning emitted + diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs new file mode 100644 index 0000000000..4afc086860 --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.rs @@ -0,0 +1,15 @@ +// compile-flags: --cap-lints warn --force-warn rust-2021-compatibility -Zunstable-options +// check-pass +#![allow(ellipsis_inclusive_range_patterns)] + +pub fn f() -> bool { + let x = 123; + match x { + 0...100 => true, + //~^ WARN range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => false, + } +} + +fn main() {} diff --git a/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr new file mode 100644 index 0000000000..1d5f88086c --- /dev/null +++ b/src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr @@ -0,0 +1,12 @@ +warning: `...` range patterns are deprecated + --> $DIR/force-warn-cap-lints-warn.rs:8:10 + | +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 issue #80165 + +warning: 1 warning emitted + diff --git a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs index fd029a3d55..193ba2b6f0 100644 --- a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs +++ b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns rust_2018_idioms -Zunstable-options +// compile-flags: --force-warn rust-2018-idioms -Zunstable-options // check-pass #![allow(bare_trait_objects)] @@ -7,6 +7,6 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this was previously accepted by the compiler +//~| WARN this is accepted in the current edition fn main() {} diff --git a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr index 88ae846caa..d242ef266b 100644 --- a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr +++ b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr @@ -4,8 +4,8 @@ warning: trait objects without an explicit `dyn` are deprecated LL | pub fn function(_x: Box) {} | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = note: warning forced by `force-warns` commandline option - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = 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 issue #80165 warning: 1 warning emitted diff --git a/src/test/ui/lint/force-warn/force-warn-group.rs b/src/test/ui/lint/force-warn/force-warn-group.rs index c97eeabbd4..0198610b78 100644 --- a/src/test/ui/lint/force-warn/force-warn-group.rs +++ b/src/test/ui/lint/force-warn/force-warn-group.rs @@ -1,4 +1,4 @@ -// compile-flags: --force-warns rust_2018_idioms -Zunstable-options +// compile-flags: --force-warn rust_2018_idioms -Zunstable-options // check-pass #![allow(rust_2018_idioms)] @@ -7,6 +7,6 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this was previously accepted by the compiler +//~| WARN this is accepted in the current edition fn main() {} diff --git a/src/test/ui/lint/force-warn/force-warn-group.stderr b/src/test/ui/lint/force-warn/force-warn-group.stderr index f808727991..180dff880a 100644 --- a/src/test/ui/lint/force-warn/force-warn-group.stderr +++ b/src/test/ui/lint/force-warn/force-warn-group.stderr @@ -4,8 +4,8 @@ warning: trait objects without an explicit `dyn` are deprecated LL | pub fn function(_x: Box) {} | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait` | - = note: warning forced by `force-warns` commandline option - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = 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 issue #80165 warning: 1 warning emitted diff --git a/src/test/ui/lint/future-incompat-test.rs b/src/test/ui/lint/future-incompat-test.rs new file mode 100644 index 0000000000..ce8c118dab --- /dev/null +++ b/src/test/ui/lint/future-incompat-test.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zfuture-incompat-test -Zemit-future-incompat-report +// check-pass + +// The `-Zfuture-incompat-test flag causes any normal warning to be included +// in the future-incompatible report. The stderr output here should mention +// the future incompatible report (as extracted by compiletest). + +fn main() { + let x = 1; +} diff --git a/src/test/ui/lint/future-incompat-test.stderr b/src/test/ui/lint/future-incompat-test.stderr new file mode 100644 index 0000000000..52674a8438 --- /dev/null +++ b/src/test/ui/lint/future-incompat-test.stderr @@ -0,0 +1,9 @@ +Future incompatibility report: Future breakage diagnostic: +warning: unused variable: `x` + --> $DIR/future-incompat-test.rs:9:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-A unused-variables` implied by `-A unused` + diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed index a1b738e33f..bee5d4ae4b 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed @@ -8,14 +8,14 @@ fn main() { match despondency { 1..=2 => {} //~^ WARN `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition _ => {} } match &despondency { &(1..=2) => {} //~^ WARN `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition _ => {} } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs index d3ebbf38e1..d98c10c26c 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs @@ -8,14 +8,14 @@ fn main() { match despondency { 1...2 => {} //~^ WARN `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition _ => {} } match &despondency { &1...2 => {} //~^ WARN `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition _ => {} } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr index ba4ae208e3..efa684a24e 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 warning: `...` range patterns are deprecated @@ -18,7 +18,7 @@ warning: `...` range patterns are deprecated LL | &1...2 => {} | ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 warning: 2 warnings emitted diff --git a/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs b/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs deleted file mode 100644 index 4d98f0ad62..0000000000 --- a/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs +++ /dev/null @@ -1,10 +0,0 @@ -// compile-flags: -D warnings --cap-lints allow -// check-pass - -// Regression test for issue #78660 -// Tests that we don't ICE when a future-incompat-report lint has -// has a command-line source, but is capped to allow - -fn main() { - ["hi"].into_iter(); -} diff --git a/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr b/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr deleted file mode 100644 index 79958ba90d..0000000000 --- a/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr +++ /dev/null @@ -1,11 +0,0 @@ -Future incompatibility report: Future breakage date: None, diagnostic: -warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. - --> $DIR/issue-78660-cap-lints-future-compat.rs:9:12 - | -LL | ["hi"].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` - | - = note: `-D array-into-iter` 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 #66145 - diff --git a/src/test/ui/lint/issue-83477.rs b/src/test/ui/lint/issue-83477.rs index ab62f0c8b8..4262a28799 100644 --- a/src/test/ui/lint/issue-83477.rs +++ b/src/test/ui/lint/issue-83477.rs @@ -12,6 +12,5 @@ //~| SUGGESTION rustc::default_hash_types fn main() { let _ = std::collections::HashMap::::new(); - //~^ WARN Prefer FxHashMap over HashMap, it has better performance - //~| HELP use + //~^ WARN prefer `FxHashMap` over `HashMap`, it has better performance } diff --git a/src/test/ui/lint/issue-83477.stderr b/src/test/ui/lint/issue-83477.stderr index 028890f362..e619bcfe23 100644 --- a/src/test/ui/lint/issue-83477.stderr +++ b/src/test/ui/lint/issue-83477.stderr @@ -12,11 +12,11 @@ warning: unknown lint: `rustc::foo::default_hash_types` LL | #[allow(rustc::foo::default_hash_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` -warning: Prefer FxHashMap over HashMap, it has better performance - --> $DIR/issue-83477.rs:14:31 +warning: prefer `FxHashMap` over `HashMap`, it has better performance + --> $DIR/issue-83477.rs:14:13 | LL | let _ = std::collections::HashMap::::new(); - | ^^^^^^^ help: use: `FxHashMap` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/issue-83477.rs:3:9 diff --git a/src/test/ui/lint/issue-86600-lint-twice.rs b/src/test/ui/lint/issue-86600-lint-twice.rs new file mode 100644 index 0000000000..0e8a837d98 --- /dev/null +++ b/src/test/ui/lint/issue-86600-lint-twice.rs @@ -0,0 +1,15 @@ +// Regression test for #86600, where an instance of the +// `illegal_floating_point_literal_pattern` lint was issued twice. + +// check-pass + +fn main() { + let x = 42.0; + + match x { + 5.0 => {} + //~^ WARNING: floating-point types cannot be used in patterns + //~| WARNING: this was previously accepted by the compiler + _ => {} + } +} diff --git a/src/test/ui/lint/issue-86600-lint-twice.stderr b/src/test/ui/lint/issue-86600-lint-twice.stderr new file mode 100644 index 0000000000..8da3fb5a83 --- /dev/null +++ b/src/test/ui/lint/issue-86600-lint-twice.stderr @@ -0,0 +1,12 @@ +warning: floating-point types cannot be used in patterns + --> $DIR/issue-86600-lint-twice.rs:10:9 + | +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 + +warning: 1 warning emitted + diff --git a/src/test/ui/lint/issue-87274-paren-parent.rs b/src/test/ui/lint/issue-87274-paren-parent.rs new file mode 100644 index 0000000000..0141c5a252 --- /dev/null +++ b/src/test/ui/lint/issue-87274-paren-parent.rs @@ -0,0 +1,9 @@ +// check-pass +// Tests that we properly lint at 'paren' expressions + +fn foo() -> Result<(), String> { + (try!(Ok::(1))); //~ WARN use of deprecated macro `try` + Ok(()) +} + +fn main() {} diff --git a/src/test/ui/lint/issue-87274-paren-parent.stderr b/src/test/ui/lint/issue-87274-paren-parent.stderr new file mode 100644 index 0000000000..f06024298b --- /dev/null +++ b/src/test/ui/lint/issue-87274-paren-parent.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated macro `try`: use the `?` operator instead + --> $DIR/issue-87274-paren-parent.rs:5:6 + | +LL | (try!(Ok::(1))); + | ^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + 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 6efd03f14a..3355bb4e4f 100644 --- a/src/test/ui/lint/lint-pre-expansion-extern-module.stderr +++ b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr @@ -5,7 +5,7 @@ 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 was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 warning: 1 warning emitted diff --git a/src/test/ui/lint/lint-stability-deprecated.stderr b/src/test/ui/lint/lint-stability-deprecated.stderr index 94fc1a7b46..4b082fcd35 100644 --- a/src/test/ui/lint/lint-stability-deprecated.stderr +++ b/src/test/ui/lint/lint-stability-deprecated.stderr @@ -11,16 +11,16 @@ LL | #![warn(deprecated)] | ^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:29:9 + --> $DIR/lint-stability-deprecated.rs:29:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:31:9 + --> $DIR/lint-stability-deprecated.rs:31:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:33:9 @@ -29,16 +29,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:38:9 + --> $DIR/lint-stability-deprecated.rs:38:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:40:9 + --> $DIR/lint-stability-deprecated.rs:40:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:42:9 @@ -47,16 +47,16 @@ LL | deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:47:9 + --> $DIR/lint-stability-deprecated.rs:47:16 | LL | ... Trait::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:49:9 + --> $DIR/lint-stability-deprecated.rs:49:25 | LL | ... ::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text --> $DIR/lint-stability-deprecated.rs:51:9 @@ -65,16 +65,16 @@ LL | deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:56:9 + --> $DIR/lint-stability-deprecated.rs:56:16 | LL | ... Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:58:9 + --> $DIR/lint-stability-deprecated.rs:58:25 | LL | ... ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text --> $DIR/lint-stability-deprecated.rs:108:17 @@ -101,16 +101,16 @@ LL | let _ = DeprecatedUnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated variant `lint_stability::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:123:17 + --> $DIR/lint-stability-deprecated.rs:123:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ warning: use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`: text - --> $DIR/lint-stability-deprecated.rs:124:17 + --> $DIR/lint-stability-deprecated.rs:124:23 | LL | let _ = Enum::DeprecatedUnstableVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:128:17 @@ -143,52 +143,52 @@ LL | macro_test_arg!(macro_test_arg!(deprecated_text())); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:145:9 + --> $DIR/lint-stability-deprecated.rs:145:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:147:9 + --> $DIR/lint-stability-deprecated.rs:147:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:149:9 + --> $DIR/lint-stability-deprecated.rs:149:16 | LL | ... Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:151:9 + --> $DIR/lint-stability-deprecated.rs:151:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:153:9 + --> $DIR/lint-stability-deprecated.rs:153:16 | LL | ... Trait::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:155:9 + --> $DIR/lint-stability-deprecated.rs:155:25 | LL | ... ::trait_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:157:9 + --> $DIR/lint-stability-deprecated.rs:157:16 | LL | ... Trait::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:159:9 + --> $DIR/lint-stability-deprecated.rs:159:25 | LL | ... ::trait_deprecated_unstable_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text --> $DIR/lint-stability-deprecated.rs:187:10 @@ -203,10 +203,10 @@ LL | trait LocalTrait2 : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:208:9 + --> $DIR/lint-stability-deprecated.rs:208:23 | LL | unstable_mod::deprecated(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text --> $DIR/lint-stability-deprecated.rs:330:9 @@ -215,16 +215,16 @@ LL | deprecated(); | ^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:335:9 + --> $DIR/lint-stability-deprecated.rs:335:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:337:9 + --> $DIR/lint-stability-deprecated.rs:337:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:339:9 @@ -233,16 +233,16 @@ LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:344:9 + --> $DIR/lint-stability-deprecated.rs:344:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:346:9 + --> $DIR/lint-stability-deprecated.rs:346:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `this_crate::DeprecatedStruct`: text --> $DIR/lint-stability-deprecated.rs:384:17 @@ -257,10 +257,10 @@ LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:395:17 + --> $DIR/lint-stability-deprecated.rs:395:23 | LL | let _ = Enum::DeprecatedVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:399:17 @@ -269,28 +269,28 @@ LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:406:9 + --> $DIR/lint-stability-deprecated.rs:406:16 | LL | Trait::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:408:9 + --> $DIR/lint-stability-deprecated.rs:408:25 | LL | ::trait_deprecated(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:410:9 + --> $DIR/lint-stability-deprecated.rs:410:16 | LL | Trait::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:412:9 + --> $DIR/lint-stability-deprecated.rs:412:25 | LL | ... ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text --> $DIR/lint-stability-deprecated.rs:439:9 diff --git a/src/test/ui/lint/lint-stability3.stderr b/src/test/ui/lint/lint-stability3.stderr index 56d4ffc472..3bbb60dd35 100644 --- a/src/test/ui/lint/lint-stability3.stderr +++ b/src/test/ui/lint/lint-stability3.stderr @@ -1,15 +1,14 @@ error: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability3.rs:13:5 + --> $DIR/lint-stability3.rs:13:28 | LL | macro_test_arg_nested!(deprecated_text); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/lint-stability3.rs:4:9 | LL | #![deny(deprecated)] | ^^^^^^^^^^ - = note: this error originates in the macro `macro_test_arg_nested` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/lint/lint-unknown-lint.rs b/src/test/ui/lint/lint-unknown-lint.rs index c36a8b2a4b..2d842d5142 100644 --- a/src/test/ui/lint/lint-unknown-lint.rs +++ b/src/test/ui/lint/lint-unknown-lint.rs @@ -6,4 +6,8 @@ //~| HELP did you mean //~| SUGGESTION dead_code +#![deny(rust_2018_idiots)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION rust_2018_idioms + fn main() {} diff --git a/src/test/ui/lint/lint-unknown-lint.stderr b/src/test/ui/lint/lint-unknown-lint.stderr index 3a102769e8..0cb6b49578 100644 --- a/src/test/ui/lint/lint-unknown-lint.stderr +++ b/src/test/ui/lint/lint-unknown-lint.stderr @@ -16,5 +16,11 @@ error: unknown lint: `dead_cod` LL | #![deny(dead_cod)] | ^^^^^^^^ help: did you mean: `dead_code` -error: aborting due to 2 previous errors +error: unknown lint: `rust_2018_idiots` + --> $DIR/lint-unknown-lint.rs:9:9 + | +LL | #![deny(rust_2018_idiots)] + | ^^^^^^^^^^^^^^^^ help: did you mean: `rust_2018_idioms` + +error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/missing-doc-private-macro.rs b/src/test/ui/lint/missing-doc-private-macro.rs new file mode 100644 index 0000000000..8d1d5c5688 --- /dev/null +++ b/src/test/ui/lint/missing-doc-private-macro.rs @@ -0,0 +1,43 @@ +// Checks that undocumented private macros will not generate `missing_docs` +// lints, but public ones will. +// +// This is a regression test for issue #57569 +#![deny(missing_docs)] +#![feature(decl_macro)] +//! Empty documentation. + +macro new_style_private_macro { + () => () +} + +pub(crate) macro new_style_crate_macro { + () => () +} + +macro_rules! old_style_private_macro { + () => () +} + +mod submodule { + pub macro new_style_macro_in_private_module { + () => () + } + + macro_rules! old_style_mod_private_macro { + () => () + } + + #[macro_export] + macro_rules! exported_to_top_level { + //~^ ERROR missing documentation for macro + () => () + } +} + +pub macro top_level_pub_macro { + //~^ ERROR missing documentation for macro + () => () +} + +/// Empty documentation. +pub fn main() {} diff --git a/src/test/ui/lint/missing-doc-private-macro.stderr b/src/test/ui/lint/missing-doc-private-macro.stderr new file mode 100644 index 0000000000..a5d39faf40 --- /dev/null +++ b/src/test/ui/lint/missing-doc-private-macro.stderr @@ -0,0 +1,20 @@ +error: missing documentation for macro + --> $DIR/missing-doc-private-macro.rs:31:5 + | +LL | macro_rules! exported_to_top_level { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/missing-doc-private-macro.rs:5:9 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for macro + --> $DIR/missing-doc-private-macro.rs:37:1 + | +LL | pub macro top_level_pub_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs index 0bbd7dc6c8..fff380934e 100644 --- a/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs +++ b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs @@ -1,14 +1,17 @@ // check-pass // edition:2018 +#![feature(stmt_expr_attributes)] #![warn(semicolon_in_expressions_from_macros)] #[allow(dead_code)] macro_rules! foo { ($val:ident) => { - true; //~ WARN trailing - //~| WARN this was previously - //~| WARN trailing - //~| WARN this was previously + true; //~ WARN trailing semicolon in macro + //~| WARN this was previously accepted + //~| WARN trailing semicolon in macro + //~| WARN this was previously accepted + //~| WARN trailing semicolon in macro + //~| WARN this was previously accepted } } @@ -18,17 +21,14 @@ async fn bar() { } fn main() { - // This `allow` doesn't work #[allow(semicolon_in_expressions_from_macros)] let _ = { foo!(first) }; - // This 'allow' doesn't work either #[allow(semicolon_in_expressions_from_macros)] let _ = foo!(second); - // But this 'allow' does #[allow(semicolon_in_expressions_from_macros)] fn inner() { let _ = foo!(third); @@ -38,4 +38,14 @@ fn main() { async { let _ = foo!(fourth); }; + + let _ = { + foo!(warn_in_block) + }; + + let _ = foo!(warn_in_expr); + + // This `#[allow]` does not work, since the attribute gets dropped + // when we expand the macro + let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); } 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 111ebea61d..c00c3d77dc 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 @@ -1,14 +1,14 @@ warning: trailing semicolon in macro used in expression position - --> $DIR/semicolon-in-expressions-from-macros.rs:8:13 + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | LL | true; | ^ ... -LL | foo!(first) - | ----------- in this macro invocation +LL | foo!(warn_in_block) + | ------------------- in this macro invocation | note: the lint level is defined here - --> $DIR/semicolon-in-expressions-from-macros.rs:3:9 + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 | LL | #![warn(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +17,30 @@ LL | #![warn(semicolon_in_expressions_from_macros)] = 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 - --> $DIR/semicolon-in-expressions-from-macros.rs:8:13 + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | LL | true; | ^ ... -LL | let _ = foo!(second); - | ------------ in this macro invocation +LL | let _ = foo!(warn_in_expr); + | ------------------ 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 = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 2 warnings emitted +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + | ------------------------- 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 + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 3 warnings emitted diff --git a/src/test/ui/lint/unused-borrows.rs b/src/test/ui/lint/unused-borrows.rs new file mode 100644 index 0000000000..4518522ae0 --- /dev/null +++ b/src/test/ui/lint/unused-borrows.rs @@ -0,0 +1,33 @@ +#![deny(unused_must_use)] + +fn foo(_: i32) -> bool { todo!() } + +fn bar() -> &'static i32 { + &42; + //~^ unused + + &mut foo(42); + //~^ unused + + &&42; + //~^ unused + + &&mut 42; + //~^ unused + + &mut &42; + //~^ unused + + let _result = foo(4) + && foo(2); // Misplaced semi-colon (perhaps due to reordering of lines) + && foo(42); + //~^ unused + + let _ = &42; // ok + + &42 // ok +} + +fn main() { + let _ = bar(); +} diff --git a/src/test/ui/lint/unused-borrows.stderr b/src/test/ui/lint/unused-borrows.stderr new file mode 100644 index 0000000000..24899fe992 --- /dev/null +++ b/src/test/ui/lint/unused-borrows.stderr @@ -0,0 +1,44 @@ +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:6:5 + | +LL | &42; + | ^^^ + | +note: the lint level is defined here + --> $DIR/unused-borrows.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:9:5 + | +LL | &mut foo(42); + | ^^^^^^^^^^^^ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:12:5 + | +LL | &&42; + | ^^^^ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:15:5 + | +LL | &&mut 42; + | ^^^^^^^^ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:18:5 + | +LL | &mut &42; + | ^^^^^^^^ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:23:5 + | +LL | && foo(42); + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr index 713b79bae3..e4de04ef3c 100644 --- a/src/test/ui/lto-duplicate-symbols.stderr +++ b/src/test/ui/lto-duplicate-symbols.stderr @@ -1,6 +1,6 @@ warning: Linking globals named 'foo': symbol multiply defined! -error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.3a1fbbbh-cgu.0.rcgu.o": +error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o": error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/macros/assert-macro-owned.rs b/src/test/ui/macros/assert-macro-owned.rs index 2846f2a1f8..753675872b 100644 --- a/src/test/ui/macros/assert-macro-owned.rs +++ b/src/test/ui/macros/assert-macro-owned.rs @@ -2,7 +2,7 @@ // error-pattern:panicked at 'test-assert-owned' // ignore-emscripten no processes -#![allow(non_fmt_panic)] +#![allow(non_fmt_panics)] fn main() { assert!(false, "test-assert-owned".to_string()); diff --git a/src/test/ui/macros/auxiliary/or-pattern.rs b/src/test/ui/macros/auxiliary/or-pattern.rs new file mode 100644 index 0000000000..a319c405eb --- /dev/null +++ b/src/test/ui/macros/auxiliary/or-pattern.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +#[macro_export] +macro_rules! a { + ($x:pat|) => (); +} diff --git a/src/test/ui/issues/issue-52169.rs b/src/test/ui/macros/issue-52169.rs similarity index 100% rename from src/test/ui/issues/issue-52169.rs rename to src/test/ui/macros/issue-52169.rs diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs new file mode 100644 index 0000000000..9139775c80 --- /dev/null +++ b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs @@ -0,0 +1,16 @@ +// Regression test for #84632: Recursion limit is ignored +// for builtin macros that eagerly expands. + +#![recursion_limit = "15"] +macro_rules! a { + () => (""); + (A) => (concat!("", a!())); + (A, $($A:ident),*) => (concat!("", a!($($A),*))) + //~^ ERROR recursion limit reached + //~| HELP consider adding +} + +fn main() { + a!(A, A, A, A, A); + a!(A, A, A, A, A, A, A, A, A, A, A); +} diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr new file mode 100644 index 0000000000..e6067e3334 --- /dev/null +++ b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr @@ -0,0 +1,14 @@ +error: recursion limit reached while expanding `concat!` + --> $DIR/issue-84632-eager-expansion-recursion-limit.rs:8:28 + | +LL | (A, $($A:ident),*) => (concat!("", a!($($A),*))) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | a!(A, A, A, A, A, A, A, A, A, A, A); + | ------------------------------------ in this macro invocation + | + = help: consider adding a `#![recursion_limit="30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`) + = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs index fd2c590ae5..780e158fe0 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -14,11 +14,12 @@ // revisions: std core // ignore-wasm32-bare compiled with panic=abort by default - #![cfg_attr(core, no_std)] -#[cfg(std)] use std::fmt; -#[cfg(core)] use core::fmt; +#[cfg(core)] +use core::fmt; +#[cfg(std)] +use std::fmt; // an easy mistake in the implementation of 'assert!' // would cause this to say "explicit panic" @@ -57,7 +58,7 @@ fn writeln_1arg() { // // (Example: Issue #48042) #[test] -#[allow(non_fmt_panic)] +#[allow(non_fmt_panics)] fn to_format_or_not_to_format() { // ("{}" is the easiest string to test because if this gets // sent to format_args!, it'll simply fail to compile. @@ -80,13 +81,17 @@ fn to_format_or_not_to_format() { // format!("{}",); // see check-fail // format_args!("{}",); // see check-fail - if falsum() { panic!("{}",); } + if falsum() { + panic!("{}",); + } // print!("{}",); // see check-fail // println!("{}",); // see check-fail // unimplemented!("{}",); // see check-fail - if falsum() { unreachable!("{}",); } + if falsum() { + unreachable!("{}",); + } // write!(&mut stdout, "{}",); // see check-fail // writeln!(&mut stdout, "{}",); // see check-fail diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.fixed b/src/test/ui/macros/macro-or-patterns-back-compat.fixed index f829129d51..b0d56e9bb1 100644 --- a/src/test/ui/macros/macro-or-patterns-back-compat.fixed +++ b/src/test/ui/macros/macro-or-patterns-back-compat.fixed @@ -1,14 +1,28 @@ // run-rustfix +// aux-build:or-pattern.rs -#![deny(or_patterns_back_compat)] +#![deny(rust_2021_incompatible_or_patterns)] #![allow(unused_macros)] -macro_rules! foo { ($x:pat_param | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro -macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + +#[macro_use] +extern crate or_pattern; + +macro_rules! foo { ($x:pat_param | $y:pat) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition +macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition + macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok -macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition macro_rules! match_any { - ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => { + //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + //~| WARN this is accepted in the current edition match $expr { $( $( $pat => $expr_arm, )+ @@ -21,4 +35,5 @@ fn main() { let result: Result = Err(42); let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); assert_eq!(int, 42); + a!(1|); } diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.rs b/src/test/ui/macros/macro-or-patterns-back-compat.rs index 1cdaa1cd63..9e24b5106b 100644 --- a/src/test/ui/macros/macro-or-patterns-back-compat.rs +++ b/src/test/ui/macros/macro-or-patterns-back-compat.rs @@ -1,14 +1,28 @@ // run-rustfix +// aux-build:or-pattern.rs -#![deny(or_patterns_back_compat)] +#![deny(rust_2021_incompatible_or_patterns)] #![allow(unused_macros)] -macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro -macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + +#[macro_use] +extern crate or_pattern; + +macro_rules! foo { ($x:pat | $y:pat) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition + macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok -macro_rules! ogg { ($x:pat | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +macro_rules! ogg { ($x:pat | $y:pat_param) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition macro_rules! match_any { - ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + //~| WARN this is accepted in the current edition match $expr { $( $( $pat => $expr_arm, )+ @@ -21,4 +35,5 @@ fn main() { let result: Result = Err(42); let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); assert_eq!(int, 42); + a!(1|); } 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 01d220dd0b..eb6204fa02 100644 --- a/src/test/ui/macros/macro-or-patterns-back-compat.stderr +++ b/src/test/ui/macros/macro-or-patterns-back-compat.stderr @@ -1,32 +1,43 @@ error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro - --> $DIR/macro-or-patterns-back-compat.rs:5:21 + --> $DIR/macro-or-patterns-back-compat.rs:10:21 | LL | macro_rules! foo { ($x:pat | $y:pat) => {} } | ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param` | note: the lint level is defined here - --> $DIR/macro-or-patterns-back-compat.rs:3:9 + --> $DIR/macro-or-patterns-back-compat.rs:4:9 | -LL | #![deny(or_patterns_back_compat)] - | ^^^^^^^^^^^^^^^^^^^^^^^ +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 issue #84869 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro - --> $DIR/macro-or-patterns-back-compat.rs:6:23 + --> $DIR/macro-or-patterns-back-compat.rs:13:23 | LL | macro_rules! bar { ($($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 issue #84869 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro - --> $DIR/macro-or-patterns-back-compat.rs:9:21 + --> $DIR/macro-or-patterns-back-compat.rs:19:21 | LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} } | ^^^^^^ 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 issue #84869 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro - --> $DIR/macro-or-patterns-back-compat.rs:11:26 + --> $DIR/macro-or-patterns-back-compat.rs:23:26 | LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { | ^^^^^^^^ help: use pat_param to preserve semantics: `$pat: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 issue #84869 error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/trace_faulty_macros.rs b/src/test/ui/macros/trace_faulty_macros.rs index 5a8e2f50ce..b2fdd2e196 100644 --- a/src/test/ui/macros/trace_faulty_macros.rs +++ b/src/test/ui/macros/trace_faulty_macros.rs @@ -39,5 +39,5 @@ fn main() { #[my_macro] fn use_bang_macro_as_attr() {} -#[derive(Debug)] //~ ERROR `derive` may only be applied to structs +#[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s fn use_derive_macro_as_attr() {} diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index 96e7d61398..38affde5f6 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -60,11 +60,13 @@ LL | let a = pat_macro!(); | = note: this error originates in the macro `pat_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/trace_faulty_macros.rs:42:1 | LL | #[derive(Debug)] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ not applicable here +LL | fn use_derive_macro_as_attr() {} + | -------------------------------- not a `struct`, `enum` or `union` note: trace_macro --> $DIR/trace_faulty_macros.rs:36:13 diff --git a/src/test/ui/mir/issue-75053.full_tait.stderr b/src/test/ui/mir/issue-75053.full_tait.stderr index aff19094b7..543d15fadc 100644 --- a/src/test/ui/mir/issue-75053.full_tait.stderr +++ b/src/test/ui/mir/issue-75053.full_tait.stderr @@ -7,15 +7,11 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-75053.rs:52:15 +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-75053.rs:49:1 | -LL | let _pos: Phantom1> = Scope::new().my_index(); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable +LL | fn main() { + | ^^^^^^^^^ error: aborting due to previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mir/issue-75053.in_bindings.stderr b/src/test/ui/mir/issue-75053.in_bindings.stderr index a43fabc8f5..d75996bf0b 100644 --- a/src/test/ui/mir/issue-75053.in_bindings.stderr +++ b/src/test/ui/mir/issue-75053.in_bindings.stderr @@ -1,24 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes +error[E0557]: feature has been removed --> $DIR/issue-75053.rs:7:34 | LL | #![cfg_attr(in_bindings, feature(impl_trait_in_bindings))] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ feature has been removed | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information + = note: removed due to being incomplete and unstable -error[E0282]: type annotations needed - --> $DIR/issue-75053.rs:52:38 - | -LL | type O; - | ------- `>::O` defined here -... -LL | let _pos: Phantom1> = Scope::new().my_index(); - | ^^^^^^^^^^------------- - | | - | this method call resolves to `>::O` - | cannot infer type for type parameter `T` - -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0557`. diff --git a/src/test/ui/mir/issue-75053.min_tait.stderr b/src/test/ui/mir/issue-75053.min_tait.stderr index 7ce91e851a..c533275c99 100644 --- a/src/test/ui/mir/issue-75053.min_tait.stderr +++ b/src/test/ui/mir/issue-75053.min_tait.stderr @@ -1,12 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-75053.rs:52:15 +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-75053.rs:49:1 | -LL | let _pos: Phantom1> = Scope::new().my_index(); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable +LL | fn main() { + | ^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mir/issue-75053.rs b/src/test/ui/mir/issue-75053.rs index 89ae3ca300..b71f84dd9c 100644 --- a/src/test/ui/mir/issue-75053.rs +++ b/src/test/ui/mir/issue-75053.rs @@ -1,11 +1,9 @@ // compile-flags: -Z mir-opt-level=3 -// revisions: min_tait full_tait in_bindings +// revisions: min_tait full_tait #![feature(min_type_alias_impl_trait, rustc_attrs)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -#![cfg_attr(in_bindings, feature(impl_trait_in_bindings))] -//[in_bindings]~^ WARN incomplete use std::marker::PhantomData; @@ -49,7 +47,6 @@ impl>>, U> MyIndex> for Scope { #[rustc_error] fn main() { + //~^ ERROR let _pos: Phantom1> = Scope::new().my_index(); - //[min_tait,full_tait]~^ ERROR not permitted here - //[in_bindings]~^^ ERROR type annotations needed } diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs index 4d404d015e..0086d2ec18 100644 --- a/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs +++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs @@ -5,6 +5,6 @@ fn main() {} fn foo(_: Bar, ...) -> impl {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR cannot find type `Bar` in this scope //~| ERROR at least one trait must be specified diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr index eb17268489..4eb3adc8b4 100644 --- a/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr +++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -1,4 +1,4 @@ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16 | LL | fn foo(_: Bar, ...) -> impl {} diff --git a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs index 0385a120ce..86fd37e781 100644 --- a/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs +++ b/src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs @@ -1,6 +1,6 @@ // Tests correct kind-checking of the reason stack closures without the :Copy // bound must be noncopyable. For details see -// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/ +// https://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/ struct R<'a> { // This struct is needed to create the diff --git a/src/test/ui/mut/mutable-class-fields-2.stderr b/src/test/ui/mut/mutable-class-fields-2.stderr index 15323ce9a9..5a4e31947f 100644 --- a/src/test/ui/mut/mutable-class-fields-2.stderr +++ b/src/test/ui/mut/mutable-class-fields-2.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `self.how_hungry` which is behind a `&` reference +error[E0594]: cannot assign to `self.how_hungry`, which is behind a `&` reference --> $DIR/mutable-class-fields-2.rs:9:5 | LL | pub fn eat(&self) { diff --git a/src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs similarity index 100% rename from src/test/ui/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs rename to src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs diff --git a/src/test/ui/issues/issue-45157.rs b/src/test/ui/nll/issue-45157.rs similarity index 100% rename from src/test/ui/issues/issue-45157.rs rename to src/test/ui/nll/issue-45157.rs diff --git a/src/test/ui/issues/issue-45157.stderr b/src/test/ui/nll/issue-45157.stderr similarity index 100% rename from src/test/ui/issues/issue-45157.stderr rename to src/test/ui/nll/issue-45157.stderr diff --git a/src/test/ui/nll/issue-47388.stderr b/src/test/ui/nll/issue-47388.stderr index 8d48b00f8d..a4ee778175 100644 --- a/src/test/ui/nll/issue-47388.stderr +++ b/src/test/ui/nll/issue-47388.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference +error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference --> $DIR/issue-47388.rs:8:5 | LL | let fancy_ref = &(&mut fancy); diff --git a/src/test/ui/nll/issue-50461-used-mut-from-moves.rs b/src/test/ui/nll/issue-50461-used-mut-from-moves.rs index 69d7cdd83a..2458b171e6 100644 --- a/src/test/ui/nll/issue-50461-used-mut-from-moves.rs +++ b/src/test/ui/nll/issue-50461-used-mut-from-moves.rs @@ -1,6 +1,7 @@ // run-pass #![deny(unused_mut)] +#![allow(dead_code)] struct Foo { pub value: i32 diff --git a/src/test/ui/nll/issue-51244.rs b/src/test/ui/nll/issue-51244.rs index 743415d58a..c4cbee6754 100644 --- a/src/test/ui/nll/issue-51244.rs +++ b/src/test/ui/nll/issue-51244.rs @@ -1,5 +1,5 @@ fn main() { let ref my_ref @ _ = 0; *my_ref = 0; - //~^ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594] + //~^ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594] } diff --git a/src/test/ui/nll/issue-51244.stderr b/src/test/ui/nll/issue-51244.stderr index c91083955b..19f0223a35 100644 --- a/src/test/ui/nll/issue-51244.stderr +++ b/src/test/ui/nll/issue-51244.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference +error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference --> $DIR/issue-51244.rs:3:5 | LL | let ref my_ref @ _ = 0; diff --git a/src/test/ui/nll/issue-57989.rs b/src/test/ui/nll/issue-57989.rs index c410f0b0bf..8f3dec454d 100644 --- a/src/test/ui/nll/issue-57989.rs +++ b/src/test/ui/nll/issue-57989.rs @@ -2,7 +2,7 @@ fn f(x: &i32) { let g = &x; - *x = 0; //~ ERROR cannot assign to `*x` which is behind a `&` reference + *x = 0; //~ ERROR cannot assign to `*x`, which is behind a `&` reference //~| ERROR cannot assign to `*x` because it is borrowed g; } diff --git a/src/test/ui/nll/issue-57989.stderr b/src/test/ui/nll/issue-57989.stderr index 4c41610503..e85e63e52e 100644 --- a/src/test/ui/nll/issue-57989.stderr +++ b/src/test/ui/nll/issue-57989.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*x` which is behind a `&` reference +error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/issue-57989.rs:5:5 | LL | fn f(x: &i32) { diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr index d003acd879..8c7c8918f3 100644 --- a/src/test/ui/nll/normalization-bounds-error.stderr +++ b/src/test/ui/nll/normalization-bounds-error.stderr @@ -1,8 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements - --> $DIR/normalization-bounds-error.rs:12:1 + --> $DIR/normalization-bounds-error.rs:12:4 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'d` as defined on the function body at 12:14... --> $DIR/normalization-bounds-error.rs:12:14 @@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined on LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^ note: ...so that the types are compatible - --> $DIR/normalization-bounds-error.rs:12:1 + --> $DIR/normalization-bounds-error.rs:12:4 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ = note: expected `Visitor<'d>` found `Visitor<'_>` diff --git a/src/test/ui/non-constant-in-const-path.rs b/src/test/ui/non-constant-in-const-path.rs deleted file mode 100644 index 343bb98aeb..0000000000 --- a/src/test/ui/non-constant-in-const-path.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - let x = 0; - match 1 { - 0 ..= x => {} - //~^ ERROR runtime values cannot be referenced in patterns - }; -} diff --git a/src/test/ui/non-constant-in-const-path.stderr b/src/test/ui/non-constant-in-const-path.stderr deleted file mode 100644 index 5936f76b2e..0000000000 --- a/src/test/ui/non-constant-in-const-path.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: runtime values cannot be referenced in patterns - --> $DIR/non-constant-in-const-path.rs:4:15 - | -LL | 0 ..= x => {} - | ^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr index 3278eb5f02..6aa2eb174e 100644 --- a/src/test/ui/non-fmt-panic.stderr +++ b/src/test/ui/non-fmt-panic.stderr @@ -4,7 +4,7 @@ warning: panic message contains a brace LL | panic!("here's a brace: {"); | ^ | - = note: `#[warn(non_fmt_panic)]` on by default + = note: `#[warn(non_fmt_panics)]` on by default = note: this message is not used as a format string, but will be in Rust 2021 help: add a "{}" format string to use the message literally | @@ -61,7 +61,8 @@ warning: panic message is not a string literal LL | assert!(false, S); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | assert!(false, "{}", S); @@ -85,7 +86,8 @@ warning: panic message is not a string literal LL | panic!(C); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | panic!("{}", C); @@ -101,7 +103,8 @@ warning: panic message is not a string literal LL | panic!(S); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | panic!("{}", S); @@ -117,7 +120,8 @@ warning: panic message is not a string literal LL | std::panic!(123); | ^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | std::panic!("{}", 123); @@ -133,7 +137,8 @@ warning: panic message is not a string literal LL | core::panic!(&*"abc"); | ^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | core::panic!("{}", &*"abc"); @@ -181,7 +186,8 @@ warning: panic message is not a string literal LL | fancy_panic::fancy_panic!(S); | ^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see warning: panic message is not a string literal --> $DIR/non-fmt-panic.rs:36:12 @@ -189,7 +195,8 @@ warning: panic message is not a string literal LL | panic!(a!()); | ^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | panic!("{}", a!()); @@ -205,7 +212,8 @@ warning: panic message is not a string literal LL | panic!(format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see = note: the panic!() macro supports formatting, so there's no need for the format!() macro here help: remove the `format!(..)` macro call | @@ -218,7 +226,8 @@ warning: panic message is not a string literal LL | assert!(false, format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see = note: the assert!() macro supports formatting, so there's no need for the format!() macro here help: remove the `format!(..)` macro call | @@ -231,7 +240,8 @@ warning: panic message is not a string literal LL | debug_assert!(false, format!("{}", 1)); | ^^^^^^^^^^^^^^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see = note: the debug_assert!() macro supports formatting, so there's no need for the format!() macro here help: remove the `format!(..)` macro call | @@ -244,7 +254,8 @@ warning: panic message is not a string literal LL | panic![123]; | ^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | panic!["{}", 123]; @@ -260,7 +271,8 @@ warning: panic message is not a string literal LL | panic!{123}; | ^^^ | - = note: this is no longer accepted in Rust 2021 + = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see help: add a "{}" format string to Display the message | LL | panic!{"{}", 123}; diff --git a/src/test/ui/nullable-pointer-iotareduction.rs b/src/test/ui/nullable-pointer-iotareduction.rs index 4c6964f294..568c3e144b 100644 --- a/src/test/ui/nullable-pointer-iotareduction.rs +++ b/src/test/ui/nullable-pointer-iotareduction.rs @@ -4,7 +4,7 @@ // Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, // which "says that a destructor applied to an object built from a constructor -// behaves as expected". -- http://coq.inria.fr/doc/Reference-Manual006.html +// behaves as expected". -- https://coq.inria.fr/doc/language/core/conversion.html#iota-reduction // // It's a little more complicated here, because of pointers and regions and // trying to get assert failure messages that at least identify which case diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index f0651c4cde..804b628220 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -1,35 +1,41 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:18 | -LL | fn index(&self, index: Idx) -> &Self::Output; - | --------------------------------------------- required by `Index::index` -... LL | Index::index(&[] as &[i32], 2u32); | ^^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` +note: required by `Index::index` + --> $DIR/multiple-impls.rs:12:5 + | +LL | fn index(&self, index: Idx) -> &Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:36:18 | -LL | fn index(&self, index: Idx) -> &Self::Output; - | --------------------------------------------- required by `Index::index` -... LL | Index::index(&[] as &[i32], Foo(2u32)); | ^^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` +note: required by `Index::index` + --> $DIR/multiple-impls.rs:12:5 + | +LL | fn index(&self, index: Idx) -> &Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:39:18 | -LL | fn index(&self, index: Idx) -> &Self::Output; - | --------------------------------------------- required by `Index::index` -... LL | Index::index(&[] as &[i32], Bar(2u32)); | ^^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` +note: required by `Index::index` + --> $DIR/multiple-impls.rs:12:5 + | +LL | fn index(&self, index: Idx) -> &Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:5 diff --git a/src/test/ui/on-unimplemented/no-debug.stderr b/src/test/ui/on-unimplemented/no-debug.stderr index fe4114aedd..b17c1d4c25 100644 --- a/src/test/ui/on-unimplemented/no-debug.stderr +++ b/src/test/ui/on-unimplemented/no-debug.stderr @@ -5,8 +5,7 @@ LL | println!("{:?} {:?}", Foo, Bar); | ^^^ `Foo` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `Foo` - = note: add `#[derive(Debug)]` or manually implement `Debug` - = note: required by `std::fmt::Debug::fmt` + = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `Bar` doesn't implement `Debug` @@ -16,7 +15,6 @@ LL | println!("{:?} {:?}", Foo, Bar); | ^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `Bar` - = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `Foo` doesn't implement `std::fmt::Display` @@ -27,7 +25,6 @@ LL | println!("{} {}", Foo, Bar); | = help: the trait `std::fmt::Display` is not implemented for `Foo` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = note: required by `std::fmt::Display::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `Bar` doesn't implement `std::fmt::Display` @@ -38,7 +35,6 @@ LL | println!("{} {}", Foo, Bar); | = help: the trait `std::fmt::Display` is not implemented for `Bar` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = note: required by `std::fmt::Display::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index f19fa8a07f..bfd438e5cc 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -1,13 +1,15 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:25 | -LL | fn index(&self, index: Idx) -> &Self::Output; - | --------------------------------------------- required by `Index::index` -... LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | = help: the trait `Index` is not implemented for `[i32]` +note: required by `Index::index` + --> $DIR/on-impl.rs:9:5 + | +LL | fn index(&self, index: Idx) -> &Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:5 diff --git a/src/test/ui/issues/issue-27060-2.rs b/src/test/ui/packed/issue-27060-2.rs similarity index 100% rename from src/test/ui/issues/issue-27060-2.rs rename to src/test/ui/packed/issue-27060-2.rs diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/packed/issue-27060-2.stderr similarity index 100% rename from src/test/ui/issues/issue-27060-2.stderr rename to src/test/ui/packed/issue-27060-2.stderr diff --git a/src/test/ui/issues/issue-27060-rpass.rs b/src/test/ui/packed/issue-27060-rpass.rs similarity index 100% rename from src/test/ui/issues/issue-27060-rpass.rs rename to src/test/ui/packed/issue-27060-rpass.rs diff --git a/src/test/ui/issues/issue-27060.rs b/src/test/ui/packed/issue-27060.rs similarity index 100% rename from src/test/ui/issues/issue-27060.rs rename to src/test/ui/packed/issue-27060.rs diff --git a/src/test/ui/issues/issue-27060.stderr b/src/test/ui/packed/issue-27060.stderr similarity index 100% rename from src/test/ui/issues/issue-27060.stderr rename to src/test/ui/packed/issue-27060.stderr diff --git a/src/test/ui/panic-runtime/incompatible-type.rs b/src/test/ui/panic-runtime/incompatible-type.rs new file mode 100644 index 0000000000..026364a205 --- /dev/null +++ b/src/test/ui/panic-runtime/incompatible-type.rs @@ -0,0 +1,24 @@ +// Check that rust_eh_personality can have a different type signature than the +// one hardcoded in the compiler. Regression test for #70117. Used to fail with: +// +// Assertion `isa(Val) && "cast() argument of incompatible type!"' failed. +// +// build-pass +// compile-flags: --crate-type=lib -Ccodegen-units=1 +#![no_std] +#![panic_runtime] +#![feature(panic_runtime)] +#![feature(rustc_attrs)] + +pub struct DropMe; + +impl Drop for DropMe { + fn drop(&mut self) {} +} + +pub fn test(_: DropMe) { + unreachable!(); +} + +#[rustc_std_internal_symbol] +pub unsafe extern "C" fn rust_eh_personality() {} diff --git a/src/test/ui/panics/explicit-panic-msg.rs b/src/test/ui/panics/explicit-panic-msg.rs index bfcc12cd18..9d80357873 100644 --- a/src/test/ui/panics/explicit-panic-msg.rs +++ b/src/test/ui/panics/explicit-panic-msg.rs @@ -1,6 +1,6 @@ #![allow(unused_assignments)] #![allow(unused_variables)] -#![allow(non_fmt_panic)] +#![allow(non_fmt_panics)] // run-fail // error-pattern:wooooo diff --git a/src/test/ui/panics/panic-macro-any-wrapped.rs b/src/test/ui/panics/panic-macro-any-wrapped.rs index 100ac10c76..663bf6713d 100644 --- a/src/test/ui/panics/panic-macro-any-wrapped.rs +++ b/src/test/ui/panics/panic-macro-any-wrapped.rs @@ -2,7 +2,7 @@ // error-pattern:panicked at 'Box' // ignore-emscripten no processes -#![allow(non_fmt_panic)] +#![allow(non_fmt_panics)] fn main() { panic!(Box::new(612_i64)); diff --git a/src/test/ui/panics/panic-macro-any.rs b/src/test/ui/panics/panic-macro-any.rs index a5ba30220e..08acc6e807 100644 --- a/src/test/ui/panics/panic-macro-any.rs +++ b/src/test/ui/panics/panic-macro-any.rs @@ -3,7 +3,7 @@ // ignore-emscripten no processes #![feature(box_syntax)] -#![allow(non_fmt_panic)] +#![allow(non_fmt_panics)] fn main() { panic!(box 413 as Box); diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index 02816ef279..c217ab9774 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -1,4 +1,5 @@ // run-rustfix +// rustfix-only-machine-applicable #![allow(unused_variables)] #![allow(dead_code)] #![allow(unused_must_use)] diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index 93baa8278f..b04025faae 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -1,4 +1,5 @@ // run-rustfix +// rustfix-only-machine-applicable #![allow(unused_variables)] #![allow(dead_code)] #![allow(unused_must_use)] diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index 09a6d7cbeb..067b7edc77 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -1,5 +1,5 @@ error: expected expression, found `+` - --> $DIR/expr-as-stmt.rs:7:9 + --> $DIR/expr-as-stmt.rs:8:9 | LL | {2} + {2} | --- ^ expected expression @@ -7,7 +7,7 @@ LL | {2} + {2} | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` - --> $DIR/expr-as-stmt.rs:12:9 + --> $DIR/expr-as-stmt.rs:13:9 | LL | {2} + 2 | --- ^ expected expression @@ -15,7 +15,7 @@ LL | {2} + 2 | help: parentheses are required to parse this as an expression: `({2})` error: expected expression, found `+` - --> $DIR/expr-as-stmt.rs:18:12 + --> $DIR/expr-as-stmt.rs:19:12 | LL | { 42 } + foo; | ------ ^ expected expression @@ -23,7 +23,7 @@ LL | { 42 } + foo; | help: parentheses are required to parse this as an expression: `({ 42 })` error: expected expression, found `>` - --> $DIR/expr-as-stmt.rs:31:7 + --> $DIR/expr-as-stmt.rs:32:7 | LL | } > 0 | ^ expected expression @@ -36,7 +36,7 @@ LL | }) > 0 | error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:7:6 + --> $DIR/expr-as-stmt.rs:8:6 | LL | {2} + {2} | ^ expected `()`, found integer @@ -47,7 +47,7 @@ LL | {return 2;} + {2} | ^^^^^^ ^ error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:12:6 + --> $DIR/expr-as-stmt.rs:13:6 | LL | {2} + 2 | ^ expected `()`, found integer @@ -58,7 +58,7 @@ LL | {return 2;} + 2 | ^^^^^^ ^ error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:18:7 + --> $DIR/expr-as-stmt.rs:19:7 | LL | { 42 } + foo; | ^^ expected `()`, found integer @@ -69,7 +69,7 @@ LL | { return 42; } + foo; | ^^^^^^ ^ error[E0308]: mismatched types - --> $DIR/expr-as-stmt.rs:24:7 + --> $DIR/expr-as-stmt.rs:25:7 | LL | { 3 } * 3 | ^ expected `()`, found integer @@ -80,7 +80,7 @@ LL | { return 3; } * 3 | ^^^^^^ ^ error[E0614]: type `{integer}` cannot be dereferenced - --> $DIR/expr-as-stmt.rs:24:11 + --> $DIR/expr-as-stmt.rs:25:11 | LL | { 3 } * 3 | ----- ^^^ diff --git a/src/test/ui/parser/float-literals.rs b/src/test/ui/parser/float-literals.rs new file mode 100644 index 0000000000..1e9319fd27 --- /dev/null +++ b/src/test/ui/parser/float-literals.rs @@ -0,0 +1,9 @@ +// build-pass +// ignore-tidy-linelength +// Regression test for #31109 and #31407. + +pub fn main() { + let _: f64 = 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333; + + let _: f64 = 1234567890123456789012345678901234567890e-340; +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs index 1ccc9497d9..9871cb8fe3 100644 --- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -1,5 +1,4 @@ #![feature(generic_associated_types)] -//~^ WARN the feature `generic_associated_types` is incomplete fn main() {} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr index 818d73c898..4b398d791c 100644 --- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -1,5 +1,5 @@ error: associated type in `impl` without body - --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:8:5 | LL | type Y; | ^^^^^^- @@ -7,7 +7,7 @@ LL | type Y; | help: provide a definition for the type: `= ;` error: associated type in `impl` without body - --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:11:5 | LL | type Z: Ord; | ^^^^^^^^^^^- @@ -15,13 +15,13 @@ LL | type Z: Ord; | help: provide a definition for the type: `= ;` error: bounds on `type`s in `impl`s have no effect - --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:11:13 | LL | type Z: Ord; | ^^^ error: associated type in `impl` without body - --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:15:5 | LL | type W: Ord where Self: Eq; | ^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -29,30 +29,21 @@ LL | type W: Ord where Self: Eq; | help: provide a definition for the type: `= ;` error: bounds on `type`s in `impl`s have no effect - --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:15:13 | LL | type W: Ord where Self: Eq; | ^^^ error: associated type in `impl` without body - --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:19:5 | LL | type W where Self: Eq; | ^^^^^^^^^^^^^^^^^^^^^- | | | help: provide a definition for the type: `= ;` -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #44265 for more information - error[E0658]: inherent associated types are unstable - --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:8:5 | LL | type Y; | ^^^^^^^ @@ -61,7 +52,7 @@ LL | type Y; = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable error[E0658]: inherent associated types are unstable - --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:11:5 | LL | type Z: Ord; | ^^^^^^^^^^^^ @@ -70,7 +61,7 @@ LL | type Z: Ord; = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable error[E0658]: inherent associated types are unstable - --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:15:5 | LL | type W: Ord where Self: Eq; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,7 +70,7 @@ LL | type W: Ord where Self: Eq; = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable error[E0658]: inherent associated types are unstable - --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:19:5 | LL | type W where Self: Eq; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -87,6 +78,6 @@ LL | type W where Self: Eq; = note: see issue #8995 for more information = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-48636.fixed b/src/test/ui/parser/issue-48636.fixed similarity index 100% rename from src/test/ui/issues/issue-48636.fixed rename to src/test/ui/parser/issue-48636.fixed diff --git a/src/test/ui/issues/issue-48636.rs b/src/test/ui/parser/issue-48636.rs similarity index 100% rename from src/test/ui/issues/issue-48636.rs rename to src/test/ui/parser/issue-48636.rs diff --git a/src/test/ui/issues/issue-48636.stderr b/src/test/ui/parser/issue-48636.stderr similarity index 100% rename from src/test/ui/issues/issue-48636.stderr rename to src/test/ui/parser/issue-48636.stderr diff --git a/src/test/ui/issues/issue-54521-1.rs b/src/test/ui/parser/issue-54521-1.rs similarity index 100% rename from src/test/ui/issues/issue-54521-1.rs rename to src/test/ui/parser/issue-54521-1.rs diff --git a/src/test/ui/issues/issue-54521-2.fixed b/src/test/ui/parser/issue-54521-2.fixed similarity index 100% rename from src/test/ui/issues/issue-54521-2.fixed rename to src/test/ui/parser/issue-54521-2.fixed diff --git a/src/test/ui/issues/issue-54521-2.rs b/src/test/ui/parser/issue-54521-2.rs similarity index 100% rename from src/test/ui/issues/issue-54521-2.rs rename to src/test/ui/parser/issue-54521-2.rs diff --git a/src/test/ui/issues/issue-54521-2.stderr b/src/test/ui/parser/issue-54521-2.stderr similarity index 100% rename from src/test/ui/issues/issue-54521-2.stderr rename to src/test/ui/parser/issue-54521-2.stderr diff --git a/src/test/ui/issues/issue-54521.fixed b/src/test/ui/parser/issue-54521-3.fixed similarity index 100% rename from src/test/ui/issues/issue-54521.fixed rename to src/test/ui/parser/issue-54521-3.fixed diff --git a/src/test/ui/issues/issue-54521.rs b/src/test/ui/parser/issue-54521-3.rs similarity index 100% rename from src/test/ui/issues/issue-54521.rs rename to src/test/ui/parser/issue-54521-3.rs diff --git a/src/test/ui/issues/issue-54521.stderr b/src/test/ui/parser/issue-54521-3.stderr similarity index 86% rename from src/test/ui/issues/issue-54521.stderr rename to src/test/ui/parser/issue-54521-3.stderr index ffefbfd034..0f23dd6210 100644 --- a/src/test/ui/issues/issue-54521.stderr +++ b/src/test/ui/parser/issue-54521-3.stderr @@ -1,23 +1,23 @@ error: unmatched angle brackets - --> $DIR/issue-54521.rs:11:60 + --> $DIR/issue-54521-3.rs:11:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::>>>>>(); | ^^^^ help: remove extra angle brackets error: unmatched angle brackets - --> $DIR/issue-54521.rs:14:60 + --> $DIR/issue-54521-3.rs:14:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::>>>>(); | ^^^ help: remove extra angle brackets error: unmatched angle brackets - --> $DIR/issue-54521.rs:17:60 + --> $DIR/issue-54521-3.rs:17:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::>>>(); | ^^ help: remove extra angle brackets error: unmatched angle bracket - --> $DIR/issue-54521.rs:20:60 + --> $DIR/issue-54521-3.rs:20:60 | LL | let _ = vec![1, 2, 3].into_iter().collect::>>(); | ^ help: remove extra angle bracket diff --git a/src/test/ui/parser/issue-68890-2.rs b/src/test/ui/parser/issue-68890-2.rs index 88527cc878..0a6e26acfc 100644 --- a/src/test/ui/parser/issue-68890-2.rs +++ b/src/test/ui/parser/issue-68890-2.rs @@ -4,4 +4,4 @@ type X<'a> = (?'a) +; //~^ ERROR `?` may only modify trait bounds, not lifetime bounds //~| ERROR at least one trait is required for an object type //~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this was previously accepted by the compiler +//~| WARN this is accepted in the current edition diff --git a/src/test/ui/parser/issue-68890-2.stderr b/src/test/ui/parser/issue-68890-2.stderr index 37f38365b0..dce03e1a96 100644 --- a/src/test/ui/parser/issue-68890-2.stderr +++ b/src/test/ui/parser/issue-68890-2.stderr @@ -11,7 +11,7 @@ LL | type X<'a> = (?'a) +; | ^^^^^^^ help: use `dyn`: `dyn (?'a) +` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error[E0224]: at least one trait is required for an object type diff --git a/src/test/ui/parser/issue-73568-lifetime-after-mut.rs b/src/test/ui/parser/issue-73568-lifetime-after-mut.rs index 0733b2d2df..e68ee747cf 100644 --- a/src/test/ui/parser/issue-73568-lifetime-after-mut.rs +++ b/src/test/ui/parser/issue-73568-lifetime-after-mut.rs @@ -14,10 +14,10 @@ mac!('a); fn y<'a>(y: &mut 'a + Send) { //~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a` //~| WARNING trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition //~| ERROR at least one trait is required for an object type let z = y as &mut 'a + Send; //~^ ERROR expected value, found trait `Send` //~| WARNING trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition } diff --git a/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr b/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr index f83b7944b1..c10037d44e 100644 --- a/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr +++ b/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr @@ -34,7 +34,7 @@ LL | fn y<'a>(y: &mut 'a + Send) { | ^^ help: use `dyn`: `dyn 'a` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 warning: trait objects without an explicit `dyn` are deprecated @@ -43,7 +43,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | let z = y as &mut 'a + Send; | ^^ help: use `dyn`: `dyn 'a` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error[E0224]: at least one trait is required for an object type diff --git a/src/test/ui/parser/issue-86895.rs b/src/test/ui/parser/issue-86895.rs new file mode 100644 index 0000000000..4cd0984310 --- /dev/null +++ b/src/test/ui/parser/issue-86895.rs @@ -0,0 +1,3 @@ +const pub () {} +//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe` +pub fn main() {} diff --git a/src/test/ui/parser/issue-86895.stderr b/src/test/ui/parser/issue-86895.stderr new file mode 100644 index 0000000000..575d857c0e --- /dev/null +++ b/src/test/ui/parser/issue-86895.stderr @@ -0,0 +1,8 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-86895.rs:1:7 + | +LL | const pub () {} + | ^^^ expected one of `async`, `extern`, `fn`, or `unsafe` + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issue-87086-colon-path-sep.rs b/src/test/ui/parser/issue-87086-colon-path-sep.rs new file mode 100644 index 0000000000..4ee0b2054f --- /dev/null +++ b/src/test/ui/parser/issue-87086-colon-path-sep.rs @@ -0,0 +1,66 @@ +// Tests that a suggestion is issued if the user wrote a colon instead of +// a path separator in a match arm. + +enum Foo { + Bar, + Baz, +} + +fn f() -> Foo { Foo::Bar } + +fn g1() { + match f() { + Foo:Bar => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + match f() { + Foo::Bar:Baz => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + match f() { + Foo:Bar::Baz => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + match f() { + Foo: Bar::Baz if true => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + if let Bar:Baz = f() { + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + } +} + +fn g1_neg() { + match f() { + ref Foo: Bar::Baz => {} + //~^ ERROR: expected one of + _ => {} + } +} + +fn g2_neg() { + match f() { + mut Foo: Bar::Baz => {} + //~^ ERROR: expected one of + _ => {} + } +} + +fn main() { + let myfoo = Foo::Bar; + match myfoo { + Foo::Bar => {} + Foo:Bar::Baz => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + } +} diff --git a/src/test/ui/parser/issue-87086-colon-path-sep.stderr b/src/test/ui/parser/issue-87086-colon-path-sep.stderr new file mode 100644 index 0000000000..8f93661a62 --- /dev/null +++ b/src/test/ui/parser/issue-87086-colon-path-sep.stderr @@ -0,0 +1,68 @@ +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:13:12 + | +LL | Foo:Bar => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:19:17 + | +LL | Foo::Bar:Baz => {} + | ^ + | | + | expected one of 8 possible tokens + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:25:12 + | +LL | Foo:Bar::Baz => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:31:12 + | +LL | Foo: Bar::Baz if true => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:36:15 + | +LL | if let Bar:Baz = f() { + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `=>`, `@`, `if`, or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:44:16 + | +LL | ref Foo: Bar::Baz => {} + | ^ expected one of `=>`, `@`, `if`, or `|` + +error: expected one of `=>`, `@`, `if`, or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:52:16 + | +LL | mut Foo: Bar::Baz => {} + | ^ expected one of `=>`, `@`, `if`, or `|` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:62:12 + | +LL | Foo:Bar::Baz => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: aborting due to 8 previous errors + diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.rs b/src/test/ui/parser/macro/trait-object-macro-matcher.rs index 0428ea0e2c..663739f235 100644 --- a/src/test/ui/parser/macro/trait-object-macro-matcher.rs +++ b/src/test/ui/parser/macro/trait-object-macro-matcher.rs @@ -12,5 +12,5 @@ fn main() { //~^ ERROR lifetime in trait object type must be followed by `+` //~| ERROR at least one trait is required for an object type //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition } diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr index 8ae5611d89..caca84f695 100644 --- a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr +++ b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr @@ -11,7 +11,7 @@ LL | m!('static); | ^^^^^^^ help: use `dyn`: `dyn 'static` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error[E0224]: at least one trait is required for an object type diff --git a/src/test/ui/parser/parser-unicode-whitespace.rs b/src/test/ui/parser/parser-unicode-whitespace.rs index 2d1fa7dc42..555cd68c3a 100644 --- a/src/test/ui/parser/parser-unicode-whitespace.rs +++ b/src/test/ui/parser/parser-unicode-whitespace.rs @@ -1,7 +1,7 @@ // run-pass // Beware editing: it has numerous whitespace characters which are important. // It contains one ranges from the 'PATTERN_WHITE_SPACE' property outlined in -// http://unicode.org/Public/UNIDATA/PropList.txt +// https://unicode.org/Public/UNIDATA/PropList.txt // // The characters in the first expression of the assertion can be generated // from: "4\u{0C}+\n\t\r7\t*\u{20}2\u{85}/\u{200E}3\u{200F}*\u{2028}2\u{2029}" diff --git a/src/test/ui/parser/range-inclusive-extra-equals.rs b/src/test/ui/parser/range-inclusive-extra-equals.rs new file mode 100644 index 0000000000..d41c0699cf --- /dev/null +++ b/src/test/ui/parser/range-inclusive-extra-equals.rs @@ -0,0 +1,10 @@ +// Makes sure that a helpful message is shown when someone mistypes +// an inclusive range as `..==` rather than `..=`. This is an +// easy mistake, because of the resemblance to`==`. +// See #86395 for a bit of background. + +pub fn main() { + if let 1..==3 = 1 {} //~ERROR unexpected `=` after inclusive range + //~|HELP use `..=` instead + //~|NOTE inclusive ranges end with a single equals sign +} diff --git a/src/test/ui/parser/range-inclusive-extra-equals.stderr b/src/test/ui/parser/range-inclusive-extra-equals.stderr new file mode 100644 index 0000000000..d37b6be4fa --- /dev/null +++ b/src/test/ui/parser/range-inclusive-extra-equals.stderr @@ -0,0 +1,10 @@ +error: unexpected `=` after inclusive range + --> $DIR/range-inclusive-extra-equals.rs:7:13 + | +LL | if let 1..==3 = 1 {} + | ^^^^ help: use `..=` instead + | + = note: inclusive ranges end with a single equals sign (`..=`) + +error: aborting due to previous error + diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs index a10add6d9e..2e5a991543 100644 --- a/src/test/ui/parser/recover-range-pats.rs +++ b/src/test/ui/parser/recover-range-pats.rs @@ -41,30 +41,30 @@ fn inclusive_from_to() { fn inclusive2_from_to() { if let 0...3 = 0 {} //~^ ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition if let 0...Y = 0 {} //~^ ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition if let X...3 = 0 {} //~^ ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition if let X...Y = 0 {} //~^ ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition if let true...Y = 0 {} //~ ERROR only `char` and numeric types //~^ ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition if let X...true = 0 {} //~ ERROR only `char` and numeric types //~^ ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition if let .0...Y = 0 {} //~ ERROR mismatched types //~^ ERROR float literals must have an integer part - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition //~| ERROR `...` range patterns are deprecated if let X... .0 = 0 {} //~ ERROR mismatched types //~^ ERROR float literals must have an integer part //~| ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition } fn exclusive_from() { @@ -137,7 +137,7 @@ fn with_macro_expr_var() { let $e1..$e2; let $e1...$e2; //~^ ERROR `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition let $e1..=$e2; } } diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr index 3236ef0db2..2d8088432a 100644 --- a/src/test/ui/parser/recover-range-pats.stderr +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -204,7 +204,7 @@ note: the lint level is defined here | LL | #![deny(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -213,7 +213,7 @@ error: `...` range patterns are deprecated LL | if let 0...Y = 0 {} | ^^^ help: use `..=` for an inclusive range | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -222,7 +222,7 @@ error: `...` range patterns are deprecated LL | if let X...3 = 0 {} | ^^^ help: use `..=` for an inclusive range | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -231,7 +231,7 @@ error: `...` range patterns are deprecated LL | if let X...Y = 0 {} | ^^^ help: use `..=` for an inclusive range | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -240,7 +240,7 @@ error: `...` range patterns are deprecated LL | if let true...Y = 0 {} | ^^^ help: use `..=` for an inclusive range | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -249,7 +249,7 @@ error: `...` range patterns are deprecated LL | if let X...true = 0 {} | ^^^ help: use `..=` for an inclusive range | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -258,7 +258,7 @@ error: `...` range patterns are deprecated LL | if let .0...Y = 0 {} | ^^^ help: use `..=` for an inclusive range | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -267,7 +267,7 @@ error: `...` range patterns are deprecated LL | if let X... .0 = 0 {} | ^^^ help: use `..=` for an inclusive range | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: `...` range patterns are deprecated @@ -279,7 +279,7 @@ LL | let $e1...$e2; LL | mac2!(0, 1); | ------------ in this macro invocation | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/recover-ref-dyn-mut.rs b/src/test/ui/parser/recover-ref-dyn-mut.rs new file mode 100644 index 0000000000..3016275cc0 --- /dev/null +++ b/src/test/ui/parser/recover-ref-dyn-mut.rs @@ -0,0 +1,9 @@ +// Test that the parser detects `&dyn mut`, offers a help message, and +// recovers. + +fn main() { + let r: &dyn mut Trait; + //~^ ERROR: `mut` must precede `dyn` + //~| HELP: place `mut` before `dyn` + //~| ERROR: cannot find trait `Trait` in this scope [E0405] +} diff --git a/src/test/ui/parser/recover-ref-dyn-mut.stderr b/src/test/ui/parser/recover-ref-dyn-mut.stderr new file mode 100644 index 0000000000..c048c8ea1b --- /dev/null +++ b/src/test/ui/parser/recover-ref-dyn-mut.stderr @@ -0,0 +1,15 @@ +error: `mut` must precede `dyn` + --> $DIR/recover-ref-dyn-mut.rs:5:12 + | +LL | let r: &dyn mut Trait; + | ^^^^^^^^ help: place `mut` before `dyn`: `&mut dyn` + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/recover-ref-dyn-mut.rs:5:21 + | +LL | let r: &dyn mut Trait; + | ^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr index fe9c113710..5c229431ad 100644 --- a/src/test/ui/parser/struct-literal-in-for.stderr +++ b/src/test/ui/parser/struct-literal-in-for.stderr @@ -25,7 +25,11 @@ LL | | }.hi() { | = help: the trait `Iterator` is not implemented for `bool` = note: required because of the requirements on the impl of `IntoIterator` for `bool` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/trait-object-trait-parens.rs b/src/test/ui/parser/trait-object-trait-parens.rs index 7d55da7d09..438034bc38 100644 --- a/src/test/ui/parser/trait-object-trait-parens.rs +++ b/src/test/ui/parser/trait-object-trait-parens.rs @@ -9,15 +9,15 @@ fn main() { //~^ ERROR `?Trait` is not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition let _: Box Trait<'a>) + (Obj)>; //~^ ERROR `?Trait` is not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition let _: Box Trait<'a> + (Obj) + (?Sized)>; //~^ ERROR `?Trait` is not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition } diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr index 79b6892dc0..9bfc4943fe 100644 --- a/src/test/ui/parser/trait-object-trait-parens.stderr +++ b/src/test/ui/parser/trait-object-trait-parens.stderr @@ -23,7 +23,7 @@ LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Obj) + (?Sized) + (for<'a> Trait<'a>)` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 warning: trait objects without an explicit `dyn` are deprecated @@ -32,7 +32,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | let _: Box Trait<'a>) + (Obj)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn ?Sized + (for<'a> Trait<'a>) + (Obj)` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 warning: trait objects without an explicit `dyn` are deprecated @@ -41,7 +41,7 @@ warning: trait objects without an explicit `dyn` are deprecated LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn for<'a> Trait<'a> + (Obj) + (?Sized)` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error[E0225]: only auto traits can be used as additional traits in a trait object diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs index fe993a6ee1..0b61e267da 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -4,32 +4,32 @@ fn main() {} fn f1_1(x: isize, ...) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic fn f1_2(...) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR C-variadic function must be declared with at least one named argument extern "C" fn f2_1(x: isize, ...) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic extern "C" fn f2_2(...) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR C-variadic function must be declared with at least one named argument extern "C" fn f2_3(..., x: isize) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR `...` must be the last argument of a C-variadic function extern "C" fn f3_1(x: isize, ...) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic extern "C" fn f3_2(...) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR C-variadic function must be declared with at least one named argument extern "C" fn f3_3(..., x: isize) {} -//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR `...` must be the last argument of a C-variadic function extern "C" { @@ -43,35 +43,35 @@ struct X; impl X { fn i_f1(x: isize, ...) {} - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic fn i_f2(...) {} - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR C-variadic function must be declared with at least one named argument fn i_f3(..., x: isize, ...) {} - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic - //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR `...` must be the last argument of a C-variadic function fn i_f4(..., x: isize, ...) {} - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic - //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR `...` must be the last argument of a C-variadic function } trait T { fn t_f1(x: isize, ...) {} - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic fn t_f2(x: isize, ...); - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic fn t_f3(...) {} - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR C-variadic function must be declared with at least one named argument fn t_f4(...); - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR C-variadic function must be declared with at least one named argument fn t_f5(..., x: isize) {} - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR `...` must be the last argument of a C-variadic function fn t_f6(..., x: isize); - //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR `...` must be the last argument of a C-variadic function } diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr index 10fd05c0be..f1cbbb279c 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -1,4 +1,4 @@ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19 | LL | fn f1_1(x: isize, ...) {} @@ -10,13 +10,13 @@ error: C-variadic function must be declared with at least one named argument LL | fn f1_2(...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 | LL | fn f1_2(...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:13:30 | LL | extern "C" fn f2_1(x: isize, ...) {} @@ -28,7 +28,7 @@ error: C-variadic function must be declared with at least one named argument LL | extern "C" fn f2_2(...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:16:20 | LL | extern "C" fn f2_2(...) {} @@ -40,13 +40,13 @@ error: `...` must be the last argument of a C-variadic function LL | extern "C" fn f2_3(..., x: isize) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:20:20 | LL | extern "C" fn f2_3(..., x: isize) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:24:30 | LL | extern "C" fn f3_1(x: isize, ...) {} @@ -58,7 +58,7 @@ error: C-variadic function must be declared with at least one named argument LL | extern "C" fn f3_2(...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:27:20 | LL | extern "C" fn f3_2(...) {} @@ -70,7 +70,7 @@ error: `...` must be the last argument of a C-variadic function LL | extern "C" fn f3_3(..., x: isize) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:31:20 | LL | extern "C" fn f3_3(..., x: isize) {} @@ -88,7 +88,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn e_f2(..., x: isize); | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:45:23 | LL | fn i_f1(x: isize, ...) {} @@ -100,7 +100,7 @@ error: C-variadic function must be declared with at least one named argument LL | fn i_f2(...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13 | LL | fn i_f2(...) {} @@ -112,13 +112,13 @@ error: `...` must be the last argument of a C-variadic function LL | fn i_f3(..., x: isize, ...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:50:28 | LL | fn i_f3(..., x: isize, ...) {} @@ -130,25 +130,25 @@ error: `...` must be the last argument of a C-variadic function LL | fn i_f4(..., x: isize, ...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:54:13 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:54:28 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:61:23 | LL | fn t_f1(x: isize, ...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:63:23 | LL | fn t_f2(x: isize, ...); @@ -160,7 +160,7 @@ error: C-variadic function must be declared with at least one named argument LL | fn t_f3(...) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 | LL | fn t_f3(...) {} @@ -172,7 +172,7 @@ error: C-variadic function must be declared with at least one named argument LL | fn t_f4(...); | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13 | LL | fn t_f4(...); @@ -184,7 +184,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn t_f5(..., x: isize) {} | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13 | LL | fn t_f5(..., x: isize) {} @@ -196,7 +196,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn t_f6(..., x: isize); | ^^^ -error: only foreign or `unsafe extern "C" functions may be C-variadic +error: only foreign or `unsafe extern "C"` functions may be C-variadic --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13 | LL | fn t_f6(..., x: isize); diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs deleted file mode 100644 index f10a7f2d8a..0000000000 --- a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let x = 255u8; - let 0u8..=x = 0; - //~^ ERROR runtime values cannot be referenced in patterns -} diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr deleted file mode 100644 index c1508bd71f..0000000000 --- a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: runtime values cannot be referenced in patterns - --> $DIR/issue-68394-let-pat-runtime-value.rs:3:15 - | -LL | let 0u8..=x = 0; - | ^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/pattern/issue-68396-let-float-bug.rs b/src/test/ui/pattern/issue-68396-let-float-bug.rs deleted file mode 100644 index afc599a4b2..0000000000 --- a/src/test/ui/pattern/issue-68396-let-float-bug.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - let 1234567890123456789012345678901234567890e-340: f64 = 0.0; - //~^ ERROR could not evaluate float literal (see issue #31407) - - fn param(1234567890123456789012345678901234567890e-340: f64) {} - //~^ ERROR could not evaluate float literal (see issue #31407) -} diff --git a/src/test/ui/pattern/issue-68396-let-float-bug.stderr b/src/test/ui/pattern/issue-68396-let-float-bug.stderr deleted file mode 100644 index 618aa4b502..0000000000 --- a/src/test/ui/pattern/issue-68396-let-float-bug.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0080]: could not evaluate float literal (see issue #31407) - --> $DIR/issue-68396-let-float-bug.rs:2:9 - | -LL | let 1234567890123456789012345678901234567890e-340: f64 = 0.0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0080]: could not evaluate float literal (see issue #31407) - --> $DIR/issue-68396-let-float-bug.rs:5:14 - | -LL | fn param(1234567890123456789012345678901234567890e-340: f64) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs deleted file mode 100644 index 65f27cf78f..0000000000 --- a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(impl_trait_in_bindings)] -#![allow(incomplete_features)] - -fn main() { - const C: impl Copy = 0; - match C { - C | //~ ERROR: `impl Copy` cannot be used in patterns - _ => {} - } -} diff --git a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr deleted file mode 100644 index 62dc856be8..0000000000 --- a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `impl Copy` cannot be used in patterns - --> $DIR/issue-71042-opaquely-typed-constant-used-in-pattern.rs:7:9 - | -LL | C | - | ^ - -error: aborting due to previous error - diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs index 9c320edc4d..a6144c9497 100644 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs @@ -23,8 +23,8 @@ fn tuple() { _x1 = U; //~ ERROR cannot assign twice to immutable variable let _x0_hold = &mut tup.0; //~ ERROR cannot borrow `tup.0` as mutable because it is also let (ref mut _x0_hold, ..) = tup; //~ ERROR cannot borrow `tup.0` as mutable because it is also - *_x0 = U; //~ ERROR cannot assign to `*_x0` which is behind a `&` reference - *_x2 = U; //~ ERROR cannot assign to `*_x2` which is behind a `&` reference + *_x0 = U; //~ ERROR cannot assign to `*_x0`, which is behind a `&` reference + *_x2 = U; //~ ERROR cannot assign to `*_x2`, which is behind a `&` reference drop(tup.1); //~ ERROR use of moved value: `tup.1` let _x1_hold = &tup.1; //~ ERROR borrow of moved value: `tup.1` let (.., ref mut _x3) = tup; diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr index d0726f05cc..5beca04d28 100644 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -101,7 +101,7 @@ LL | let (ref mut _x0_hold, ..) = tup; LL | *_x0 = U; | -------- immutable borrow later used here -error[E0594]: cannot assign to `*_x0` which is behind a `&` reference +error[E0594]: cannot assign to `*_x0`, which is behind a `&` reference --> $DIR/borrowck-move-ref-pattern.rs:26:5 | LL | let (ref _x0, _x1, ref _x2, ..) = tup; @@ -110,7 +110,7 @@ LL | let (ref _x0, _x1, ref _x2, ..) = tup; LL | *_x0 = U; | ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*_x2` which is behind a `&` reference +error[E0594]: cannot assign to `*_x2`, which is behind a `&` reference --> $DIR/borrowck-move-ref-pattern.rs:27:5 | LL | let (ref _x0, _x1, ref _x2, ..) = tup; diff --git a/src/test/ui/pattern/non-constant-in-const-path.rs b/src/test/ui/pattern/non-constant-in-const-path.rs new file mode 100644 index 0000000000..3918485bac --- /dev/null +++ b/src/test/ui/pattern/non-constant-in-const-path.rs @@ -0,0 +1,18 @@ +// Checks if we emit `PatternError`s correctly. +// This is also a regression test for #27895 and #68394. + +static FOO: u8 = 10; + +fn main() { + let x = 0; + let 0u8..=x = 0; + //~^ ERROR: runtime values cannot be referenced in patterns + let 0u8..=FOO = 0; + //~^ ERROR: statics cannot be referenced in patterns + match 1 { + 0 ..= x => {} + //~^ ERROR: runtime values cannot be referenced in patterns + 0 ..= FOO => {} + //~^ ERROR: statics cannot be referenced in patterns + }; +} diff --git a/src/test/ui/pattern/non-constant-in-const-path.stderr b/src/test/ui/pattern/non-constant-in-const-path.stderr new file mode 100644 index 0000000000..53c3974f78 --- /dev/null +++ b/src/test/ui/pattern/non-constant-in-const-path.stderr @@ -0,0 +1,28 @@ +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:8:15 + | +LL | let 0u8..=x = 0; + | ^ + +error[E0158]: statics cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:10:15 + | +LL | let 0u8..=FOO = 0; + | ^^^ + +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:13:15 + | +LL | 0 ..= x => {} + | ^ + +error[E0158]: statics cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:15:15 + | +LL | 0 ..= FOO => {} + | ^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0158. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr index 65c10a7bca..70e6fcb7a0 100644 --- a/src/test/ui/privacy/privacy1.stderr +++ b/src/test/ui/privacy/privacy1.stderr @@ -157,30 +157,45 @@ LL | trait B { error[E0624]: associated function `bar` is private --> $DIR/privacy1.rs:77:23 | +LL | fn bar() {} + | -------- private associated function defined here +... LL | self::baz::A::bar(); | ^^^ private associated function error[E0624]: associated function `bar` is private --> $DIR/privacy1.rs:95:13 | +LL | fn bar() {} + | -------- private associated function defined here +... LL | bar::A::bar(); | ^^^ private associated function error[E0624]: associated function `bar` is private --> $DIR/privacy1.rs:102:19 | +LL | fn bar() {} + | -------- private associated function defined here +... LL | ::bar::A::bar(); | ^^^ private associated function error[E0624]: associated function `bar` is private --> $DIR/privacy1.rs:105:24 | +LL | fn bar() {} + | -------- private associated function defined here +... LL | ::bar::baz::A::bar(); | ^^^ private associated function error[E0624]: associated function `bar2` is private --> $DIR/privacy1.rs:108:23 | +LL | fn bar2(&self) {} + | -------------- private associated function defined here +... LL | ::bar::baz::A.bar2(); | ^^^^ private associated function diff --git a/src/test/ui/privacy/private-impl-method.stderr b/src/test/ui/privacy/private-impl-method.stderr index 444b9180b3..bb54dce7e7 100644 --- a/src/test/ui/privacy/private-impl-method.stderr +++ b/src/test/ui/privacy/private-impl-method.stderr @@ -1,6 +1,9 @@ error[E0624]: associated function `foo` is private --> $DIR/private-impl-method.rs:20:7 | +LL | fn foo(&self) {} + | ------------- private associated function defined here +... LL | s.foo(); | ^^^ private associated function diff --git a/src/test/ui/privacy/private-method-cross-crate.stderr b/src/test/ui/privacy/private-method-cross-crate.stderr index 8a47846d66..6532932993 100644 --- a/src/test/ui/privacy/private-method-cross-crate.stderr +++ b/src/test/ui/privacy/private-method-cross-crate.stderr @@ -3,6 +3,11 @@ error[E0624]: associated function `nap` is private | LL | nyan.nap(); | ^^^ private associated function + | + ::: $DIR/auxiliary/cci_class_5.rs:8:9 + | +LL | fn nap(&self) {} + | ------------- private associated function defined here error: aborting due to previous error diff --git a/src/test/ui/privacy/private-method-inherited.stderr b/src/test/ui/privacy/private-method-inherited.stderr index 8083b197a5..011a7fee47 100644 --- a/src/test/ui/privacy/private-method-inherited.stderr +++ b/src/test/ui/privacy/private-method-inherited.stderr @@ -1,6 +1,9 @@ error[E0624]: associated function `f` is private --> $DIR/private-method-inherited.rs:13:7 | +LL | fn f(self) {} + | ---------- private associated function defined here +... LL | x.f(); | ^ private associated function diff --git a/src/test/ui/privacy/private-method.stderr b/src/test/ui/privacy/private-method.stderr index a15fce4687..17c7179dc3 100644 --- a/src/test/ui/privacy/private-method.stderr +++ b/src/test/ui/privacy/private-method.stderr @@ -1,6 +1,9 @@ error[E0624]: associated function `nap` is private --> $DIR/private-method.rs:22:8 | +LL | fn nap(&self) {} + | ------------- private associated function defined here +... LL | nyan.nap(); | ^^^ private associated function diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr index 61b9a43f89..6950667f1e 100644 --- a/src/test/ui/privacy/restricted/test.stderr +++ b/src/test/ui/privacy/restricted/test.stderr @@ -55,12 +55,18 @@ LL | S::default().x; error[E0624]: associated function `f` is private --> $DIR/test.rs:32:18 | +LL | pub(super) fn f(&self) {} + | ---------------------- private associated function defined here +... LL | S::default().f(); | ^ private associated function error[E0624]: associated function `g` is private --> $DIR/test.rs:33:8 | +LL | pub(super) fn g() {} + | ----------------- private associated function defined here +... LL | S::g(); | ^ private associated function @@ -81,12 +87,22 @@ error[E0624]: associated function `g` is private | LL | u.g(); | ^ private associated function + | + ::: $DIR/auxiliary/pub_restricted.rs:14:5 + | +LL | pub(crate) fn g(&self) {} + | ---------------------- private associated function defined here error[E0624]: associated function `h` is private --> $DIR/test.rs:46:7 | LL | u.h(); | ^ private associated function + | + ::: $DIR/auxiliary/pub_restricted.rs:15:5 + | +LL | crate fn h(&self) {} + | ----------------- private associated function defined here error: aborting due to 12 previous errors diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.rs b/src/test/ui/proc-macro/attributes-on-modules-fail.rs index c506e903e7..6c30e8f4f9 100644 --- a/src/test/ui/proc-macro/attributes-on-modules-fail.rs +++ b/src/test/ui/proc-macro/attributes-on-modules-fail.rs @@ -13,7 +13,7 @@ mod m { struct Y; type A = X; //~ ERROR cannot find type `X` in this scope -#[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions +#[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s mod n {} #[empty_attr] diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr index 7141a1b50b..bb6cbb6984 100644 --- a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr +++ b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr @@ -1,8 +1,10 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/attributes-on-modules-fail.rs:16:1 | LL | #[derive(Copy)] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ not applicable here +LL | mod n {} + | -------- not a `struct`, `enum` or `union` error[E0658]: non-inline modules in proc macro input are unstable --> $DIR/attributes-on-modules-fail.rs:20:1 diff --git a/src/test/ui/proc-macro/auxiliary/call-deprecated.rs b/src/test/ui/proc-macro/auxiliary/call-deprecated.rs new file mode 100644 index 0000000000..2f484809a5 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/call-deprecated.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +#[deprecated(since = "1.0.0", note = "test")] +pub fn attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +#[deprecated(since = "1.0.0", note = "test")] +pub fn attr_remove(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/call-deprecated.rs b/src/test/ui/proc-macro/call-deprecated.rs new file mode 100644 index 0000000000..b92cc23638 --- /dev/null +++ b/src/test/ui/proc-macro/call-deprecated.rs @@ -0,0 +1,34 @@ +// check-pass +// aux-build:call-deprecated.rs + +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`. +// See #63221 for a discussion about how we should +// handle the interaction of 'inert' attributes and +// proc-macro attributes. + +#[allow(deprecated)] +#[call_deprecated::attr] //~ WARN use of deprecated macro +struct First; + +#[allow(deprecated)] +#[call_deprecated::attr_remove] //~ WARN use of deprecated macro +struct Second; + +#[allow(deprecated)] +mod bar { + #[allow(deprecated)] + #[call_deprecated::attr] + struct Third; + + #[allow(deprecated)] + #[call_deprecated::attr_remove] + struct Fourth; +} + + +fn main() { +} diff --git a/src/test/ui/proc-macro/call-deprecated.stderr b/src/test/ui/proc-macro/call-deprecated.stderr new file mode 100644 index 0000000000..3506f9a16a --- /dev/null +++ b/src/test/ui/proc-macro/call-deprecated.stderr @@ -0,0 +1,16 @@ +warning: use of deprecated macro `call_deprecated::attr`: test + --> $DIR/call-deprecated.rs:14:3 + | +LL | #[call_deprecated::attr] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated macro `call_deprecated::attr_remove`: test + --> $DIR/call-deprecated.rs:18:3 + | +LL | #[call_deprecated::attr_remove] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr index e764480e8e..070b066721 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr @@ -81,7 +81,7 @@ LL | tuple_from_req!(Foo); warning: 5 warnings emitted -Future incompatibility report: Future breakage date: None, diagnostic: +Future incompatibility report: Future breakage diagnostic: warning: using an old version of `time-macros-impl` --> $DIR/time-macros-impl/src/lib.rs:5:32 | @@ -99,7 +99,7 @@ LL | impl_macros!(Foo); = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `time-macros-impl` --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32 | @@ -116,7 +116,7 @@ LL | impl_macros!(Foo); = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage = note: this warning originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `js-sys` --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 | @@ -133,7 +133,7 @@ LL | arrays!(Foo); = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above = note: this warning originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `actix-web` --> $DIR/actix-web/src/extract.rs:5:34 | @@ -150,7 +150,7 @@ LL | tuple_from_req!(Foo); = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage = note: this warning originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info) -Future breakage date: None, diagnostic: +Future breakage diagnostic: warning: using an old version of `actix-web` --> $DIR/actix-web-2.0.0/src/extract.rs:5:34 | diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr index 0b930705e3..4d6edab08e 100644 --- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr @@ -11,7 +11,7 @@ LL | enum ProceduralMasqueradeDummyType { warning: 1 warning emitted -Future incompatibility report: Future breakage date: None, diagnostic: +Future incompatibility report: Future breakage diagnostic: warning: using `procedural-masquerade` crate --> $DIR/issue-73933-procedural-masquerade.rs:8:6 | diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs new file mode 100644 index 0000000000..8be1ae7773 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs @@ -0,0 +1,11 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +//! Inner doc comment +//~^ ERROR expected outer doc comment +#[derive(Empty)] +pub struct Foo; + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr new file mode 100644 index 0000000000..0b2e612ee5 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr @@ -0,0 +1,11 @@ +error[E0753]: expected outer doc comment + --> $DIR/issue-86781-bad-inner-doc.rs:6:1 + | +LL | //! Inner doc comment + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0753`. diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.rs b/src/test/ui/proc-macro/macros-in-extern-derive.rs index e52bf435a1..c8b26b0059 100644 --- a/src/test/ui/proc-macro/macros-in-extern-derive.rs +++ b/src/test/ui/proc-macro/macros-in-extern-derive.rs @@ -1,5 +1,5 @@ extern "C" { - #[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions + #[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s fn f(); } diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.stderr b/src/test/ui/proc-macro/macros-in-extern-derive.stderr index 6b73744920..efd9ff2250 100644 --- a/src/test/ui/proc-macro/macros-in-extern-derive.stderr +++ b/src/test/ui/proc-macro/macros-in-extern-derive.stderr @@ -1,8 +1,10 @@ -error[E0774]: `derive` may only be applied to structs, enums and unions +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/macros-in-extern-derive.rs:2:5 | LL | #[derive(Copy)] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ not applicable here +LL | fn f(); + | ------- not a `struct`, `enum` or `union` error: aborting due to previous error diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout index 95ef260537..2524d8273b 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -30,7 +30,7 @@ macro_rules! produce_it */ { () => { - meta_macro :: print_def_site! ($ crate :: dummy! ()) ; + meta_macro :: print_def_site! ($crate :: dummy! ()) ; // `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 @@ -43,23 +43,23 @@ fn main /* 0#0 */() { ; } /* Expansions: -0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root -1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) -2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "produce_it", proc_macro: false } -3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) -4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "meta_macro::print_def_site", proc_macro: true } -5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "$crate::dummy", proc_macro: true } +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) +crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it") +crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy") +crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) SyntaxContexts: -#0: parent: #0, outer_mark: (ExpnId(0), Opaque) -#1: parent: #0, outer_mark: (ExpnId(1), Opaque) -#2: parent: #0, outer_mark: (ExpnId(1), Transparent) -#3: parent: #0, outer_mark: (ExpnId(3), Opaque) -#4: parent: #0, outer_mark: (ExpnId(2), SemiTransparent) -#5: parent: #0, outer_mark: (ExpnId(4), Opaque) -#6: parent: #4, outer_mark: (ExpnId(4), Transparent) -#7: parent: #0, outer_mark: (ExpnId(4), SemiTransparent) -#8: parent: #0, outer_mark: (ExpnId(5), Opaque) -#9: parent: #5, outer_mark: (ExpnId(5), Transparent) -#10: parent: #5, outer_mark: (ExpnId(5), SemiTransparent) +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) +#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) +#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#6: parent: #4, outer_mark: (crate0::{{expn3}}, Transparent) +#7: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent) +#8: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) +#9: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) +#10: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout index ac020cddf0..b5ab82737e 100644 --- a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -50,9 +50,9 @@ macro_rules! outer /* 0#0 */ { - ($ item : item) => + ($item : item) => { - macro inner() { print_bang! { $ item } } inner! () ; + macro inner() { print_bang! { $item } } inner! () ; } ; } @@ -67,22 +67,22 @@ fn main /* 0#0 */() { } /* Expansions: -0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root -1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) -2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "outer", proc_macro: false } -3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) -4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro { kind: Bang, name: "inner", proc_macro: false } -5: parent: ExpnId(4), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "print_bang", proc_macro: true } +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) +crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") +crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) SyntaxContexts: -#0: parent: #0, outer_mark: (ExpnId(0), Opaque) -#1: parent: #0, outer_mark: (ExpnId(1), Opaque) -#2: parent: #0, outer_mark: (ExpnId(1), Transparent) -#3: parent: #0, outer_mark: (ExpnId(3), Opaque) -#4: parent: #0, outer_mark: (ExpnId(2), SemiTransparent) -#5: parent: #0, outer_mark: (ExpnId(4), Opaque) -#6: parent: #4, outer_mark: (ExpnId(4), Opaque) -#7: parent: #0, outer_mark: (ExpnId(5), Opaque) -#8: parent: #6, outer_mark: (ExpnId(5), Transparent) -#9: parent: #5, outer_mark: (ExpnId(5), SemiTransparent) +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) +#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) +#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#6: parent: #4, outer_mark: (crate0::{{expn3}}, Opaque) +#7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) +#8: parent: #6, outer_mark: (crate0::{{expn4}}, Transparent) +#9: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ diff --git a/src/test/ui/proc-macro/span-from-proc-macro.stderr b/src/test/ui/proc-macro/span-from-proc-macro.stderr index 2cbe91afac..c3904d62c8 100644 --- a/src/test/ui/proc-macro/span-from-proc-macro.stderr +++ b/src/test/ui/proc-macro/span-from-proc-macro.stderr @@ -2,7 +2,7 @@ error[E0412]: cannot find type `MissingType` in this scope --> $DIR/auxiliary/span-from-proc-macro.rs:37:20 | LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { - | ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]` + | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]` ... LL | field: MissingType | ^^^^^^^^^^^ not found in this scope @@ -10,13 +10,13 @@ LL | field: MissingType ::: $DIR/span-from-proc-macro.rs:8:1 | LL | #[error_from_attribute] - | ----------------------- in this macro invocation + | ----------------------- in this procedural macro expansion error[E0412]: cannot find type `OtherMissingType` in this scope --> $DIR/auxiliary/span-from-proc-macro.rs:46:21 | LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream { - | ------------------------------------------------------------ in this expansion of procedural macro `#[derive(ErrorFromDerive)]` + | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]` ... LL | Variant(OtherMissingType) | ^^^^^^^^^^^^^^^^ not found in this scope @@ -24,13 +24,13 @@ LL | Variant(OtherMissingType) ::: $DIR/span-from-proc-macro.rs:11:10 | LL | #[derive(ErrorFromDerive)] - | --------------- in this macro invocation + | --------------- in this derive macro expansion error[E0425]: cannot find value `my_ident` in this scope --> $DIR/auxiliary/span-from-proc-macro.rs:29:9 | LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream { - | ---------------------------------------------------------------- in this expansion of procedural macro `other_error_from_bang!` + | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!` LL | custom_quote::custom_quote! { LL | my_ident | ^^^^^^^^ not found in this scope @@ -49,7 +49,7 @@ LL | let bang_error: bool = 25; | expected due to this ... LL | pub fn error_from_bang(_input: TokenStream) -> TokenStream { - | ---------------------------------------------------------- in this expansion of procedural macro `error_from_bang!` + | ---------------------------------------------------------- in this expansion of `error_from_bang!` | ::: $DIR/span-from-proc-macro.rs:15:5 | diff --git a/src/test/ui/process-termination/process-termination-blocking-io.rs b/src/test/ui/process-termination/process-termination-blocking-io.rs index f306a61a53..b2dab5c938 100644 --- a/src/test/ui/process-termination/process-termination-blocking-io.rs +++ b/src/test/ui/process-termination/process-termination-blocking-io.rs @@ -9,7 +9,7 @@ use std::{net::TcpListener, sync::mpsc, thread}; fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { - let listen = TcpListener::bind("0.0.0.0:0").unwrap(); + let listen = TcpListener::bind("127.0.0.1:0").unwrap(); tx.send(()).unwrap(); while let Ok(_) = listen.accept() {} }); diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index 2cebffec99..b282fa7803 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr @@ -12,7 +12,11 @@ LL | for i in false..true {} | = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range` = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time --> $DIR/range-1.rs:14:17 diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.fixed b/src/test/ui/range/range-inclusive-pattern-precedence.fixed index 6c01209967..8a4b8fc38e 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence.fixed +++ b/src/test/ui/range/range-inclusive-pattern-precedence.fixed @@ -10,7 +10,7 @@ pub fn main() { match &12 { &(0..=9) => {} //~^ WARN `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition //~| HELP use `..=` for an inclusive range &(10 ..=15) => {} //~^ ERROR the range pattern here has ambiguous interpretation diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.rs b/src/test/ui/range/range-inclusive-pattern-precedence.rs index ce763ba267..b294e436fa 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence.rs +++ b/src/test/ui/range/range-inclusive-pattern-precedence.rs @@ -10,7 +10,7 @@ pub fn main() { match &12 { &0...9 => {} //~^ WARN `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition //~| HELP use `..=` for an inclusive range &10..=15 => {} //~^ ERROR the range pattern here has ambiguous interpretation diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr index ffb833535c..3330ced1eb 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr +++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr @@ -15,7 +15,7 @@ note: the lint level is defined here | LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/range/range-inclusive-pattern-precedence2.rs b/src/test/ui/range/range-inclusive-pattern-precedence2.rs index 7fa2698a49..bede9c5797 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence2.rs +++ b/src/test/ui/range/range-inclusive-pattern-precedence2.rs @@ -9,7 +9,7 @@ fn main() { // FIXME: can we add suggestions like `&(0..=9)`? box 0...9 => {} //~^ WARN `...` range patterns are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition //~| HELP use `..=` for an inclusive range box 10..=15 => {} //~^ ERROR the range pattern here has ambiguous interpretation diff --git a/src/test/ui/range/range-inclusive-pattern-precedence2.stderr b/src/test/ui/range/range-inclusive-pattern-precedence2.stderr index e8e62b485c..90a4aa6822 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence2.stderr +++ b/src/test/ui/range/range-inclusive-pattern-precedence2.stderr @@ -15,7 +15,7 @@ note: the lint level is defined here | LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/range/range_traits-1.stderr b/src/test/ui/range/range_traits-1.stderr index bc4c9a04b5..34c59fcb31 100644 --- a/src/test/ui/range/range_traits-1.stderr +++ b/src/test/ui/range/range_traits-1.stderr @@ -1,115 +1,199 @@ error[E0277]: can't compare `std::ops::Range` with `std::ops::Range` --> $DIR/range_traits-1.rs:5:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +LL | struct AllTheRanges { LL | a: Range, | ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range < std::ops::Range` and `std::ops::Range > std::ops::Range` | = help: the trait `PartialOrd` is not implemented for `std::ops::Range` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeTo` with `std::ops::RangeTo` --> $DIR/range_traits-1.rs:8:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... LL | b: RangeTo, | ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo < std::ops::RangeTo` and `std::ops::RangeTo > std::ops::RangeTo` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeTo` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeFrom` with `std::ops::RangeFrom` --> $DIR/range_traits-1.rs:11:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... LL | c: RangeFrom, | ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom < std::ops::RangeFrom` and `std::ops::RangeFrom > std::ops::RangeFrom` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFrom` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull` --> $DIR/range_traits-1.rs:14:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... LL | d: RangeFull, | ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFull` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeInclusive` with `std::ops::RangeInclusive` --> $DIR/range_traits-1.rs:17:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... LL | e: RangeInclusive, | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive < std::ops::RangeInclusive` and `std::ops::RangeInclusive > std::ops::RangeInclusive` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeInclusive` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeToInclusive` with `std::ops::RangeToInclusive` --> $DIR/range_traits-1.rs:20:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... LL | f: RangeToInclusive, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive < std::ops::RangeToInclusive` and `std::ops::RangeToInclusive > std::ops::RangeToInclusive` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeToInclusive` - = note: required by `std::cmp::PartialOrd::partial_cmp` +note: required by `std::cmp::PartialOrd::partial_cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn partial_cmp(&self, other: &Rhs) -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::Range: Ord` is not satisfied --> $DIR/range_traits-1.rs:5:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +LL | struct AllTheRanges { LL | a: Range, | ^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::Range` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeTo: Ord` is not satisfied --> $DIR/range_traits-1.rs:8:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... LL | b: RangeTo, | ^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeTo` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeFrom: Ord` is not satisfied --> $DIR/range_traits-1.rs:11:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... LL | c: RangeFrom, | ^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFrom` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeFull: Ord` is not satisfied --> $DIR/range_traits-1.rs:14:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... LL | d: RangeFull, | ^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFull` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeInclusive: Ord` is not satisfied --> $DIR/range_traits-1.rs:17:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... LL | e: RangeInclusive, | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeInclusive` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeToInclusive: Ord` is not satisfied --> $DIR/range_traits-1.rs:20:5 | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... LL | f: RangeToInclusive, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeToInclusive` | - = note: required by `std::cmp::Ord::cmp` +note: required by `std::cmp::Ord::cmp` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | fn cmp(&self, other: &Self) -> Ordering; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/src/test/ui/recursion_limit/empty.rs b/src/test/ui/recursion_limit/empty.rs index 31ff9c1e3a..59dae106c0 100644 --- a/src/test/ui/recursion_limit/empty.rs +++ b/src/test/ui/recursion_limit/empty.rs @@ -2,5 +2,7 @@ #![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer //~| `limit` must be a non-negative integer + //~| ERROR `limit` must be a non-negative integer + //~| `limit` must be a non-negative integer fn main() {} diff --git a/src/test/ui/recursion_limit/empty.stderr b/src/test/ui/recursion_limit/empty.stderr index bcd1d27e59..cb5c0c35a5 100644 --- a/src/test/ui/recursion_limit/empty.stderr +++ b/src/test/ui/recursion_limit/empty.stderr @@ -6,5 +6,13 @@ LL | #![recursion_limit = ""] | | | `limit` must be a non-negative integer -error: aborting due to previous error +error: `limit` must be a non-negative integer + --> $DIR/empty.rs:3:1 + | +LL | #![recursion_limit = ""] + | ^^^^^^^^^^^^^^^^^^^^^--^ + | | + | `limit` must be a non-negative integer + +error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion_limit/invalid_digit.rs b/src/test/ui/recursion_limit/invalid_digit.rs index 759d69d0af..03df3e7a92 100644 --- a/src/test/ui/recursion_limit/invalid_digit.rs +++ b/src/test/ui/recursion_limit/invalid_digit.rs @@ -2,5 +2,6 @@ #![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer //~| not a valid integer - + //~| ERROR `limit` must be a non-negative integer + //~| not a valid integer fn main() {} diff --git a/src/test/ui/recursion_limit/invalid_digit.stderr b/src/test/ui/recursion_limit/invalid_digit.stderr index e6fd6b72a0..4dc93ad5f6 100644 --- a/src/test/ui/recursion_limit/invalid_digit.stderr +++ b/src/test/ui/recursion_limit/invalid_digit.stderr @@ -6,5 +6,13 @@ LL | #![recursion_limit = "-100"] | | | not a valid integer -error: aborting due to previous error +error: `limit` must be a non-negative integer + --> $DIR/invalid_digit.rs:3:1 + | +LL | #![recursion_limit = "-100"] + | ^^^^^^^^^^^^^^^^^^^^^------^ + | | + | not a valid integer + +error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion_limit/overflow.rs b/src/test/ui/recursion_limit/overflow.rs index 8eee2792b2..c733ba6b93 100644 --- a/src/test/ui/recursion_limit/overflow.rs +++ b/src/test/ui/recursion_limit/overflow.rs @@ -3,5 +3,7 @@ #![recursion_limit = "999999999999999999999999"] //~^ ERROR `limit` must be a non-negative integer //~| `limit` is too large +//~| ERROR `limit` must be a non-negative integer +//~| `limit` is too large fn main() {} diff --git a/src/test/ui/recursion_limit/overflow.stderr b/src/test/ui/recursion_limit/overflow.stderr index f6ed76c1eb..2f622d28b4 100644 --- a/src/test/ui/recursion_limit/overflow.stderr +++ b/src/test/ui/recursion_limit/overflow.stderr @@ -6,5 +6,13 @@ LL | #![recursion_limit = "999999999999999999999999"] | | | `limit` is too large -error: aborting due to previous error +error: `limit` must be a non-negative integer + --> $DIR/overflow.rs:3:1 + | +LL | #![recursion_limit = "999999999999999999999999"] + | ^^^^^^^^^^^^^^^^^^^^^--------------------------^ + | | + | `limit` is too large + +error: aborting due to 2 previous errors diff --git a/src/test/ui/repr/issue-83505-repr-simd.rs b/src/test/ui/repr/issue-83505-repr-simd.rs new file mode 100644 index 0000000000..280b771d01 --- /dev/null +++ b/src/test/ui/repr/issue-83505-repr-simd.rs @@ -0,0 +1,10 @@ +// Regression test for the ICE described in #83505. + +#![crate_type="lib"] + +#[repr(simd)] +//~^ ERROR: attribute should be applied to a struct [E0517] +//~| ERROR: unsupported representation for zero-variant enum [E0084] +enum Es {} +static CLs: Es; +//~^ ERROR: free static item without body diff --git a/src/test/ui/repr/issue-83505-repr-simd.stderr b/src/test/ui/repr/issue-83505-repr-simd.stderr new file mode 100644 index 0000000000..f1390a6520 --- /dev/null +++ b/src/test/ui/repr/issue-83505-repr-simd.stderr @@ -0,0 +1,30 @@ +error: free static item without body + --> $DIR/issue-83505-repr-simd.rs:9:1 + | +LL | static CLs: Es; + | ^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error[E0517]: attribute should be applied to a struct + --> $DIR/issue-83505-repr-simd.rs:5:8 + | +LL | #[repr(simd)] + | ^^^^ +... +LL | enum Es {} + | ---------- not a struct + +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/issue-83505-repr-simd.rs:5:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ +... +LL | enum Es {} + | ---------- zero-variant enum + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0084, E0517. +For more information about an error, try `rustc --explain E0084`. diff --git a/src/test/ui/repr/issue-83921-ice.rs b/src/test/ui/repr/issue-83921-ice.rs new file mode 100644 index 0000000000..70583eb9bd --- /dev/null +++ b/src/test/ui/repr/issue-83921-ice.rs @@ -0,0 +1,34 @@ +// Regression test for various ICEs inspired by +// https://github.com/rust-lang/rust/issues/83921#issuecomment-814640734 + +// compile-flags: -Zdeduplicate-diagnostics=yes + +#[repr(packed())] +//~^ ERROR: incorrect `repr(packed)` attribute format +struct S1; + +#[repr(align)] +//~^ ERROR: invalid `repr(align)` attribute +struct S2; + +#[repr(align(2, 4))] +//~^ ERROR: incorrect `repr(align)` attribute format +struct S3; + +#[repr(align())] +//~^ ERROR: incorrect `repr(align)` attribute format +struct S4; + +#[repr(i8())] +//~^ ERROR: invalid representation hint +enum E1 { A, B } + +#[repr(u32(42))] +//~^ ERROR: invalid representation hint +enum E2 { A, B } + +#[repr(i64 = 2)] +//~^ ERROR: invalid representation hint +enum E3 { A, B } + +fn main() {} diff --git a/src/test/ui/repr/issue-83921-ice.stderr b/src/test/ui/repr/issue-83921-ice.stderr new file mode 100644 index 0000000000..32c450410e --- /dev/null +++ b/src/test/ui/repr/issue-83921-ice.stderr @@ -0,0 +1,46 @@ +error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all + --> $DIR/issue-83921-ice.rs:6:8 + | +LL | #[repr(packed())] + | ^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: `align` needs an argument + --> $DIR/issue-83921-ice.rs:10:8 + | +LL | #[repr(align)] + | ^^^^^ help: supply an argument here: `align(...)` + +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/issue-83921-ice.rs:14:8 + | +LL | #[repr(align(2, 4))] + | ^^^^^^^^^^^ + +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/issue-83921-ice.rs:18:8 + | +LL | #[repr(align())] + | ^^^^^^^ + +error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list + --> $DIR/issue-83921-ice.rs:22:8 + | +LL | #[repr(i8())] + | ^^^^ + +error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list + --> $DIR/issue-83921-ice.rs:26:8 + | +LL | #[repr(u32(42))] + | ^^^^^^^ + +error[E0552]: invalid representation hint: `i64` does not take a value + --> $DIR/issue-83921-ice.rs:30:8 + | +LL | #[repr(i64 = 2)] + | ^^^^^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0552, E0589, E0693. +For more information about an error, try `rustc --explain E0552`. diff --git a/src/test/ui/repr/issue-83921-pretty.normal.stderr b/src/test/ui/repr/issue-83921-pretty.normal.stderr new file mode 100644 index 0000000000..6b7e831ed2 --- /dev/null +++ b/src/test/ui/repr/issue-83921-pretty.normal.stderr @@ -0,0 +1,9 @@ +error[E0565]: meta item in `repr` must be an identifier + --> $DIR/issue-83921-pretty.rs:10:8 + | +LL | #[repr("C")] + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0565`. diff --git a/src/test/ui/repr/issue-83921-pretty.pretty.stdout b/src/test/ui/repr/issue-83921-pretty.pretty.stdout new file mode 100644 index 0000000000..dad3641f0f --- /dev/null +++ b/src/test/ui/repr/issue-83921-pretty.pretty.stdout @@ -0,0 +1,19 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// Regression test for #83921. A `delay_span_bug()` call was issued, but the +// error was never reported because the pass responsible for detecting and +// reporting the error does not run in certain modes of pretty-printing. + +// Make sure the error is reported if we do not just pretty-print: +// revisions: pretty normal +// [pretty]compile-flags: -Zunpretty=everybody_loops +// [pretty]check-pass +#[repr("C")] +struct A { +} + +fn main() { loop { } } diff --git a/src/test/ui/repr/issue-83921-pretty.rs b/src/test/ui/repr/issue-83921-pretty.rs new file mode 100644 index 0000000000..d5d36470f1 --- /dev/null +++ b/src/test/ui/repr/issue-83921-pretty.rs @@ -0,0 +1,14 @@ +// Regression test for #83921. A `delay_span_bug()` call was issued, but the +// error was never reported because the pass responsible for detecting and +// reporting the error does not run in certain modes of pretty-printing. + +// Make sure the error is reported if we do not just pretty-print: +// revisions: pretty normal +// [pretty]compile-flags: -Zunpretty=everybody_loops +// [pretty]check-pass + +#[repr("C")] +//[normal]~^ ERROR: meta item in `repr` must be an identifier [E0565] +struct A {} + +fn main() {} diff --git a/src/test/ui/repr/repr-disallow-on-variant.rs b/src/test/ui/repr/repr-disallow-on-variant.rs index 90cad7e647..d9bd0b0e38 100644 --- a/src/test/ui/repr/repr-disallow-on-variant.rs +++ b/src/test/ui/repr/repr-disallow-on-variant.rs @@ -2,7 +2,7 @@ struct Test; enum Foo { #[repr(u8)] - //~^ ERROR attribute should be applied to a struct, enum, or union + //~^ ERROR attribute should be applied to an enum Variant, } diff --git a/src/test/ui/repr/repr-disallow-on-variant.stderr b/src/test/ui/repr/repr-disallow-on-variant.stderr index 70b45e393f..f7e4dcc9d8 100644 --- a/src/test/ui/repr/repr-disallow-on-variant.stderr +++ b/src/test/ui/repr/repr-disallow-on-variant.stderr @@ -1,11 +1,11 @@ -error[E0517]: attribute should be applied to a struct, enum, or union +error[E0517]: attribute should be applied to an enum --> $DIR/repr-disallow-on-variant.rs:4:12 | LL | #[repr(u8)] | ^^ LL | LL | Variant, - | ------- not a struct, enum, or union + | ------- not an enum error: aborting due to previous error diff --git a/src/test/ui/repr/repr-transparent.rs b/src/test/ui/repr/repr-transparent.rs index 8fbdb4cc80..8c9d1639c0 100644 --- a/src/test/ui/repr/repr-transparent.rs +++ b/src/test/ui/repr/repr-transparent.rs @@ -8,27 +8,29 @@ use std::marker::PhantomData; #[repr(transparent)] -struct NoFields; //~ ERROR needs exactly one non-zero-sized field +struct NoFields; #[repr(transparent)] -struct ContainsOnlyZst(()); //~ ERROR needs exactly one non-zero-sized field +struct ContainsOnlyZst(()); #[repr(transparent)] -struct ContainsOnlyZstArray([bool; 0]); //~ ERROR needs exactly one non-zero-sized field +struct ContainsOnlyZstArray([bool; 0]); #[repr(transparent)] struct ContainsMultipleZst(PhantomData<*const i32>, NoFields); -//~^ ERROR needs exactly one non-zero-sized field #[repr(transparent)] -struct MultipleNonZst(u8, u8); //~ ERROR needs exactly one non-zero-sized field +struct ContainsZstAndNonZst((), [i32; 2]); + +#[repr(transparent)] +struct MultipleNonZst(u8, u8); //~ ERROR needs at most one non-zero-sized field trait Mirror { type It: ?Sized; } impl Mirror for T { type It = Self; } #[repr(transparent)] pub struct StructWithProjection(f32, ::It); -//~^ ERROR needs exactly one non-zero-sized field +//~^ ERROR needs at most one non-zero-sized field #[repr(transparent)] struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1 @@ -40,22 +42,26 @@ struct ZstAlign32(PhantomData); struct GenericAlign(ZstAlign32, u32); //~ ERROR alignment larger than 1 #[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum -enum Void {} -//~^ ERROR transparent enum needs exactly one variant, but has 0 +enum Void {} //~ ERROR transparent enum needs exactly one variant, but has 0 #[repr(transparent)] -enum FieldlessEnum { //~ ERROR transparent enum needs exactly one non-zero-sized field, but has 0 +enum FieldlessEnum { Foo, } +#[repr(transparent)] +enum UnitFieldEnum { + Foo(()), +} + #[repr(transparent)] enum TooManyFieldsEnum { Foo(u32, String), } -//~^^^ ERROR transparent enum needs exactly one non-zero-sized field, but has 2 +//~^^^ ERROR transparent enum needs at most one non-zero-sized field, but has 2 #[repr(transparent)] -enum TooManyVariants { //~ ERROR transparent enum needs exactly one variant, but has 2 +enum MultipleVariants { //~ ERROR transparent enum needs exactly one variant, but has 2 Foo(String), Bar, } @@ -71,12 +77,12 @@ enum GenericAlignEnum { } #[repr(transparent)] -union UnitUnion { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 0 +union UnitUnion { u: (), } #[repr(transparent)] -union TooManyFields { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 2 +union TooManyFields { //~ ERROR transparent union needs at most one non-zero-sized field, but has 2 u: u32, s: i32 } diff --git a/src/test/ui/repr/repr-transparent.stderr b/src/test/ui/repr/repr-transparent.stderr index cbc74fbb6a..001a181881 100644 --- a/src/test/ui/repr/repr-transparent.stderr +++ b/src/test/ui/repr/repr-transparent.stderr @@ -1,61 +1,37 @@ -error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 - --> $DIR/repr-transparent.rs:11:1 - | -LL | struct NoFields; - | ^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 - -error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 - --> $DIR/repr-transparent.rs:14:1 - | -LL | struct ContainsOnlyZst(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 - -error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 - --> $DIR/repr-transparent.rs:17:1 - | -LL | struct ContainsOnlyZstArray([bool; 0]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 - -error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 - --> $DIR/repr-transparent.rs:20:1 - | -LL | struct ContainsMultipleZst(PhantomData<*const i32>, NoFields); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 - -error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2 - --> $DIR/repr-transparent.rs:24:1 +error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:26:1 | LL | struct MultipleNonZst(u8, u8); | ^^^^^^^^^^^^^^^^^^^^^^--^^--^^ | | | | | | | this field is non-zero-sized | | this field is non-zero-sized - | needs exactly one non-zero-sized field, but has 2 + | needs at most one non-zero-sized field, but has 2 -error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2 - --> $DIR/repr-transparent.rs:30:1 +error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:32:1 | LL | pub struct StructWithProjection(f32, ::It); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^ | | | | | | | this field is non-zero-sized | | this field is non-zero-sized - | needs exactly one non-zero-sized field, but has 2 + | needs at most one non-zero-sized field, but has 2 error[E0691]: zero-sized field in transparent struct has alignment larger than 1 - --> $DIR/repr-transparent.rs:34:32 + --> $DIR/repr-transparent.rs:36:32 | LL | struct NontrivialAlignZst(u32, [u16; 0]); | ^^^^^^^^ has alignment larger than 1 error[E0691]: zero-sized field in transparent struct has alignment larger than 1 - --> $DIR/repr-transparent.rs:40:24 + --> $DIR/repr-transparent.rs:42:24 | LL | struct GenericAlign(ZstAlign32, u32); | ^^^^^^^^^^^^^ has alignment larger than 1 error[E0084]: unsupported representation for zero-variant enum - --> $DIR/repr-transparent.rs:42:1 + --> $DIR/repr-transparent.rs:44:1 | LL | #[repr(transparent)] | ^^^^^^^^^^^^^^^^^^^^ @@ -63,66 +39,54 @@ LL | enum Void {} | ------------ zero-variant enum error[E0731]: transparent enum needs exactly one variant, but has 0 - --> $DIR/repr-transparent.rs:43:1 + --> $DIR/repr-transparent.rs:45:1 | LL | enum Void {} | ^^^^^^^^^ needs exactly one variant, but has 0 -error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 0 - --> $DIR/repr-transparent.rs:47:1 - | -LL | enum FieldlessEnum { - | ^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 - -error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 2 - --> $DIR/repr-transparent.rs:52:1 +error[E0690]: the variant of a transparent enum needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:58:1 | LL | enum TooManyFieldsEnum { - | ^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2 + | ^^^^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2 LL | Foo(u32, String), | --- ------ this field is non-zero-sized | | | this field is non-zero-sized error[E0731]: transparent enum needs exactly one variant, but has 2 - --> $DIR/repr-transparent.rs:58:1 + --> $DIR/repr-transparent.rs:64:1 | -LL | enum TooManyVariants { - | ^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 +LL | enum MultipleVariants { + | ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 LL | Foo(String), | ----------- LL | Bar, - | --- too many variants in `TooManyVariants` + | --- too many variants in `MultipleVariants` error[E0691]: zero-sized field in transparent enum has alignment larger than 1 - --> $DIR/repr-transparent.rs:65:14 + --> $DIR/repr-transparent.rs:71:14 | LL | Foo(u32, [u16; 0]), | ^^^^^^^^ has alignment larger than 1 error[E0691]: zero-sized field in transparent enum has alignment larger than 1 - --> $DIR/repr-transparent.rs:70:11 + --> $DIR/repr-transparent.rs:76:11 | LL | Foo { bar: ZstAlign32, baz: u32 } | ^^^^^^^^^^^^^^^^^^ has alignment larger than 1 -error[E0690]: transparent union needs exactly one non-zero-sized field, but has 0 - --> $DIR/repr-transparent.rs:74:1 - | -LL | union UnitUnion { - | ^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0 - -error[E0690]: transparent union needs exactly one non-zero-sized field, but has 2 - --> $DIR/repr-transparent.rs:79:1 +error[E0690]: transparent union needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:85:1 | LL | union TooManyFields { - | ^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2 + | ^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2 LL | u: u32, | ------ this field is non-zero-sized LL | s: i32 | ------ this field is non-zero-sized -error: aborting due to 17 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0084, E0690, E0691, E0731. For more information about an error, try `rustc --explain E0084`. diff --git a/src/test/ui/resolve/use_suggestion_placement.fixed b/src/test/ui/resolve/use_suggestion_placement.fixed new file mode 100644 index 0000000000..63676327aa --- /dev/null +++ b/src/test/ui/resolve/use_suggestion_placement.fixed @@ -0,0 +1,39 @@ +// run-rustfix +#![allow(dead_code)] + +use m::A; + +use std::collections::HashMap; + +macro_rules! y { + () => {} +} + +mod m { + pub const A: i32 = 0; +} + +mod foo { + // FIXME: UsePlacementFinder is broken because active attributes are + // removed, and thus the `derive` attribute here is not in the AST. + // An inert attribute should work, though. + // #[derive(Debug)] + use std::path::Path; + +#[allow(warnings)] + pub struct Foo; + + // test whether the use suggestion isn't + // placed into the expansion of `#[derive(Debug)] + type Bar = Path; //~ ERROR cannot find +} + +fn main() { + y!(); + let _ = A; //~ ERROR cannot find + foo(); +} + +fn foo() { + type Dict = HashMap; //~ ERROR cannot find +} diff --git a/src/test/ui/resolve/use_suggestion_placement.rs b/src/test/ui/resolve/use_suggestion_placement.rs index 56d4b8d6d1..ecc74d7816 100644 --- a/src/test/ui/resolve/use_suggestion_placement.rs +++ b/src/test/ui/resolve/use_suggestion_placement.rs @@ -1,3 +1,6 @@ +// run-rustfix +#![allow(dead_code)] + macro_rules! y { () => {} } @@ -7,7 +10,11 @@ mod m { } mod foo { - #[derive(Debug)] + // FIXME: UsePlacementFinder is broken because active attributes are + // removed, and thus the `derive` attribute here is not in the AST. + // An inert attribute should work, though. + // #[derive(Debug)] + #[allow(warnings)] pub struct Foo; // test whether the use suggestion isn't diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr index af0495a57a..217c08a560 100644 --- a/src/test/ui/resolve/use_suggestion_placement.stderr +++ b/src/test/ui/resolve/use_suggestion_placement.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Path` in this scope - --> $DIR/use_suggestion_placement.rs:15:16 + --> $DIR/use_suggestion_placement.rs:22:16 | LL | type Bar = Path; | ^^^^ not found in this scope @@ -10,7 +10,7 @@ LL | use std::path::Path; | error[E0425]: cannot find value `A` in this scope - --> $DIR/use_suggestion_placement.rs:20:13 + --> $DIR/use_suggestion_placement.rs:27:13 | LL | let _ = A; | ^ not found in this scope @@ -21,7 +21,7 @@ LL | use m::A; | error[E0412]: cannot find type `HashMap` in this scope - --> $DIR/use_suggestion_placement.rs:25:23 + --> $DIR/use_suggestion_placement.rs:32:23 | LL | type Dict = HashMap; | ^^^^^^^ not found in this scope diff --git a/src/test/ui/retslot-cast.stderr b/src/test/ui/retslot-cast.stderr index 9b5f11ce66..798ce1199a 100644 --- a/src/test/ui/retslot-cast.stderr +++ b/src/test/ui/retslot-cast.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/retslot-cast.rs:13:5 | +LL | -> Option<&Iterator> { + | -------------------------- expected `Option<&dyn Iterator>` because of return type +... LL | inner(x) | ^^^^^^^^ expected trait `Iterator`, found trait `Iterator + Send` | diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.rs b/src/test/ui/return/issue-86188-return-not-in-fn-body.rs new file mode 100644 index 0000000000..4f076fa069 --- /dev/null +++ b/src/test/ui/return/issue-86188-return-not-in-fn-body.rs @@ -0,0 +1,41 @@ +// Due to a compiler bug, if a return occurs outside of a function body +// (e.g. in an AnonConst body), the return value expression would not be +// type-checked, leading to an ICE. This test checks that the ICE no +// longer happens, and that an appropriate error message is issued that +// also explains why the return is considered "outside of a function body" +// if it seems to be inside one, as in the main function below. + +const C: [(); 42] = { + [(); return || { + //~^ ERROR: return statement outside of function body [E0572] + let tx; + }] +}; + +struct S {} +trait Tr { + fn foo(); + fn bar() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} +impl Tr for S { + fn foo() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} + +fn main() { +//~^ NOTE: ...not the enclosing function body + [(); return || { + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + let tx; + }]; +} diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr new file mode 100644 index 0000000000..d7eeb3a729 --- /dev/null +++ b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr @@ -0,0 +1,52 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:9:10 + | +LL | [(); return || { + | __________^ +LL | | +LL | | let tx; +LL | | }] + | |_____^ + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:20:14 + | +LL | / fn bar() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:28:14 + | +LL | / fn foo() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:36:10 + | +LL | / fn main() { +LL | | +LL | | [(); return || { + | |__________^ +LL | || +LL | || +LL | || let tx; +LL | || }]; + | ||_____^ the return is part of this body... +LL | | } + | |_- ...not the enclosing function body + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/return/return-match-array-const.rs b/src/test/ui/return/return-match-array-const.rs index f21eac37c1..b619a4d57f 100644 --- a/src/test/ui/return/return-match-array-const.rs +++ b/src/test/ui/return/return-match-array-const.rs @@ -1,10 +1,19 @@ fn main() { +//~^ NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body [(); return match 0 { n => n }]; - //~^ ERROR: return statement outside of function body + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... [(); return match 0 { 0 => 0 }]; - //~^ ERROR: return statement outside of function body + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... [(); return match () { 'a' => 0, _ => 0 }]; - //~^ ERROR: return statement outside of function body + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + //~| ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found `char` + //~| NOTE: this expression has type `()` } diff --git a/src/test/ui/return/return-match-array-const.stderr b/src/test/ui/return/return-match-array-const.stderr index 8e801e3fbb..85a733adfe 100644 --- a/src/test/ui/return/return-match-array-const.stderr +++ b/src/test/ui/return/return-match-array-const.stderr @@ -1,21 +1,56 @@ error[E0572]: return statement outside of function body - --> $DIR/return-match-array-const.rs:2:10 + --> $DIR/return-match-array-const.rs:5:10 | -LL | [(); return match 0 { n => n }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / fn main() { +LL | | +LL | | +LL | | +LL | | [(); return match 0 { n => n }]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body error[E0572]: return statement outside of function body - --> $DIR/return-match-array-const.rs:5:10 + --> $DIR/return-match-array-const.rs:9:10 | -LL | [(); return match 0 { 0 => 0 }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return match 0 { 0 => 0 }]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body error[E0572]: return statement outside of function body - --> $DIR/return-match-array-const.rs:8:10 + --> $DIR/return-match-array-const.rs:13:10 + | +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return match () { 'a' => 0, _ => 0 }]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error[E0308]: mismatched types + --> $DIR/return-match-array-const.rs:13:28 | LL | [(); return match () { 'a' => 0, _ => 0 }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -- ^^^ expected `()`, found `char` + | | + | this expression has type `()` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0572`. +Some errors have detailed explanations: E0308, E0572. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs index fa5630837b..59a22c3377 100644 --- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs +++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs @@ -17,8 +17,6 @@ fn main() { match x { f32::INFINITY => { } //~^ WARNING floating-point types cannot be used in patterns - //~| WARNING will become a hard error in a future release - //~| WARNING floating-point types cannot be used in patterns //~| WARNING this was previously accepted by the compiler but is being phased out _ => { } } 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 9a5d57d411..df4809dabf 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 @@ -14,14 +14,5 @@ LL | f32::INFINITY => { } = warning: this was previously accepted 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 -warning: floating-point types cannot be used in patterns - --> $DIR/match-forbidden-without-eq.rs:18:9 - | -LL | f32::INFINITY => { } - | ^^^^^^^^^^^^^ - | - = warning: this was previously accepted 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 - -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted 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 1949e76287..e33253b19c 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,6 +1,8 @@ error[E0277]: `main` has invalid return type `Result` --> $DIR/termination-trait-test-wrong-type.rs:6:1 | +LL | #[test] + | ------- in this procedural macro expansion LL | / fn can_parse_zero_as_f32() -> Result { LL | | "0".parse() LL | | } diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.rs b/src/test/ui/rfc-2005-default-binding-mode/enum.rs index af82d36f87..4e57769d6e 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.rs @@ -6,17 +6,17 @@ use Wrapper::Wrap; pub fn main() { let Wrap(x) = &Wrap(3); - *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference + *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference if let Some(x) = &Some(3) { - *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference + *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference } else { panic!(); } while let Some(x) = &Some(3) { - *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference + *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference break; } } diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr index d6a89006bc..21e3d3d273 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr @@ -1,16 +1,16 @@ -error[E0594]: cannot assign to `*x` which is behind a `&` reference +error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/enum.rs:9:5 | LL | *x += 1; | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*x` which is behind a `&` reference +error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/enum.rs:13:9 | LL | *x += 1; | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*x` which is behind a `&` reference +error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/enum.rs:19:9 | LL | *x += 1; diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs index 212fd94ded..b8fde2208a 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs @@ -4,7 +4,7 @@ fn main() { match &&Some(5i32) { Some(n) => { - *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference let _ = n; } None => {}, @@ -12,7 +12,7 @@ fn main() { match &mut &Some(5i32) { Some(n) => { - *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference let _ = n; } None => {}, @@ -20,7 +20,7 @@ fn main() { match &&mut Some(5i32) { Some(n) => { - *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference let _ = n; } None => {}, diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr index a6f2f3ec30..c3f64f65a4 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr @@ -1,16 +1,16 @@ -error[E0594]: cannot assign to `*n` which is behind a `&` reference +error[E0594]: cannot assign to `*n`, which is behind a `&` reference --> $DIR/explicit-mut.rs:7:13 | LL | *n += 1; | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*n` which is behind a `&` reference +error[E0594]: cannot assign to `*n`, which is behind a `&` reference --> $DIR/explicit-mut.rs:15:13 | LL | *n += 1; | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*n` which is behind a `&` reference +error[E0594]: cannot assign to `*n`, which is behind a `&` reference --> $DIR/explicit-mut.rs:23:13 | LL | *n += 1; diff --git a/src/test/ui/rfc-2091-track-caller/tracked-trait-obj.rs b/src/test/ui/rfc-2091-track-caller/tracked-trait-obj.rs index 3b2a2238fa..06883a8579 100644 --- a/src/test/ui/rfc-2091-track-caller/tracked-trait-obj.rs +++ b/src/test/ui/rfc-2091-track-caller/tracked-trait-obj.rs @@ -2,22 +2,60 @@ trait Tracked { #[track_caller] - fn handle(&self) { + fn track_caller_trait_method(&self, line: u32, col: u32) { let location = std::panic::Location::caller(); assert_eq!(location.file(), file!()); - // we only call this via trait object, so the def site should *always* be returned - assert_eq!(location.line(), line!() - 4); - assert_eq!(location.column(), 5); + // The trait method definition is annotated with `#[track_caller]`, + // so caller location information will work through a method + // call on a trait object + assert_eq!(location.line(), line, "Bad line"); + assert_eq!(location.column(), col, "Bad col"); } + + fn track_caller_not_on_trait_method(&self); + + #[track_caller] + fn track_caller_through_self(self: Box, line: u32, col: u32); } -impl Tracked for () {} -impl Tracked for u8 {} +impl Tracked for () { + // We have `#[track_caller]` on the implementation of the method, + // but not on the definition of the method in the trait. Therefore, + // caller location information will *not* work through a method call + // on a trait object. Instead, we will get the location of this method + #[track_caller] + fn track_caller_not_on_trait_method(&self) { + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), line!() - 3); + assert_eq!(location.column(), 5); + } + + // We don't have a `#[track_caller]` attribute, but + // `#[track_caller]` is present on the trait definition, + // so we'll still get location information + fn track_caller_through_self(self: Box, line: u32, col: u32) { + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + // The trait method definition is annotated with `#[track_caller]`, + // so caller location information will work through a method + // call on a trait object + assert_eq!(location.line(), line, "Bad line"); + assert_eq!(location.column(), col, "Bad col"); + } +} fn main() { - let tracked: &dyn Tracked = &5u8; - tracked.handle(); + let tracked: &dyn Tracked = &(); + // The column is the start of 'track_caller_trait_method' + tracked.track_caller_trait_method(line!(), 13); const TRACKED: &dyn Tracked = &(); - TRACKED.handle(); + // The column is the start of 'track_caller_trait_method' + TRACKED.track_caller_trait_method(line!(), 13); + TRACKED.track_caller_not_on_trait_method(); + + // The column is the start of `track_caller_through_self` + let boxed: Box = Box::new(()); + boxed.track_caller_through_self(line!(), 11); } diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr index 850ca30405..3cdab6541e 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr @@ -5,9 +5,7 @@ LL | let _: NotDebug = dbg!(NotDebug); | ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `NotDebug` - = note: add `#[derive(Debug)]` or manually implement `Debug` - = note: required because of the requirements on the impl of `Debug` for `&NotDebug` - = note: required by `std::fmt::Debug::fmt` + = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error 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 6985f1b71a..4950b65414 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 @@ -502,7 +502,11 @@ LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/disallowed-positions.rs:46:19 @@ -520,7 +524,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:56:8 @@ -660,7 +668,11 @@ LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:96:11 @@ -690,7 +702,11 @@ LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/disallowed-positions.rs:110:22 @@ -708,7 +724,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:120:11 @@ -848,7 +868,11 @@ LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0614]: type `bool` cannot be dereferenced --> $DIR/disallowed-positions.rs:173:5 @@ -869,7 +893,11 @@ LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | = help: the trait `Try` is not implemented for `bool` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/disallowed-positions.rs:183:16 @@ -887,7 +915,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:198:10 @@ -916,7 +948,11 @@ LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 104 previous errors; 2 warnings emitted diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs new file mode 100644 index 0000000000..d02bebc9d6 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.rs @@ -0,0 +1,19 @@ +// only-i686-pc-windows-msvc +// compile-flags: --crate-type lib --emit link +#![allow(clashing_extern_declarations)] +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete +#[link(name = "foo", kind = "raw-dylib")] +extern "C" { + fn f(x: i32); +} + +pub fn lib_main() { + #[link(name = "foo", kind = "raw-dylib")] + extern "stdcall" { + fn f(x: i32); + //~^ ERROR multiple declarations of external function `f` from library `foo.dll` have different calling conventions + } + + unsafe { f(42); } +} diff --git a/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr new file mode 100644 index 0000000000..a9cfd6b23f --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/multiple-declarations.stderr @@ -0,0 +1,17 @@ +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/multiple-declarations.rs:4:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information + +error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions + --> $DIR/multiple-declarations.rs:14:9 + | +LL | fn f(x: i32); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs new file mode 100644 index 0000000000..e5a5ac2eb2 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.rs @@ -0,0 +1,13 @@ +// only-x86_64-pc-windows-msvc +// compile-flags: --crate-type lib --emit link +#![allow(incomplete_features)] +#![feature(raw_dylib)] +#[link(name = "foo", kind = "raw-dylib")] +extern "stdcall" { + fn f(x: i32); + //~^ ERROR ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture +} + +pub fn lib_main() { + unsafe { f(42); } +} diff --git a/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr new file mode 100644 index 0000000000..fc9008128a --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/unsupported-abi.stderr @@ -0,0 +1,8 @@ +error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture + --> $DIR/unsupported-abi.rs:7:5 + | +LL | fn f(x: i32); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + 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 5a66af1d29..4a1bd5da98 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 @@ -3,7 +3,6 @@ // FIXME: This test should fail since, within a const impl of `Foo`, the bound on `Foo::Bar` should // require a const impl of `Add` for the associated type. -#![allow(incomplete_features)] #![feature(const_trait_impl)] struct NonConstAdd(i32); diff --git a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs new file mode 100644 index 0000000000..be73ec09ce --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs @@ -0,0 +1,13 @@ +#![feature(const_trait_impl)] + +#[default_method_body_is_const] //~ ERROR attribute should be applied +trait A { + #[default_method_body_is_const] //~ ERROR attribute should be applied + fn no_body(self); + + #[default_method_body_is_const] + fn correct_use(&self) {} +} + +#[default_method_body_is_const] //~ ERROR attribute should be applied +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr new file mode 100644 index 0000000000..fcb7e15b20 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr @@ -0,0 +1,32 @@ +error: attribute should be applied to a trait method with body + --> $DIR/attr-misuse.rs:3:1 + | +LL | #[default_method_body_is_const] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait A { +LL | | #[default_method_body_is_const] +LL | | fn no_body(self); +LL | | +LL | | #[default_method_body_is_const] +LL | | fn correct_use(&self) {} +LL | | } + | |_- not a trait method or missing a body + +error: attribute should be applied to a trait method with body + --> $DIR/attr-misuse.rs:12:1 + | +LL | #[default_method_body_is_const] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn main() {} + | ------------ not a trait method or missing a body + +error: attribute should be applied to a trait method with body + --> $DIR/attr-misuse.rs:5:5 + | +LL | #[default_method_body_is_const] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn no_body(self); + | ----------------- not a trait method or missing a body + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs new file mode 100644 index 0000000000..d8fd7ef3c1 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs @@ -0,0 +1,21 @@ +#![feature(const_trait_impl)] + +pub trait MyTrait { + fn func(self); +} + +pub struct NonConst; + +impl MyTrait for NonConst { + fn func(self) { + + } +} + +pub struct Const; + +impl const MyTrait for Const { + fn func(self) { + + } +} 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 new file mode 100644 index 0000000000..80e61ab0a9 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -0,0 +1,21 @@ +#![feature(const_trait_impl)] + +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait MyTrait { + #[stable(feature = "rust1", since = "1.0.0")] + fn func(); +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Unstable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "staged", issue = "none")] +impl const MyTrait for Unstable { + 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 fa5570d545..33e839fd12 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,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(const_trait_impl)] pub trait Plus { 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 d3f350e1b6..5a73c4debb 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -1,5 +1,5 @@ error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/call-const-trait-method-fail.rs:25:5 + --> $DIR/call-const-trait-method-fail.rs:24:5 | LL | a.plus(b) | ^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs index ec6f45f956..cf38bc3c96 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 @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(const_trait_impl)] struct Int(i32); @@ -17,6 +16,9 @@ impl const PartialEq for Int { fn eq(&self, rhs: &Self) -> bool { self.0 == rhs.0 } + fn ne(&self, other: &Self) -> bool { + !self.eq(other) + } } pub trait Plus { 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 new file mode 100644 index 0000000000..536c1d7374 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs @@ -0,0 +1,15 @@ +// check-pass +#![feature(const_fn_trait_bound)] +#![feature(const_trait_impl)] + +trait MyPartialEq { + fn eq(&self, other: &Self) -> bool; +} + +impl const MyPartialEq for T { + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(self, other) + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs index c37990b1af..f3391aa634 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -4,7 +4,6 @@ #![feature(const_trait_impl)] #![feature(const_fn_trait_bound)] -#![allow(incomplete_features)] struct S; @@ -12,6 +11,9 @@ impl const PartialEq for S { fn eq(&self, _: &S) -> bool { true } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } } const fn equals_self(t: &T) -> bool { diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index d553b2ab8e..00a3c7f51f 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -11,6 +11,9 @@ impl const PartialEq for S { fn eq(&self, _: &S) -> bool { true } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } } // This duplicate bound should not result in ambiguities. It should be equivalent to a single const 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 9aefe6380c..087f8fbdcd 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,7 +2,6 @@ // ignore-test #![feature(const_trait_impl)] -#![allow(incomplete_features)] struct S; diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs index 74b0d5fbe4..aee88d6053 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -4,7 +4,6 @@ #![feature(const_trait_impl)] #![feature(const_fn_trait_bound)] -#![allow(incomplete_features)] struct S; @@ -12,6 +11,9 @@ impl const PartialEq for S { fn eq(&self, _: &S) -> bool { true } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } } const fn equals_self(t: &T) -> bool { diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs index e148ad9a0e..4b2f049b99 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(const_trait_impl)] pub struct Int(i32); diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr index 99560ed068..a0960a21d4 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32` - --> $DIR/const-and-non-const-impl.rs:6:1 + --> $DIR/const-and-non-const-impl.rs:5:1 | LL | impl const std::ops::Add for i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | impl const std::ops::Add for i32 { - impl Add for i32; error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int` - --> $DIR/const-and-non-const-impl.rs:24:1 + --> $DIR/const-and-non-const-impl.rs:23:1 | LL | impl std::ops::Add for Int { | -------------------------- first implementation here @@ -17,7 +17,7 @@ LL | impl const std::ops::Add for Int { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/const-and-non-const-impl.rs:6:1 + --> $DIR/const-and-non-const-impl.rs:5:1 | LL | impl const std::ops::Add for i32 { | ^^^^^^^^^^^-------------^^^^^--- 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 fc85e98ef5..3a70741635 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,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(const_trait_impl)] struct S; 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 c6c78c7d1e..aaec67161a 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]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/const-check-fns-in-const-impl.rs:12:16 + --> $DIR/const-check-fns-in-const-impl.rs:11:16 | LL | fn foo() { non_const() } | ^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs new file mode 100644 index 0000000000..7a0db9c98e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs @@ -0,0 +1,30 @@ +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] // FIXME is this needed? + +trait ConstDefaultFn: Sized { + fn b(self); + + #[default_method_body_is_const] + fn a(self) { + self.b(); + } +} + +struct NonConstImpl; +struct ConstImpl; + +impl ConstDefaultFn for NonConstImpl { + fn b(self) {} +} + +impl const ConstDefaultFn for ConstImpl { + fn b(self) {} +} + +const fn test() { + NonConstImpl.a(); + //~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple variants + ConstImpl.a(); +} + +fn main() {} 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 new file mode 100644 index 0000000000..63e4095af2 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/const-default-method-bodies.rs:25:5 + | +LL | NonConstImpl.a(); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs index 936c90e88a..bed4e9fd1e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs @@ -1,5 +1,4 @@ #![feature(const_trait_impl)] -#![allow(incomplete_features)] struct Foo; diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr index 612511a479..603f6b7d28 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `impl` - --> $DIR/const-impl-norecover.rs:6:7 + --> $DIR/const-impl-norecover.rs:5:7 | LL | const impl Foo { | ^^^^ expected identifier, found keyword 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 fd3dd2cef9..470c653dd4 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,5 +1,4 @@ #![feature(const_trait_impl)] -#![allow(incomplete_features)] trait Foo {} 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 84fb619dc9..f815389ff0 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:6:7 + --> $DIR/const-impl-recovery.rs:5:7 | LL | const impl Foo for i32 {} | ^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | impl const Foo for i32 {} |-- ^^^^^ error: expected identifier, found keyword `impl` - --> $DIR/const-impl-recovery.rs:10:7 + --> $DIR/const-impl-recovery.rs:9:7 | LL | const impl Bar for T {} | ^^^^ expected identifier, found keyword diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr new file mode 100644 index 0000000000..3f553a8ee7 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/cross-crate.rs:15:5 + | +LL | NonConst.func(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs new file mode 100644 index 0000000000..4bd3359947 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs @@ -0,0 +1,21 @@ +// revisions: stock gated +#![cfg_attr(gated, feature(const_trait_impl))] + +// aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +fn non_const_context() { + NonConst.func(); + Const.func(); +} + +const fn const_context() { + NonConst.func(); + //~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants + Const.func(); + //[stock]~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr new file mode 100644 index 0000000000..9908f47a7b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -0,0 +1,15 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/cross-crate.rs:15:5 + | +LL | NonConst.func(); + | ^^^^^^^^^^^^^^^ + +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/cross-crate.rs:17:5 + | +LL | Const.func(); + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. 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 4c630d33c5..af4d3909e4 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:14:1 + --> $DIR/feature-gate.rs:13: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 d977243194..7bac72e1bb 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 @@ -2,7 +2,6 @@ // gate-test-const_trait_impl #![cfg_attr(gated, feature(const_trait_impl))] -#![allow(incomplete_features)] #![feature(rustc_attrs)] struct S; 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 724090e49c..91a8bb578a 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:10:6 + --> $DIR/feature-gate.rs:9:6 | LL | impl const T for S {} | ^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs index d368082031..91c3d2d592 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(const_trait_impl)] #![feature(const_fn_trait_bound)] 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 ad14dd62bc..80a4442de2 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs @@ -1,7 +1,6 @@ // Regression test for #69615. #![feature(const_trait_impl)] -#![allow(incomplete_features)] 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 8c76d7eb59..3ec329cba1 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[E0744]: `?` is not allowed in a `const fn` - --> $DIR/hir-const-check.rs:12:9 + --> $DIR/hir-const-check.rs:11:9 | LL | Some(())?; | ^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs new file mode 100644 index 0000000000..59de9e9571 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs @@ -0,0 +1,37 @@ +#![feature(const_trait_impl)] + +trait Tr { + fn req(&self); + + fn prov(&self) { + println!("lul"); + self.req(); + } + + #[default_method_body_is_const] + fn default() {} +} + +struct S; + +impl const Tr for S { + fn req(&self) {} +} //~^^ ERROR const trait implementations may not use non-const default functions + +impl const Tr for u8 { + fn req(&self) {} + fn prov(&self) {} +} + +impl const Tr for u16 { + fn prov(&self) {} + fn default() {} +} //~^^^ ERROR not all trait items implemented + + +impl const Tr for u32 { + fn req(&self) {} + fn default() {} +} //~^^^ ERROR const trait implementations may not use non-const default functions + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr new file mode 100644 index 0000000000..5301e0ad12 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr @@ -0,0 +1,33 @@ +error: const trait implementations may not use non-const default functions + --> $DIR/impl-with-default-fn.rs:17:1 + | +LL | / impl const Tr for S { +LL | | fn req(&self) {} +LL | | } + | |_^ + | + = note: `prov` not implemented + +error: const trait implementations may not use non-const default functions + --> $DIR/impl-with-default-fn.rs:32:1 + | +LL | / impl const Tr for u32 { +LL | | fn req(&self) {} +LL | | fn default() {} +LL | | } + | |_^ + | + = note: `prov` not implemented + +error[E0046]: not all trait items implemented, missing: `req` + --> $DIR/impl-with-default-fn.rs:26:1 + | +LL | fn req(&self); + | -------------- `req` from trait +... +LL | impl const Tr for u16 { + | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.rs b/src/test/ui/rfc-2632-const-trait-impl/stability.rs index 454fde34a2..6b54a9eab5 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(allow_internal_unstable)] #![feature(const_add)] #![feature(const_trait_impl)] diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr index 5b2ebccef1..86b685959a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr @@ -1,5 +1,5 @@ error: trait methods cannot be stable const fn - --> $DIR/stability.rs:14:5 + --> $DIR/stability.rs:13:5 | LL | / fn sub(self, rhs: Self) -> Self { LL | | @@ -8,7 +8,7 @@ LL | | } | |_____^ error: `::add` is not yet stable as a const fn - --> $DIR/stability.rs:32:5 + --> $DIR/stability.rs:31:5 | LL | Int(1i32) + Int(2i32) | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs new file mode 100644 index 0000000000..39a1b6066d --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -0,0 +1,39 @@ +// revisions: stock staged +#![cfg_attr(staged, feature(staged))] + +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +// aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(staged, rustc_const_stable(feature = "rust1", since = "1.0.0"))] +// ^ should trigger error with or without the attribute +impl const MyTrait for Stable { + fn func() { //~ ERROR trait methods cannot be stable const fn + + } +} + +fn non_const_context() { + Unstable::func(); + Stable::func(); +} + +#[unstable(feature = "none", issue = "none")] +const fn const_context() { + Unstable::func(); + //[stock]~^ ERROR `::func` is not yet stable as a const fn + Stable::func(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr new file mode 100644 index 0000000000..d2ff4ce200 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.staged.stderr @@ -0,0 +1,10 @@ +error: trait methods cannot be stable const fn + --> $DIR/staged-api.rs:22:5 + | +LL | / fn func() { +LL | | +LL | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr new file mode 100644 index 0000000000..91c5469bd9 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stock.stderr @@ -0,0 +1,18 @@ +error: trait methods cannot be stable const fn + --> $DIR/staged-api.rs:22:5 + | +LL | / fn func() { +LL | | +LL | | } + | |_____^ + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:34:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(staged)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/rfc-2632-const-trait-impl/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs index 354d48d630..82a1275bff 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/syntax.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs @@ -3,7 +3,6 @@ #![feature(const_trait_bound_opt_out)] #![feature(const_trait_impl)] -#![allow(incomplete_features)] // For now, this parses since an error does not occur until AST lowering. impl ?const T {} diff --git a/src/test/ui/rt-explody-panic-payloads.rs b/src/test/ui/rt-explody-panic-payloads.rs new file mode 100644 index 0000000000..1d3a2ff828 --- /dev/null +++ b/src/test/ui/rt-explody-panic-payloads.rs @@ -0,0 +1,30 @@ +// run-pass +// 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; + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + std::panic::panic_any(Bomb); + } +} + +fn main() { + let args = env::args().collect::>(); + let output = match &args[..] { + [me] => Command::new(&me).arg("plant the").output(), + [..] => std::panic::panic_any(Bomb), + }.expect("running the command should have succeeded"); + println!("{:#?}", output); + let stderr = std::str::from_utf8(&output.stderr); + assert!(stderr.map(|v| { + v.ends_with("drop of the panic payload panicked") + }).unwrap_or(false)); +} diff --git a/src/test/ui/rust-2018/async-ident-allowed.rs b/src/test/ui/rust-2018/async-ident-allowed.rs index 9d961214af..8efcfbb707 100644 --- a/src/test/ui/rust-2018/async-ident-allowed.rs +++ b/src/test/ui/rust-2018/async-ident-allowed.rs @@ -7,5 +7,5 @@ fn main() { let async = 3; //~ ERROR: is a keyword - //~^ WARN previously accepted + //~^ WARN this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/async-ident-allowed.stderr b/src/test/ui/rust-2018/async-ident-allowed.stderr index 43fc3f5e33..5b63eab8e4 100644 --- a/src/test/ui/rust-2018/async-ident-allowed.stderr +++ b/src/test/ui/rust-2018/async-ident-allowed.stderr @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![deny(rust_2018_compatibility)] | ^^^^^^^^^^^^^^^^^^^^^^^ = note: `#[deny(keyword_idents)]` implied by `#[deny(rust_2018_compatibility)]` - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to previous error diff --git a/src/test/ui/rust-2018/async-ident.fixed b/src/test/ui/rust-2018/async-ident.fixed index 3d6f6ff8c4..f4ae518c71 100644 --- a/src/test/ui/rust-2018/async-ident.fixed +++ b/src/test/ui/rust-2018/async-ident.fixed @@ -5,20 +5,20 @@ // run-rustfix fn r#async() {} //~ ERROR async -//~^ WARN hard error in the 2018 edition +//~^ WARN this is accepted in the current edition macro_rules! foo { ($foo:ident) => {}; ($r#async:expr, r#async) => {}; //~^ ERROR async //~| ERROR async - //~| WARN hard error in the 2018 edition - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition + //~| WARN this is accepted in the current edition } foo!(r#async); //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition mod dont_lint_raw { fn r#async() {} @@ -27,53 +27,53 @@ mod dont_lint_raw { mod async_trait { trait r#async {} //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition struct MyStruct; impl r#async for MyStruct {} //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } mod async_static { static r#async: u32 = 0; //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } mod async_const { const r#async: u32 = 0; //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } struct Foo; impl Foo { fn r#async() {} } //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition fn main() { struct r#async {} //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition let r#async: r#async = r#async {}; //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition //~| ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition //~| ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } #[macro_export] macro_rules! produces_async { () => (pub fn r#async() {}) //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } #[macro_export] macro_rules! consumes_async { (r#async) => (1) //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/async-ident.rs b/src/test/ui/rust-2018/async-ident.rs index 6e8d33d237..79c73dafac 100644 --- a/src/test/ui/rust-2018/async-ident.rs +++ b/src/test/ui/rust-2018/async-ident.rs @@ -5,20 +5,20 @@ // run-rustfix fn async() {} //~ ERROR async -//~^ WARN hard error in the 2018 edition +//~^ WARN this is accepted in the current edition macro_rules! foo { ($foo:ident) => {}; ($async:expr, async) => {}; //~^ ERROR async //~| ERROR async - //~| WARN hard error in the 2018 edition - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition + //~| WARN this is accepted in the current edition } foo!(async); //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition mod dont_lint_raw { fn r#async() {} @@ -27,53 +27,53 @@ mod dont_lint_raw { mod async_trait { trait async {} //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition struct MyStruct; impl async for MyStruct {} //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } mod async_static { static async: u32 = 0; //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } mod async_const { const async: u32 = 0; //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } struct Foo; impl Foo { fn async() {} } //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition fn main() { struct async {} //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition let async: async = async {}; //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition //~| ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition //~| ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } #[macro_export] macro_rules! produces_async { () => (pub fn async() {}) //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } #[macro_export] macro_rules! consumes_async { (async) => (1) //~^ ERROR async - //~| WARN hard error in the 2018 edition + //~| WARN this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/async-ident.stderr b/src/test/ui/rust-2018/async-ident.stderr index 6051c81f77..6396e9deee 100644 --- a/src/test/ui/rust-2018/async-ident.stderr +++ b/src/test/ui/rust-2018/async-ident.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -18,7 +18,7 @@ error: `async` is a keyword in the 2018 edition LL | ($async:expr, async) => {}; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -27,7 +27,7 @@ error: `async` is a keyword in the 2018 edition LL | ($async:expr, async) => {}; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -36,7 +36,7 @@ error: `async` is a keyword in the 2018 edition LL | foo!(async); | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -45,7 +45,7 @@ error: `async` is a keyword in the 2018 edition LL | trait async {} | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -54,7 +54,7 @@ error: `async` is a keyword in the 2018 edition LL | impl async for MyStruct {} | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -63,7 +63,7 @@ error: `async` is a keyword in the 2018 edition LL | static async: u32 = 0; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -72,7 +72,7 @@ error: `async` is a keyword in the 2018 edition LL | const async: u32 = 0; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -81,7 +81,7 @@ error: `async` is a keyword in the 2018 edition LL | impl Foo { fn async() {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -90,7 +90,7 @@ error: `async` is a keyword in the 2018 edition LL | struct async {} | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -99,7 +99,7 @@ error: `async` is a keyword in the 2018 edition LL | let async: async = async {}; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -108,7 +108,7 @@ error: `async` is a keyword in the 2018 edition LL | let async: async = async {}; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -117,7 +117,7 @@ error: `async` is a keyword in the 2018 edition LL | let async: async = async {}; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -126,7 +126,7 @@ error: `async` is a keyword in the 2018 edition LL | () => (pub fn async() {}) | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: `async` is a keyword in the 2018 edition @@ -135,7 +135,7 @@ error: `async` is a keyword in the 2018 edition LL | (async) => (1) | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 15 previous errors diff --git a/src/test/ui/rust-2018/dyn-keyword.fixed b/src/test/ui/rust-2018/dyn-keyword.fixed index e9cda1af93..044824cbbd 100644 --- a/src/test/ui/rust-2018/dyn-keyword.fixed +++ b/src/test/ui/rust-2018/dyn-keyword.fixed @@ -6,5 +6,5 @@ fn main() { let r#dyn = (); //~ ERROR dyn - //~^ WARN hard error in the 2018 edition + //~^ WARN this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/dyn-keyword.rs b/src/test/ui/rust-2018/dyn-keyword.rs index bdd3a90cab..5989cfa1c7 100644 --- a/src/test/ui/rust-2018/dyn-keyword.rs +++ b/src/test/ui/rust-2018/dyn-keyword.rs @@ -6,5 +6,5 @@ fn main() { let dyn = (); //~ ERROR dyn - //~^ WARN hard error in the 2018 edition + //~^ WARN this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/dyn-keyword.stderr b/src/test/ui/rust-2018/dyn-keyword.stderr index 0fe11168c4..699242f2dc 100644 --- a/src/test/ui/rust-2018/dyn-keyword.stderr +++ b/src/test/ui/rust-2018/dyn-keyword.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to previous error diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed index 76fbfa6603..37847a98ac 100644 --- a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed +++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed @@ -8,20 +8,19 @@ mod foo { type Bar; } - crate struct Baz { } + crate struct Baz {} impl Foo for Baz { type Bar = (); } } - fn main() { let _: ::Bar = (); //~^ ERROR absolute paths must start with - //~| this was previously accepted + //~| this is accepted in the current edition let _: ::Bar = (); //~^ ERROR absolute paths must start with - //~| this was previously accepted + //~| this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs index ace90a180d..36efa14601 100644 --- a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs +++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs @@ -8,20 +8,19 @@ mod foo { type Bar; } - crate struct Baz { } + crate struct Baz {} impl Foo for Baz { type Bar = (); } } - fn main() { let _: ::Bar = (); //~^ ERROR absolute paths must start with - //~| this was previously accepted + //~| this is accepted in the current edition let _: <::foo::Baz as foo::Foo>::Bar = (); //~^ ERROR absolute paths must start with - //~| this was previously accepted + //~| this is accepted in the current edition } 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 0b400786d3..6f529fa911 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 @@ -1,5 +1,5 @@ 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:20:25 + --> $DIR/edition-lint-fully-qualified-paths.rs:19:25 | LL | let _: ::Bar = (); | ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo` @@ -9,16 +9,16 @@ note: the lint level is defined here | LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 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:24:13 + --> $DIR/edition-lint-fully-qualified-paths.rs:23:13 | LL | let _: <::foo::Baz as foo::Foo>::Bar = (); | ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 2 previous errors diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed index 77478e8c60..03d15cea28 100644 --- a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed +++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed @@ -16,15 +16,15 @@ crate mod foo { use crate::foo::{bar::{baz::{}}}; //~^ ERROR absolute paths must start with -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition use crate::foo::{bar::{XX, baz::{}}}; //~^ ERROR absolute paths must start with -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition use crate::foo::{bar::{baz::{}, baz1::{}}}; //~^ ERROR absolute paths must start with -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition fn main() { } diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs index 69bd4e3a18..d898daaba5 100644 --- a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs +++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs @@ -16,15 +16,15 @@ crate mod foo { use foo::{bar::{baz::{}}}; //~^ ERROR absolute paths must start with -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition use foo::{bar::{XX, baz::{}}}; //~^ ERROR absolute paths must start with -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition use foo::{bar::{baz::{}, baz1::{}}}; //~^ ERROR absolute paths must start with -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition fn main() { } 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 d554cc2862..54a4fed5cf 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 @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition @@ -18,7 +18,7 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c LL | use foo::{bar::{XX, baz::{}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{XX, baz::{}}}` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition @@ -27,7 +27,7 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c LL | use foo::{bar::{baz::{}, baz1::{}}}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}, baz1::{}}}` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 3 previous errors diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.fixed b/src/test/ui/rust-2018/edition-lint-nested-paths.fixed index da7524a63e..7c6e4a71a3 100644 --- a/src/test/ui/rust-2018/edition-lint-nested-paths.fixed +++ b/src/test/ui/rust-2018/edition-lint-nested-paths.fixed @@ -5,7 +5,7 @@ use crate::foo::{a, b}; //~^ ERROR absolute paths must start with -//~| this was previously accepted +//~| this is accepted in the current edition mod foo { crate fn a() {} @@ -20,7 +20,7 @@ fn main() { { use crate::foo::{self as x, c}; //~^ ERROR absolute paths must start with - //~| this was previously accepted + //~| this is accepted in the current edition x::a(); c(); } diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.rs b/src/test/ui/rust-2018/edition-lint-nested-paths.rs index e13b7d0086..3925f76391 100644 --- a/src/test/ui/rust-2018/edition-lint-nested-paths.rs +++ b/src/test/ui/rust-2018/edition-lint-nested-paths.rs @@ -5,7 +5,7 @@ use foo::{a, b}; //~^ ERROR absolute paths must start with -//~| this was previously accepted +//~| this is accepted in the current edition mod foo { crate fn a() {} @@ -20,7 +20,7 @@ fn main() { { use foo::{self as x, c}; //~^ ERROR absolute paths must start with - //~| this was previously accepted + //~| this is accepted in the current edition x::a(); c(); } 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 040aa4a548..c2f91e342f 100644 --- a/src/test/ui/rust-2018/edition-lint-nested-paths.stderr +++ b/src/test/ui/rust-2018/edition-lint-nested-paths.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition @@ -18,7 +18,7 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c LL | use foo::{self as x, c}; | ^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{self as x, c}` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 2 previous errors diff --git a/src/test/ui/rust-2018/edition-lint-paths.fixed b/src/test/ui/rust-2018/edition-lint-paths.fixed index de16291fea..f91405929e 100644 --- a/src/test/ui/rust-2018/edition-lint-paths.fixed +++ b/src/test/ui/rust-2018/edition-lint-paths.fixed @@ -11,30 +11,29 @@ pub mod foo { use edition_lint_paths; use crate::bar::Bar; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition use super::bar::Bar2; use crate::bar::Bar3; use crate::bar; //~^ ERROR absolute - //~| WARN this was previously accepted - use crate::{bar as something_else}; + //~| WARN this is accepted in the current edition + use crate::bar as something_else; - use crate::{Bar as SomethingElse, main}; + use crate::{main, Bar as SomethingElse}; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition - use crate::{Bar as SomethingElse2, main as another_main}; + use crate::{main as another_main, Bar as SomethingElse2}; - pub fn test() { - } + pub fn test() {} - pub trait SomeTrait { } + pub trait SomeTrait {} } use crate::bar::Bar; //~^ ERROR absolute -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition pub mod bar { use edition_lint_paths as foo; @@ -46,17 +45,17 @@ pub mod bar { mod baz { use crate::*; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition } -impl crate::foo::SomeTrait for u32 { } +impl crate::foo::SomeTrait for u32 {} //~^ ERROR absolute -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition fn main() { let x = crate::bar::Bar; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition let x = bar::Bar; let x = crate::bar::Bar; let x = self::bar::Bar; diff --git a/src/test/ui/rust-2018/edition-lint-paths.rs b/src/test/ui/rust-2018/edition-lint-paths.rs index c5b4be5a3a..52c97c7a25 100644 --- a/src/test/ui/rust-2018/edition-lint-paths.rs +++ b/src/test/ui/rust-2018/edition-lint-paths.rs @@ -9,32 +9,31 @@ extern crate edition_lint_paths; pub mod foo { use edition_lint_paths; - use ::bar::Bar; + use bar::Bar; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition use super::bar::Bar2; use crate::bar::Bar3; use bar; //~^ ERROR absolute - //~| WARN this was previously accepted - use crate::{bar as something_else}; + //~| WARN this is accepted in the current edition + use crate::bar as something_else; - use {Bar as SomethingElse, main}; + use {main, Bar as SomethingElse}; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition - use crate::{Bar as SomethingElse2, main as another_main}; + use crate::{main as another_main, Bar as SomethingElse2}; - pub fn test() { - } + pub fn test() {} - pub trait SomeTrait { } + pub trait SomeTrait {} } use bar::Bar; //~^ ERROR absolute -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition pub mod bar { use edition_lint_paths as foo; @@ -46,17 +45,17 @@ pub mod bar { mod baz { use *; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition } -impl ::foo::SomeTrait for u32 { } +impl ::foo::SomeTrait for u32 {} //~^ ERROR absolute -//~| WARN this was previously accepted +//~| WARN this is accepted in the current edition fn main() { let x = ::bar::Bar; //~^ ERROR absolute - //~| WARN this was previously accepted + //~| WARN this is accepted in the current edition let x = bar::Bar; let x = crate::bar::Bar; let x = self::bar::Bar; diff --git a/src/test/ui/rust-2018/edition-lint-paths.stderr b/src/test/ui/rust-2018/edition-lint-paths.stderr index dd36d07da5..23deeda14a 100644 --- a/src/test/ui/rust-2018/edition-lint-paths.stderr +++ b/src/test/ui/rust-2018/edition-lint-paths.stderr @@ -1,15 +1,15 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition --> $DIR/edition-lint-paths.rs:12:9 | -LL | use ::bar::Bar; - | ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar` +LL | use bar::Bar; + | ^^^^^^^^ help: use `crate`: `crate::bar::Bar` | note: the lint level is defined here --> $DIR/edition-lint-paths.rs:5:9 | LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition @@ -18,52 +18,52 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c LL | use bar; | ^^^ help: use `crate`: `crate::bar` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition --> $DIR/edition-lint-paths.rs:23:9 | -LL | use {Bar as SomethingElse, main}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{Bar as SomethingElse, main}` +LL | use {main, Bar as SomethingElse}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition - --> $DIR/edition-lint-paths.rs:35:5 + --> $DIR/edition-lint-paths.rs:34:5 | LL | use bar::Bar; | ^^^^^^^^ help: use `crate`: `crate::bar::Bar` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition - --> $DIR/edition-lint-paths.rs:47:9 + --> $DIR/edition-lint-paths.rs:46:9 | LL | use *; | ^ help: use `crate`: `crate::*` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition - --> $DIR/edition-lint-paths.rs:52:6 + --> $DIR/edition-lint-paths.rs:51:6 | -LL | impl ::foo::SomeTrait for u32 { } +LL | impl ::foo::SomeTrait for u32 {} | ^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::SomeTrait` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition - --> $DIR/edition-lint-paths.rs:57:13 + --> $DIR/edition-lint-paths.rs:56:13 | LL | let x = ::bar::Bar; | ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to 7 previous errors diff --git a/src/test/ui/rust-2018/extern-crate-rename.fixed b/src/test/ui/rust-2018/extern-crate-rename.fixed index c4c9bdf58c..ea832ef3e7 100644 --- a/src/test/ui/rust-2018/extern-crate-rename.fixed +++ b/src/test/ui/rust-2018/extern-crate-rename.fixed @@ -11,7 +11,7 @@ extern crate edition_lint_paths as my_crate; use crate::my_crate::foo; //~^ ERROR absolute paths must start -//~| WARNING this was previously accepted +//~| WARNING this is accepted in the current edition fn main() { foo(); diff --git a/src/test/ui/rust-2018/extern-crate-rename.rs b/src/test/ui/rust-2018/extern-crate-rename.rs index 8f14f2f1fe..b1f617dd88 100644 --- a/src/test/ui/rust-2018/extern-crate-rename.rs +++ b/src/test/ui/rust-2018/extern-crate-rename.rs @@ -11,7 +11,7 @@ extern crate edition_lint_paths as my_crate; use my_crate::foo; //~^ ERROR absolute paths must start -//~| WARNING this was previously accepted +//~| WARNING this is accepted in the current edition fn main() { foo(); diff --git a/src/test/ui/rust-2018/extern-crate-rename.stderr b/src/test/ui/rust-2018/extern-crate-rename.stderr index 6ea762ed99..4bccbc5122 100644 --- a/src/test/ui/rust-2018/extern-crate-rename.stderr +++ b/src/test/ui/rust-2018/extern-crate-rename.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to previous error diff --git a/src/test/ui/rust-2018/extern-crate-submod.fixed b/src/test/ui/rust-2018/extern-crate-submod.fixed index 2a8e24db0b..9b0b0dd8ee 100644 --- a/src/test/ui/rust-2018/extern-crate-submod.fixed +++ b/src/test/ui/rust-2018/extern-crate-submod.fixed @@ -18,7 +18,7 @@ mod m { // *could* rewrite it to `use edition_lint_paths::foo` use crate::m::edition_lint_paths::foo; //~^ ERROR absolute paths must start -//~| WARNING this was previously accepted +//~| WARNING this is accepted in the current edition fn main() { foo(); diff --git a/src/test/ui/rust-2018/extern-crate-submod.rs b/src/test/ui/rust-2018/extern-crate-submod.rs index f3a357917c..dfce9128c5 100644 --- a/src/test/ui/rust-2018/extern-crate-submod.rs +++ b/src/test/ui/rust-2018/extern-crate-submod.rs @@ -18,7 +18,7 @@ mod m { // *could* rewrite it to `use edition_lint_paths::foo` use m::edition_lint_paths::foo; //~^ ERROR absolute paths must start -//~| WARNING this was previously accepted +//~| WARNING this is accepted in the current edition fn main() { foo(); diff --git a/src/test/ui/rust-2018/extern-crate-submod.stderr b/src/test/ui/rust-2018/extern-crate-submod.stderr index 87a0d49267..3c75319aed 100644 --- a/src/test/ui/rust-2018/extern-crate-submod.stderr +++ b/src/test/ui/rust-2018/extern-crate-submod.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 error: aborting due to previous error diff --git a/src/test/ui/rust-2018/try-ident.fixed b/src/test/ui/rust-2018/try-ident.fixed index 13f6f8e282..985348665c 100644 --- a/src/test/ui/rust-2018/try-ident.fixed +++ b/src/test/ui/rust-2018/try-ident.fixed @@ -6,10 +6,10 @@ fn main() { r#try(); //~^ WARNING `try` is a keyword in the 2018 edition - //~| WARNING it will become a hard error in the 2018 edition! + //~| WARNING this is accepted in the current edition } fn r#try() { //~^ WARNING `try` is a keyword in the 2018 edition - //~| WARNING it will become a hard error in the 2018 edition! + //~| WARNING this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/try-ident.rs b/src/test/ui/rust-2018/try-ident.rs index bed7118011..2c02b75960 100644 --- a/src/test/ui/rust-2018/try-ident.rs +++ b/src/test/ui/rust-2018/try-ident.rs @@ -6,10 +6,10 @@ fn main() { try(); //~^ WARNING `try` is a keyword in the 2018 edition - //~| WARNING it will become a hard error in the 2018 edition! + //~| WARNING this is accepted in the current edition } fn try() { //~^ WARNING `try` is a keyword in the 2018 edition - //~| WARNING it will become a hard error in the 2018 edition! + //~| WARNING this is accepted in the current edition } diff --git a/src/test/ui/rust-2018/try-ident.stderr b/src/test/ui/rust-2018/try-ident.stderr index 2939dc1df7..3d93b433cf 100644 --- a/src/test/ui/rust-2018/try-ident.stderr +++ b/src/test/ui/rust-2018/try-ident.stderr @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![warn(rust_2018_compatibility)] | ^^^^^^^^^^^^^^^^^^^^^^^ = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]` - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 warning: `try` is a keyword in the 2018 edition @@ -19,7 +19,7 @@ warning: `try` is a keyword in the 2018 edition LL | fn try() { | ^^^ help: you can use a raw identifier to stay compatible: `r#try` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 warning: 2 warnings emitted diff --git a/src/test/ui/rust-2018/try-macro.fixed b/src/test/ui/rust-2018/try-macro.fixed index 5c899378b9..3308870f65 100644 --- a/src/test/ui/rust-2018/try-macro.fixed +++ b/src/test/ui/rust-2018/try-macro.fixed @@ -11,8 +11,8 @@ fn foo() -> Result { let x: Result = Ok(22); r#try!(x); //~^ WARNING `try` is a keyword in the 2018 edition - //~| WARNING this was previously accepted + //~| WARNING this is accepted in the current edition Ok(44) } -fn main() { } +fn main() {} diff --git a/src/test/ui/rust-2018/try-macro.rs b/src/test/ui/rust-2018/try-macro.rs index db8a198d28..69e87a1ff6 100644 --- a/src/test/ui/rust-2018/try-macro.rs +++ b/src/test/ui/rust-2018/try-macro.rs @@ -11,8 +11,8 @@ fn foo() -> Result { let x: Result = Ok(22); try!(x); //~^ WARNING `try` is a keyword in the 2018 edition - //~| WARNING this was previously accepted + //~| WARNING this is accepted in the current edition Ok(44) } -fn main() { } +fn main() {} diff --git a/src/test/ui/rust-2018/try-macro.stderr b/src/test/ui/rust-2018/try-macro.stderr index cdbb215605..f315b4d4a9 100644 --- a/src/test/ui/rust-2018/try-macro.stderr +++ b/src/test/ui/rust-2018/try-macro.stderr @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![warn(rust_2018_compatibility)] | ^^^^^^^^^^^^^^^^^^^^^^^ = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]` - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = 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 warning: 1 warning emitted diff --git a/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs b/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs new file mode 100644 index 0000000000..eb301e5e1b --- /dev/null +++ b/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs @@ -0,0 +1,25 @@ +// force-host +// edition:2018 +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_integer_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#123").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_char_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#'a'").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs b/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs new file mode 100644 index 0000000000..691bfdc15c --- /dev/null +++ b/src/test/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs @@ -0,0 +1,25 @@ +// force-host +// edition:2021 +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_integer_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#123").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_char_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#'a'").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/src/test/ui/rust-2021/future-prelude-collision-imported.fixed b/src/test/ui/rust-2021/future-prelude-collision-imported.fixed new file mode 100644 index 0000000000..c5ff0b4bcd --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-imported.fixed @@ -0,0 +1,59 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +mod m { + pub trait TryIntoU32 { + fn try_into(self) -> Result; + } + + impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } + } + + pub trait AnotherTrick {} +} + +mod a { + use crate::m::TryIntoU32; + + fn main() { + // In this case, we can just use `TryIntoU32` + let _: u32 = TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod b { + use crate::m::AnotherTrick as TryIntoU32; + use crate::m::TryIntoU32 as _; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `crate::m::TryIntoU32` (with which it was imported). + let _: u32 = crate::m::TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod c { + use super::m::TryIntoU32 as _; + use crate::m::AnotherTrick as TryIntoU32; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `super::m::TryIntoU32` (with which it was imported). + let _: u32 = super::m::TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +fn main() {} diff --git a/src/test/ui/rust-2021/future-prelude-collision-imported.rs b/src/test/ui/rust-2021/future-prelude-collision-imported.rs new file mode 100644 index 0000000000..cd39eec47f --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-imported.rs @@ -0,0 +1,59 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +mod m { + pub trait TryIntoU32 { + fn try_into(self) -> Result; + } + + impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } + } + + pub trait AnotherTrick {} +} + +mod a { + use crate::m::TryIntoU32; + + fn main() { + // In this case, we can just use `TryIntoU32` + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod b { + use crate::m::AnotherTrick as TryIntoU32; + use crate::m::TryIntoU32 as _; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `crate::m::TryIntoU32` (with which it was imported). + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod c { + use super::m::TryIntoU32 as _; + use crate::m::AnotherTrick as TryIntoU32; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `super::m::TryIntoU32` (with which it was imported). + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +fn main() {} diff --git a/src/test/ui/rust-2021/future-prelude-collision-imported.stderr b/src/test/ui/rust-2021/future-prelude-collision-imported.stderr new file mode 100644 index 0000000000..6197587681 --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-imported.stderr @@ -0,0 +1,34 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-imported.rs:27:22 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)` + | +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 issue #85684 + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-imported.rs:40:22 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `crate::m::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 issue #85684 + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-imported.rs:53:22 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `super::m::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 issue #85684 + +warning: 3 warnings emitted + diff --git a/src/test/ui/rust-2021/future-prelude-collision-shadow.rs b/src/test/ui/rust-2021/future-prelude-collision-shadow.rs new file mode 100644 index 0000000000..27891a8d11 --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-shadow.rs @@ -0,0 +1,32 @@ +// edition:2018 +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +mod m { + pub trait TryIntoU32 { + fn try_into(self) -> Result; + } + + impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } + } + + pub trait AnotherTrick {} +} + +mod d { + use crate::m::AnotherTrick as TryIntoU32; + use crate::m::*; + + fn main() { + // Here, `TryIntoU32` is imported but shadowed, but in that case we don't permit its methods + // to be available. + let _: u32 = 3u8.try_into().unwrap(); + //~^ ERROR no method named `try_into` found for type `u8` in the current scope + } +} + +fn main() {} diff --git a/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr new file mode 100644 index 0000000000..ad9b8af00e --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr @@ -0,0 +1,40 @@ +error[E0599]: no method named `try_into` found for type `u8` in the current scope + --> $DIR/future-prelude-collision-shadow.rs:27:26 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^ method not found in `u8` + | + ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn try_into(self) -> Result; + | -------- + | | + | the method is available for `Box` here + | the method is available for `Pin` here + | the method is available for `Arc` here + | the method is available for `Rc` here + | + = help: items from traits can only be used if the trait is in scope + = note: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + candidate #1: `use crate::m::TryIntoU32;` + candidate #2: `use std::convert::TryInto;` +help: consider wrapping the receiver expression with the appropriate type + | +LL | let _: u32 = Box::new(3u8).try_into().unwrap(); + | ^^^^^^^^^ ^ +help: consider wrapping the receiver expression with the appropriate type + | +LL | let _: u32 = Pin::new(3u8).try_into().unwrap(); + | ^^^^^^^^^ ^ +help: consider wrapping the receiver expression with the appropriate type + | +LL | let _: u32 = Arc::new(3u8).try_into().unwrap(); + | ^^^^^^^^^ ^ +help: consider wrapping the receiver expression with the appropriate type + | +LL | let _: u32 = Rc::new(3u8).try_into().unwrap(); + | ^^^^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs b/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs new file mode 100644 index 0000000000..247d5884b8 --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision-unneeded.rs @@ -0,0 +1,60 @@ +// edition:2018 +// check-pass +#![allow(unused)] +#![deny(rust_2021_prelude_collisions)] + +struct S; + +impl S { + fn try_into(self) -> S { + S + } +} + +struct X; + +trait Hey { + fn from_iter(_: i32) -> Self; +} + +impl Hey for X { + fn from_iter(_: i32) -> Self { + X + } +} + +struct Y(T); + +impl Hey for Y { + fn from_iter(_: i32) -> Self { + Y(0) + } +} + +struct Z(T); + +impl Hey for Z { + fn from_iter(_: i32) -> Self { + Z(0) + } +} + +impl std::iter::FromIterator for Z { + fn from_iter>(_: T) -> Self { + todo!() + } +} + +fn main() { + // See https://github.com/rust-lang/rust/issues/86633 + let s = S; + let s2 = s.try_into(); + + // Check that we do not issue suggestions for types that do not implement `FromIter`. + // + // See https://github.com/rust-lang/rust/issues/86902 + X::from_iter(1); + Y::from_iter(1); + Y::::from_iter(1); + Z::::from_iter(1); +} diff --git a/src/test/ui/rust-2021/future-prelude-collision.fixed b/src/test/ui/rust-2021/future-prelude-collision.fixed new file mode 100644 index 0000000000..43b0ec1c3e --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision.fixed @@ -0,0 +1,98 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(self) -> Result; +} + +impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } +} + +// needed for autoref test +impl TryIntoU32 for &f32 { + fn try_into(self) -> Result { + Ok(*self as u32) + } +} + +trait TryFromU8: Sized { + fn try_from(x: u8) -> Result; +} + +impl TryFromU8 for u32 { + fn try_from(x: u8) -> Result { + Ok(x as u32) + } +} + +impl TryIntoU32 for *const u16 { + fn try_into(self) -> Result { + Ok(unsafe { *self } as u32) + } +} + +trait FromByteIterator { + fn from_iter(iter: T) -> Self + where + T: Iterator; +} + +impl FromByteIterator for Vec { + fn from_iter(iter: T) -> Self + where + T: Iterator, + { + iter.collect() + } +} + +fn main() { + // test dot-call that will break in 2021 edition + let _: u32 = TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test associated function call that will break in 2021 edition + let _ = ::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test reverse turbofish too + let _ = as FromByteIterator>::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter()); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // negative testing lint (this line should *not* emit a warning) + let _: u32 = TryFromU8::try_from(3u8).unwrap(); + + // test type omission + let _: u32 = <_ as TryFromU8>::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoderef + let _: u32 = TryIntoU32::try_into(*(&3u8)).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoref + let _: u32 = TryIntoU32::try_into(&3.0).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + let mut data = 3u16; + let mut_ptr = std::ptr::addr_of_mut!(data); + let _: u32 = TryIntoU32::try_into(mut_ptr as *const _).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + type U32Alias = u32; + let _ = ::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/src/test/ui/rust-2021/future-prelude-collision.rs b/src/test/ui/rust-2021/future-prelude-collision.rs new file mode 100644 index 0000000000..4c7a47ffbe --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision.rs @@ -0,0 +1,98 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(self) -> Result; +} + +impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } +} + +// needed for autoref test +impl TryIntoU32 for &f32 { + fn try_into(self) -> Result { + Ok(*self as u32) + } +} + +trait TryFromU8: Sized { + fn try_from(x: u8) -> Result; +} + +impl TryFromU8 for u32 { + fn try_from(x: u8) -> Result { + Ok(x as u32) + } +} + +impl TryIntoU32 for *const u16 { + fn try_into(self) -> Result { + Ok(unsafe { *self } as u32) + } +} + +trait FromByteIterator { + fn from_iter(iter: T) -> Self + where + T: Iterator; +} + +impl FromByteIterator for Vec { + fn from_iter(iter: T) -> Self + where + T: Iterator, + { + iter.collect() + } +} + +fn main() { + // test dot-call that will break in 2021 edition + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test associated function call that will break in 2021 edition + let _ = u32::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test reverse turbofish too + let _ = >::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter()); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // negative testing lint (this line should *not* emit a warning) + let _: u32 = TryFromU8::try_from(3u8).unwrap(); + + // test type omission + let _: u32 = <_>::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoderef + let _: u32 = (&3u8).try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoref + let _: u32 = 3.0.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + let mut data = 3u16; + let mut_ptr = std::ptr::addr_of_mut!(data); + let _: u32 = mut_ptr.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + type U32Alias = u32; + let _ = U32Alias::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/src/test/ui/rust-2021/future-prelude-collision.stderr b/src/test/ui/rust-2021/future-prelude-collision.stderr new file mode 100644 index 0000000000..03b89da00d --- /dev/null +++ b/src/test/ui/rust-2021/future-prelude-collision.stderr @@ -0,0 +1,79 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:56:18 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)` + | +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 issue #85684 + +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:61:13 + | +LL | let _ = u32::try_from(3u8).unwrap(); + | ^^^^^^^^^^^^^ help: disambiguate the associated function: `::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 issue #85684 + +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:66:13 + | +LL | let _ = >::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as FromByteIterator>::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 issue #85684 + +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:74:18 + | +LL | let _: u32 = <_>::try_from(3u8).unwrap(); + | ^^^^^^^^^^^^^ help: disambiguate the associated function: `<_ as TryFromU8>::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 issue #85684 + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:79:18 + | +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 issue #85684 + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:84:18 + | +LL | let _: u32 = 3.0.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(&3.0)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see issue #85684 + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:90:18 + | +LL | let _: u32 = mut_ptr.try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(mut_ptr as *const _)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see issue #85684 + +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:95:13 + | +LL | let _ = U32Alias::try_from(3u8).unwrap(); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `::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 issue #85684 + +warning: 8 warnings emitted + diff --git a/src/test/ui/rust-2021/generic-type-collision.fixed b/src/test/ui/rust-2021/generic-type-collision.fixed new file mode 100644 index 0000000000..feba7d19b6 --- /dev/null +++ b/src/test/ui/rust-2021/generic-type-collision.fixed @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +// edition 2018 +#![warn(rust_2021_prelude_collisions)] + +trait MyTrait { + fn from_iter(x: Option); +} + +impl MyTrait<()> for Vec { + fn from_iter(_: Option<()>) {} +} + +fn main() { + as MyTrait<_>>::from_iter(None); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/src/test/ui/rust-2021/generic-type-collision.rs b/src/test/ui/rust-2021/generic-type-collision.rs new file mode 100644 index 0000000000..335e7e520a --- /dev/null +++ b/src/test/ui/rust-2021/generic-type-collision.rs @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +// edition 2018 +#![warn(rust_2021_prelude_collisions)] + +trait MyTrait { + fn from_iter(x: Option); +} + +impl MyTrait<()> for Vec { + fn from_iter(_: Option<()>) {} +} + +fn main() { + >::from_iter(None); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/src/test/ui/rust-2021/generic-type-collision.stderr b/src/test/ui/rust-2021/generic-type-collision.stderr new file mode 100644 index 0000000000..d4999201c2 --- /dev/null +++ b/src/test/ui/rust-2021/generic-type-collision.stderr @@ -0,0 +1,16 @@ +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/generic-type-collision.rs:15:5 + | +LL | >::from_iter(None); + | ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyTrait<_>>::from_iter` + | +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 issue #85684 + +warning: 1 warning emitted + diff --git a/src/test/ui/rust-2021/inherent-dyn-collision.fixed b/src/test/ui/rust-2021/inherent-dyn-collision.fixed new file mode 100644 index 0000000000..5789a90393 --- /dev/null +++ b/src/test/ui/rust-2021/inherent-dyn-collision.fixed @@ -0,0 +1,53 @@ +// Test case where the method we want is an inherent method on a +// dyn Trait. In that case, the fix is to insert `*` on the receiver. +// +// check-pass +// run-rustfix +// edition:2018 + +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(&self) -> Result; +} + +impl TryIntoU32 for u8 { + // note: &self + fn try_into(&self) -> Result { + Ok(22) + } +} + +mod inner { + use super::get_dyn_trait; + + // note: this does nothing, but is copying from ffishim's problem of + // having a struct of the same name as the trait in-scope, while *also* + // implementing the trait for that struct but **without** importing the + // trait itself into scope + struct TryIntoU32; + + impl super::TryIntoU32 for TryIntoU32 { + fn try_into(&self) -> Result { + Ok(0) + } + } + + // this is where the gross part happens. since `get_dyn_trait` returns + // a Box, it can still call the method for `dyn Trait` without + // `Trait` being in-scope. it might even be possible to make the trait itself + // entirely unreference-able from the callsite? + pub fn test() -> u32 { + (&*get_dyn_trait()).try_into().unwrap() + //~^ WARNING trait method `try_into` will become ambiguous + //~| WARNING this is accepted in the current edition + } +} + +fn get_dyn_trait() -> Box { + Box::new(3u8) as Box +} + +fn main() { + dbg!(inner::test()); +} diff --git a/src/test/ui/rust-2021/inherent-dyn-collision.rs b/src/test/ui/rust-2021/inherent-dyn-collision.rs new file mode 100644 index 0000000000..a3893c033e --- /dev/null +++ b/src/test/ui/rust-2021/inherent-dyn-collision.rs @@ -0,0 +1,53 @@ +// Test case where the method we want is an inherent method on a +// dyn Trait. In that case, the fix is to insert `*` on the receiver. +// +// check-pass +// run-rustfix +// edition:2018 + +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(&self) -> Result; +} + +impl TryIntoU32 for u8 { + // note: &self + fn try_into(&self) -> Result { + Ok(22) + } +} + +mod inner { + use super::get_dyn_trait; + + // note: this does nothing, but is copying from ffishim's problem of + // having a struct of the same name as the trait in-scope, while *also* + // implementing the trait for that struct but **without** importing the + // trait itself into scope + struct TryIntoU32; + + impl super::TryIntoU32 for TryIntoU32 { + fn try_into(&self) -> Result { + Ok(0) + } + } + + // this is where the gross part happens. since `get_dyn_trait` returns + // a Box, it can still call the method for `dyn Trait` without + // `Trait` being in-scope. it might even be possible to make the trait itself + // entirely unreference-able from the callsite? + pub fn test() -> u32 { + get_dyn_trait().try_into().unwrap() + //~^ WARNING trait method `try_into` will become ambiguous + //~| WARNING this is accepted in the current edition + } +} + +fn get_dyn_trait() -> Box { + Box::new(3u8) as Box +} + +fn main() { + dbg!(inner::test()); +} diff --git a/src/test/ui/rust-2021/inherent-dyn-collision.stderr b/src/test/ui/rust-2021/inherent-dyn-collision.stderr new file mode 100644 index 0000000000..605f9ced9e --- /dev/null +++ b/src/test/ui/rust-2021/inherent-dyn-collision.stderr @@ -0,0 +1,16 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/inherent-dyn-collision.rs:41:9 + | +LL | get_dyn_trait().try_into().unwrap() + | ^^^^^^^^^^^^^^^ help: disambiguate the method call: `(&*get_dyn_trait())` + | +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 issue #85684 + +warning: 1 warning emitted + diff --git a/src/test/ui/rust-2021/inherent-method-collision.rs b/src/test/ui/rust-2021/inherent-method-collision.rs new file mode 100644 index 0000000000..507105207d --- /dev/null +++ b/src/test/ui/rust-2021/inherent-method-collision.rs @@ -0,0 +1,15 @@ +// Test that we do NOT warn for inherent methods invoked via `T::` form. +// +// check-pass + +#![deny(rust_2021_prelude_collisions)] + +pub struct MySeq {} + +impl MySeq { + pub fn from_iter(_: impl IntoIterator) {} +} + +fn main() { + MySeq::from_iter(Some(22)); +} diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.fixed b/src/test/ui/rust-2021/reserved-prefixes-migration.fixed new file mode 100644 index 0000000000..e026f01e93 --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes-migration.fixed @@ -0,0 +1,38 @@ +// check-pass +// run-rustfix +// compile-flags: -Z unstable-options --edition 2018 + +#![warn(rust_2021_prefixes_incompatible_syntax)] + +macro_rules! m2 { + ($a:tt $b:tt) => {}; +} + +macro_rules! m3 { + ($a:tt $b:tt $c:tt) => {}; +} + +fn main() { + m2!(z "hey"); + //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m2!(prefix "hey"); + //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey #123); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey #hey); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} + +macro_rules! quote { + (# name = # kind # value) => {}; +} + +quote! { + #name = #kind #value + //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.rs b/src/test/ui/rust-2021/reserved-prefixes-migration.rs new file mode 100644 index 0000000000..d24f296348 --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes-migration.rs @@ -0,0 +1,38 @@ +// check-pass +// run-rustfix +// compile-flags: -Z unstable-options --edition 2018 + +#![warn(rust_2021_prefixes_incompatible_syntax)] + +macro_rules! m2 { + ($a:tt $b:tt) => {}; +} + +macro_rules! m3 { + ($a:tt $b:tt $c:tt) => {}; +} + +fn main() { + m2!(z"hey"); + //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m2!(prefix"hey"); + //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey#123); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey#hey); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} + +macro_rules! quote { + (# name = # kind # value) => {}; +} + +quote! { + #name = #kind#value + //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.stderr b/src/test/ui/rust-2021/reserved-prefixes-migration.stderr new file mode 100644 index 0000000000..95105f932d --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes-migration.stderr @@ -0,0 +1,72 @@ +warning: prefix `z` is unknown + --> $DIR/reserved-prefixes-migration.rs:16:9 + | +LL | m2!(z"hey"); + | ^ unknown prefix + | +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 issue #84978 +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m2!(z "hey"); + | -- + +warning: prefix `prefix` is unknown + --> $DIR/reserved-prefixes-migration.rs:19:9 + | +LL | m2!(prefix"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 issue #84978 +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m2!(prefix "hey"); + | -- + +warning: prefix `hey` is unknown + --> $DIR/reserved-prefixes-migration.rs:22:9 + | +LL | m3!(hey#123); + | ^^^ 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 issue #84978 +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m3!(hey #123); + | -- + +warning: prefix `hey` is unknown + --> $DIR/reserved-prefixes-migration.rs:25:9 + | +LL | m3!(hey#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 issue #84978 +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m3!(hey #hey); + | -- + +warning: prefix `kind` is unknown + --> $DIR/reserved-prefixes-migration.rs:35:14 + | +LL | #name = #kind#value + | ^^^^ 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 issue #84978 +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | #name = #kind #value + | -- + +warning: 5 warnings emitted + diff --git a/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.rs b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.rs new file mode 100644 index 0000000000..74f2066061 --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.rs @@ -0,0 +1,21 @@ +// edition:2018 +// aux-build:reserved-prefixes-macro-2018.rs +// aux-build:reserved-prefixes-macro-2021.rs + +extern crate reserved_prefixes_macro_2018 as m2018; +extern crate reserved_prefixes_macro_2021 as m2021; + +fn main() { + // Ok: + m2018::number_of_tokens_in_a_prefixed_integer_literal!(); + m2018::number_of_tokens_in_a_prefixed_char_literal!(); + m2018::number_of_tokens_in_a_prefixed_string_literal!(); + + // Error, even though *this* crate is 2018: + m2021::number_of_tokens_in_a_prefixed_integer_literal!(); + //~^ ERROR prefix `hey` is unknown + m2021::number_of_tokens_in_a_prefixed_char_literal!(); + //~^ ERROR prefix `hey` is unknown + m2021::number_of_tokens_in_a_prefixed_string_literal!(); + //~^ ERROR prefix `hey` is unknown +} diff --git a/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr new file mode 100644 index 0000000000..9d7ca570c4 --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr @@ -0,0 +1,29 @@ +error: prefix `hey` is unknown + --> $DIR/reserved-prefixes-via-macro-2.rs:15:5 + | +LL | m2021::number_of_tokens_in_a_prefixed_integer_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 + = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_integer_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: prefix `hey` is unknown + --> $DIR/reserved-prefixes-via-macro-2.rs:17:5 + | +LL | m2021::number_of_tokens_in_a_prefixed_char_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 + = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_char_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: prefix `hey` is unknown + --> $DIR/reserved-prefixes-via-macro-2.rs:19:5 + | +LL | m2021::number_of_tokens_in_a_prefixed_string_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 + = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/rust-2021/reserved-prefixes-via-macro.rs b/src/test/ui/rust-2021/reserved-prefixes-via-macro.rs new file mode 100644 index 0000000000..110b6d64cc --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes-via-macro.rs @@ -0,0 +1,12 @@ +// run-pass +// edition:2021 +// aux-build:reserved-prefixes-macro-2018.rs + +extern crate reserved_prefixes_macro_2018 as m2018; + +fn main() { + // Ok, even though *this* crate is 2021: + assert_eq!(m2018::number_of_tokens_in_a_prefixed_integer_literal!(), 3); + assert_eq!(m2018::number_of_tokens_in_a_prefixed_char_literal!(), 3); + assert_eq!(m2018::number_of_tokens_in_a_prefixed_string_literal!(), 3); +} diff --git a/src/test/ui/rust-2021/reserved-prefixes.rs b/src/test/ui/rust-2021/reserved-prefixes.rs new file mode 100644 index 0000000000..5882c7d83d --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes.rs @@ -0,0 +1,36 @@ +// compile-flags: -Z unstable-options --edition 2021 + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +fn main() { + demo3!(foo#bar); //~ ERROR prefix `foo` is unknown + demo2!(foo"bar"); //~ ERROR prefix `foo` is unknown + demo2!(foo'b'); //~ ERROR prefix `foo` is unknown + + demo2!(foo'b); //~ ERROR prefix `foo` is unknown + demo3!(foo# bar); //~ ERROR prefix `foo` is unknown + demo4!(foo#! bar); //~ ERROR prefix `foo` is unknown + demo4!(foo## bar); //~ ERROR prefix `foo` is unknown + + demo4!(foo#bar#); + //~^ ERROR prefix `foo` is unknown + //~| ERROR prefix `bar` is unknown + + demo3!(foo # bar); + demo3!(foo #bar); + demo4!(foo!#bar); + demo4!(foo ##bar); + + demo3!(r"foo"#bar); + demo3!(r#foo#bar); +} diff --git a/src/test/ui/rust-2021/reserved-prefixes.stderr b/src/test/ui/rust-2021/reserved-prefixes.stderr new file mode 100644 index 0000000000..32e1856332 --- /dev/null +++ b/src/test/ui/rust-2021/reserved-prefixes.stderr @@ -0,0 +1,110 @@ +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:16:12 + | +LL | demo3!(foo#bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo3!(foo #bar); + | -- + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:17:12 + | +LL | demo2!(foo"bar"); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(foo "bar"); + | -- + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:18:12 + | +LL | demo2!(foo'b'); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(foo 'b'); + | -- + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:20:12 + | +LL | demo2!(foo'b); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(foo 'b); + | -- + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:21:12 + | +LL | demo3!(foo# bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo3!(foo # bar); + | -- + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:22:12 + | +LL | demo4!(foo#! bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo #! bar); + | -- + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:23:12 + | +LL | demo4!(foo## bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo ## bar); + | -- + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:25:12 + | +LL | demo4!(foo#bar#); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo #bar#); + | -- + +error: prefix `bar` is unknown + --> $DIR/reserved-prefixes.rs:25:16 + | +LL | demo4!(foo#bar#); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo#bar #); + | -- + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/rustdoc/check-doc-alias-attr-location.rs b/src/test/ui/rustdoc/check-doc-alias-attr-location.rs index 007d2ae650..4738e5116b 100644 --- a/src/test/ui/rustdoc/check-doc-alias-attr-location.rs +++ b/src/test/ui/rustdoc/check-doc-alias-attr-location.rs @@ -1,9 +1,9 @@ -#![crate_type="lib"] +#![crate_type = "lib"] pub struct Bar; pub trait Foo { type X; - fn foo() -> Self::X; + fn foo(x: u32) -> Self::X; } #[doc(alias = "foo")] //~ ERROR @@ -19,7 +19,8 @@ impl Bar { impl Foo for Bar { #[doc(alias = "assoc")] //~ ERROR type X = i32; - fn foo() -> Self::X { + fn foo(#[doc(alias = "qux")] _x: u32) -> Self::X { + //~^ ERROR 0 } } diff --git a/src/test/ui/rustdoc/check-doc-alias-attr-location.stderr b/src/test/ui/rustdoc/check-doc-alias-attr-location.stderr index a66e9939ea..2b25882be2 100644 --- a/src/test/ui/rustdoc/check-doc-alias-attr-location.stderr +++ b/src/test/ui/rustdoc/check-doc-alias-attr-location.stderr @@ -1,3 +1,9 @@ +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/check-doc-alias-attr-location.rs:22:12 + | +LL | fn foo(#[doc(alias = "qux")] _x: u32) -> Self::X { + | ^^^^^^^^^^^^^^^^^^^^^ + error: `#[doc(alias = "...")]` isn't allowed on extern block --> $DIR/check-doc-alias-attr-location.rs:9:7 | @@ -22,5 +28,5 @@ error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation blo LL | #[doc(alias = "assoc")] | ^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/rustdoc/doc_keyword.rs b/src/test/ui/rustdoc/doc_keyword.rs index 4c72e7e968..4518f77ef9 100644 --- a/src/test/ui/rustdoc/doc_keyword.rs +++ b/src/test/ui/rustdoc/doc_keyword.rs @@ -10,3 +10,11 @@ mod foo { #[doc(keyword = "hall")] //~ ERROR fn foo() {} + + +// Regression test for the ICE described in #83512. +trait Foo { + #[doc(keyword = "match")] + //~^ ERROR: `#[doc(keyword = "...")]` can only be used on modules + fn quux() {} +} diff --git a/src/test/ui/rustdoc/doc_keyword.stderr b/src/test/ui/rustdoc/doc_keyword.stderr index 0679bb8c5a..6ba7034d54 100644 --- a/src/test/ui/rustdoc/doc_keyword.stderr +++ b/src/test/ui/rustdoc/doc_keyword.stderr @@ -10,11 +10,17 @@ error: `#[doc(keyword = "...")]` can only be used on modules LL | #[doc(keyword = "hall")] | ^^^^^^^^^^^^^^^^ +error: `#[doc(keyword = "...")]` can only be used on modules + --> $DIR/doc_keyword.rs:17:11 + | +LL | #[doc(keyword = "match")] + | ^^^^^^^^^^^^^^^^^ + error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc_keyword.rs:4:8 | LL | #![doc(keyword = "hello")] | ^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/sanitize/crt-static.rs b/src/test/ui/sanitize/crt-static.rs index f5dd2a40cc..7a6b9eda3f 100644 --- a/src/test/ui/sanitize/crt-static.rs +++ b/src/test/ui/sanitize/crt-static.rs @@ -1,4 +1,5 @@ // compile-flags: -Z sanitizer=address -C target-feature=+crt-static --target x86_64-unknown-linux-gnu +// needs-llvm-components: x86 #![feature(no_core)] #![no_core] diff --git a/src/test/ui/sanitize/incompatible.rs b/src/test/ui/sanitize/incompatible.rs index 4947f3b3d8..bcafc2891f 100644 --- a/src/test/ui/sanitize/incompatible.rs +++ b/src/test/ui/sanitize/incompatible.rs @@ -1,4 +1,5 @@ // compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu +// needs-llvm-components: x86 // error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` #![feature(no_core)] diff --git a/src/test/ui/sanitize/unsupported-target.rs b/src/test/ui/sanitize/unsupported-target.rs index 3fb749815f..9f29c76353 100644 --- a/src/test/ui/sanitize/unsupported-target.rs +++ b/src/test/ui/sanitize/unsupported-target.rs @@ -1,4 +1,5 @@ // compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu +// needs-llvm-components: x86 // error-pattern: error: leak sanitizer is not supported for this target #![feature(no_core)] #![no_core] diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr index f2e556c63c..e25c636351 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr @@ -1,15 +1,15 @@ error: lifetime may not live long enough - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:37 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | - ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | - ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` | | | let's call the lifetime of this reference `'1` | help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound | LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr index 73766c31b9..962593e411 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr @@ -9,7 +9,7 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self } help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/self/self-infer.rs b/src/test/ui/self/self-infer.rs index 0956f2a569..cc17d8f8e3 100644 --- a/src/test/ui/self/self-infer.rs +++ b/src/test/ui/self/self-infer.rs @@ -1,8 +1,8 @@ struct S; impl S { - fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item sig - fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item sig + fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions + fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item signatures for functions } fn main() {} diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index 1475b212b5..8d70c6287e 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/self-infer.rs:4:16 | LL | fn f(self: _) {} @@ -9,7 +9,7 @@ help: use type parameters instead LL | fn f(self: T) {} | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/self-infer.rs:5:17 | LL | fn g(self: &_) {} diff --git a/src/test/ui/self/self-re-assign.rs b/src/test/ui/self/self-re-assign.rs index a7b089ebff..88e8614683 100644 --- a/src/test/ui/self/self-re-assign.rs +++ b/src/test/ui/self/self-re-assign.rs @@ -3,6 +3,7 @@ // that we do not glue_drop before we glue_take (#3290). #![feature(box_syntax)] +#![allow(dead_code)] use std::rc::Rc; diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd-intrinsic/issue-85855.rs new file mode 100644 index 0000000000..f276fbd669 --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.rs @@ -0,0 +1,19 @@ +// Check that appropriate errors are reported if an intrinsic is defined +// with the wrong number of generic lifetime/type/const parameters, and +// that no ICE occurs in these cases. + +#![feature(platform_intrinsics)] +#![crate_type="lib"] + +extern "platform-intrinsic" { + fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of lifetime parameters + + fn simd_add<'a, T>(x: T, y: T) -> T; + + fn simd_sub(x: T, y: U); + //~^ ERROR: intrinsic has wrong number of type parameters + + fn simd_mul(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of const parameters +} diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd-intrinsic/issue-85855.stderr new file mode 100644 index 0000000000..fb2f1fbc5b --- /dev/null +++ b/src/test/ui/simd-intrinsic/issue-85855.stderr @@ -0,0 +1,21 @@ +error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:9:27 + | +LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + | ^^^^^^^^^^^ expected 0 lifetime parameters + +error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 + --> $DIR/issue-85855.rs:14:16 + | +LL | fn simd_sub(x: T, y: U); + | ^^^^^^ expected 1 type parameter + +error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:17:16 + | +LL | fn simd_mul(x: T, y: T); + | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0094`. diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr index 723c4a7a1f..b251e8a438 100644 --- a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr +++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr @@ -1,11 +1,11 @@ -error: lifetime parameter `'b` only used once - --> $DIR/one-use-in-fn-argument-in-band.rs:11:22 +error: lifetime parameter `'a` only used once + --> $DIR/one-use-in-fn-argument-in-band.rs:11:10 | LL | fn a(x: &'a u32, y: &'b u32) { - | ^^- - | | - | this lifetime is only used here - | help: elide the single-use lifetime + | ^^- + | | + | this lifetime is only used here + | help: elide the single-use lifetime | note: the lint level is defined here --> $DIR/one-use-in-fn-argument-in-band.rs:4:9 @@ -13,14 +13,14 @@ note: the lint level is defined here LL | #![deny(single_use_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^ -error: lifetime parameter `'a` only used once - --> $DIR/one-use-in-fn-argument-in-band.rs:11:10 +error: lifetime parameter `'b` only used once + --> $DIR/one-use-in-fn-argument-in-band.rs:11:22 | LL | fn a(x: &'a u32, y: &'b u32) { - | ^^- - | | - | this lifetime is only used here - | help: elide the single-use lifetime + | ^^- + | | + | this lifetime is only used here + | help: elide the single-use lifetime error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 1d3e33e4b0..24dfdf8ebc 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -1,11 +1,14 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied --> $DIR/issue-29595.rs:6:17 | -LL | const C: Self; - | -------------- required by `Tr::C` -... LL | let a: u8 = Tr::C; | ^^^^^ the trait `Tr` is not implemented for `u8` + | +note: required by `Tr::C` + --> $DIR/issue-29595.rs:2:5 + | +LL | const C: Self; + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/span/missing-unit-argument.rs b/src/test/ui/span/missing-unit-argument.rs index b8fb332120..5b9861da6e 100644 --- a/src/test/ui/span/missing-unit-argument.rs +++ b/src/test/ui/span/missing-unit-argument.rs @@ -8,7 +8,7 @@ impl S { } fn main() { - let _: Result<(), String> = Ok(); //~ ERROR this function takes + let _: Result<(), String> = Ok(); //~ ERROR this enum variant takes foo(); //~ ERROR this function takes foo(()); //~ ERROR this function takes bar(); //~ ERROR this function takes diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index b15da2cb47..7a24ffbd81 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -1,4 +1,4 @@ -error[E0061]: this function takes 1 argument but 0 arguments were supplied +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:11:33 | LL | let _: Result<(), String> = Ok(); diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs index f14588e6e0..0f5714e996 100644 --- a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs @@ -3,7 +3,6 @@ #![feature(specialization)] #![feature(generic_associated_types)] //~^^ WARNING `specialization` is incomplete -//~^^ WARNING the feature `generic_associated_types` is incomplete trait X { type U<'a>: PartialEq<&'a Self> where Self: 'a; diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr index eb5d80bc4d..e646c1640b 100644 --- a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr @@ -8,16 +8,8 @@ LL | #![feature(specialization)] = note: see issue #31844 for more information = help: consider using `min_specialization` instead, which is more stable and complete -warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/deafult-generic-associated-type-bound.rs:4:12 - | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #44265 for more information - error[E0277]: can't compare `T` with `T` - --> $DIR/deafult-generic-associated-type-bound.rs:19:5 + --> $DIR/deafult-generic-associated-type-bound.rs:18:5 | LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; | ------------------- required by this bound in `X::U` @@ -31,6 +23,6 @@ help: consider further restricting this bound LL | impl X for T { | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr index fa59d7a031..d2eea15f39 100644 --- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -1,4 +1,4 @@ -error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])` +error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[b09c]::Id::This) }, (I,)), [])` --> $DIR/repeated_projection_type.rs:19:1 | LL | / impl> X for V { diff --git a/src/test/ui/stability-attribute/generics-default-stability.stderr b/src/test/ui/stability-attribute/generics-default-stability.stderr index 99523f8eb6..bc59844f77 100644 --- a/src/test/ui/stability-attribute/generics-default-stability.stderr +++ b/src/test/ui/stability-attribute/generics-default-stability.stderr @@ -34,7 +34,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct4`: test --> $DIR/generics-default-stability.rs:83:12 | LL | let _: Struct4 = Struct4 { field: 1 }; - | ^^^^^^^^^^^^^^ + | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct4`: test --> $DIR/generics-default-stability.rs:88:12 @@ -46,7 +46,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct4`: test --> $DIR/generics-default-stability.rs:89:12 | LL | let _: Struct4 = STRUCT4; - | ^^^^^^^^^^^^^^ + | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct4`: test --> $DIR/generics-default-stability.rs:90:29 @@ -58,7 +58,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct4`: test --> $DIR/generics-default-stability.rs:90:12 | LL | let _: Struct4 = Struct4 { field: 0 }; - | ^^^^^^^^^^^^^^ + | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct5`: test --> $DIR/generics-default-stability.rs:96:29 @@ -70,7 +70,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct5`: test --> $DIR/generics-default-stability.rs:96:12 | LL | let _: Struct5 = Struct5 { field: 1 }; - | ^^^^^^^^^^^^^^ + | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct5`: test --> $DIR/generics-default-stability.rs:101:12 @@ -82,7 +82,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct5`: test --> $DIR/generics-default-stability.rs:102:12 | LL | let _: Struct5 = STRUCT5; - | ^^^^^^^^^^^^^^ + | ^^^^^^^ warning: use of deprecated struct `unstable_generic_param::Struct5`: test --> $DIR/generics-default-stability.rs:104:29 @@ -94,7 +94,7 @@ warning: use of deprecated struct `unstable_generic_param::Struct5`: test --> $DIR/generics-default-stability.rs:104:12 | LL | let _: Struct5 = Struct5 { field: 0 }; - | ^^^^^^^^^^^^^^ + | ^^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test --> $DIR/generics-default-stability.rs:159:28 @@ -106,7 +106,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test --> $DIR/generics-default-stability.rs:159:12 | LL | let _: Alias4 = Alias4::Some(1); - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test --> $DIR/generics-default-stability.rs:163:12 @@ -118,7 +118,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test --> $DIR/generics-default-stability.rs:164:12 | LL | let _: Alias4 = ALIAS4; - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test --> $DIR/generics-default-stability.rs:165:28 @@ -130,7 +130,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias4`: test --> $DIR/generics-default-stability.rs:165:12 | LL | let _: Alias4 = Alias4::Some(0); - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test --> $DIR/generics-default-stability.rs:170:28 @@ -142,7 +142,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test --> $DIR/generics-default-stability.rs:170:12 | LL | let _: Alias5 = Alias5::Some(1); - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test --> $DIR/generics-default-stability.rs:174:12 @@ -154,7 +154,7 @@ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test --> $DIR/generics-default-stability.rs:175:12 | LL | let _: Alias5 = ALIAS5; - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test --> $DIR/generics-default-stability.rs:177:28 @@ -166,19 +166,19 @@ warning: use of deprecated type alias `unstable_generic_param::Alias5`: test --> $DIR/generics-default-stability.rs:177:12 | LL | let _: Alias5 = Alias5::Some(0); - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test - --> $DIR/generics-default-stability.rs:231:27 + --> $DIR/generics-default-stability.rs:231:34 | LL | let _: Enum4 = Enum4::Some(1); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test --> $DIR/generics-default-stability.rs:231:12 | LL | let _: Enum4 = Enum4::Some(1); - | ^^^^^^^^^^^^ + | ^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test --> $DIR/generics-default-stability.rs:235:12 @@ -190,31 +190,31 @@ warning: use of deprecated enum `unstable_generic_param::Enum4`: test --> $DIR/generics-default-stability.rs:236:12 | LL | let _: Enum4 = ENUM4; - | ^^^^^^^^^^^^ + | ^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test - --> $DIR/generics-default-stability.rs:237:27 + --> $DIR/generics-default-stability.rs:237:34 | LL | let _: Enum4 = Enum4::Some(0); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum4`: test --> $DIR/generics-default-stability.rs:237:12 | LL | let _: Enum4 = Enum4::Some(0); - | ^^^^^^^^^^^^ + | ^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test - --> $DIR/generics-default-stability.rs:242:27 + --> $DIR/generics-default-stability.rs:242:34 | LL | let _: Enum5 = Enum5::Some(1); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test --> $DIR/generics-default-stability.rs:242:12 | LL | let _: Enum5 = Enum5::Some(1); - | ^^^^^^^^^^^^ + | ^^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test --> $DIR/generics-default-stability.rs:246:12 @@ -226,19 +226,19 @@ warning: use of deprecated enum `unstable_generic_param::Enum5`: test --> $DIR/generics-default-stability.rs:247:12 | LL | let _: Enum5 = ENUM5; - | ^^^^^^^^^^^^ + | ^^^^^ warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test - --> $DIR/generics-default-stability.rs:249:27 + --> $DIR/generics-default-stability.rs:249:34 | LL | let _: Enum5 = Enum5::Some(0); - | ^^^^^^^^^^^ + | ^^^^ warning: use of deprecated enum `unstable_generic_param::Enum5`: test --> $DIR/generics-default-stability.rs:249:12 | LL | let _: Enum5 = Enum5::Some(0); - | ^^^^^^^^^^^^ + | ^^^^^ error[E0658]: use of unstable library feature 'unstable_default' --> $DIR/generics-default-stability.rs:35:20 diff --git a/src/test/ui/static/static-method-privacy.stderr b/src/test/ui/static/static-method-privacy.stderr index 569608780d..4be1b22fc6 100644 --- a/src/test/ui/static/static-method-privacy.stderr +++ b/src/test/ui/static/static-method-privacy.stderr @@ -1,6 +1,9 @@ error[E0624]: associated function `new` is private --> $DIR/static-method-privacy.rs:9:19 | +LL | fn new() -> S { S } + | ------------- private associated function defined here +... LL | let _ = a::S::new(); | ^^^ private associated function diff --git a/src/test/ui/structs/struct-path-alias-bounds.stderr b/src/test/ui/structs/struct-path-alias-bounds.stderr index cea3d5d4df..e0a22c2df1 100644 --- a/src/test/ui/structs/struct-path-alias-bounds.stderr +++ b/src/test/ui/structs/struct-path-alias-bounds.stderr @@ -1,11 +1,14 @@ error[E0277]: the trait bound `NoClone: Clone` is not satisfied --> $DIR/struct-path-alias-bounds.rs:9:13 | -LL | struct S { a: T } - | ------------------ required by `S` -... LL | let s = A { a: NoClone }; | ^ the trait `Clone` is not implemented for `NoClone` + | +note: required by `S` + --> $DIR/struct-path-alias-bounds.rs:3:1 + | +LL | struct S { a: T } + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs index 2ffb24c6e6..6f46cfdf02 100644 --- a/src/test/ui/suggestions/const-no-type.rs +++ b/src/test/ui/suggestions/const-no-type.rs @@ -32,20 +32,20 @@ static mut SM2 = "abc"; const C = 42; //~^ ERROR missing type for `const` item -//~| HELP provide a type for the item +//~| HELP provide a type for the constant //~| SUGGESTION C: i32 const D = &&42; //~^ ERROR missing type for `const` item -//~| HELP provide a type for the item +//~| HELP provide a type for the constant //~| SUGGESTION D: &&i32 static S = Vec::::new(); //~^ ERROR missing type for `static` item -//~| HELP provide a type for the item +//~| HELP provide a type for the static variable //~| SUGGESTION S: Vec static mut SM = "abc"; //~^ ERROR missing type for `static mut` item -//~| HELP provide a type for the item +//~| HELP provide a type for the static variable //~| SUGGESTION &str diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr index b180a6a9a9..3b0fd6337f 100644 --- a/src/test/ui/suggestions/const-no-type.stderr +++ b/src/test/ui/suggestions/const-no-type.stderr @@ -2,25 +2,25 @@ error: missing type for `const` item --> $DIR/const-no-type.rs:33:7 | LL | const C = 42; - | ^ help: provide a type for the item: `C: i32` + | ^ help: provide a type for the constant: `C: i32` error: missing type for `const` item --> $DIR/const-no-type.rs:38:7 | LL | const D = &&42; - | ^ help: provide a type for the item: `D: &&i32` + | ^ help: provide a type for the constant: `D: &&i32` error: missing type for `static` item --> $DIR/const-no-type.rs:43:8 | LL | static S = Vec::::new(); - | ^ help: provide a type for the item: `S: Vec` + | ^ help: provide a type for the static variable: `S: Vec` error: missing type for `static mut` item --> $DIR/const-no-type.rs:48:12 | LL | static mut SM = "abc"; - | ^^ help: provide a type for the item: `SM: &str` + | ^^ help: provide a type for the static variable: `SM: &str` error: missing type for `const` item --> $DIR/const-no-type.rs:14:7 diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 3786457fb1..d5d51324e6 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -47,7 +47,11 @@ LL | Pin::new(x) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` | = note: consider using `Box::pin` - = note: required by `Pin::

::new` +note: required by `Pin::

::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + | +LL | pub const fn new(pointer: P) -> Pin

{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn Future + Send` cannot be unpinned --> $DIR/expected-boxed-future-isnt-pinned.rs:27:5 @@ -56,7 +60,11 @@ LL | Pin::new(Box::new(x)) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` | = note: consider using `Box::pin` - = note: required by `Pin::

::new` +note: required by `Pin::

::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + | +LL | pub const fn new(pointer: P) -> Pin

{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/expected-boxed-future-isnt-pinned.rs:31:5 diff --git a/src/test/ui/suggestions/issue-61963.rs b/src/test/ui/suggestions/issue-61963.rs index b5c379ebc6..d31ed01b19 100644 --- a/src/test/ui/suggestions/issue-61963.rs +++ b/src/test/ui/suggestions/issue-61963.rs @@ -17,11 +17,11 @@ pub struct Qux(T); #[dom_struct] pub struct Foo { //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition qux: Qux>, bar: Box, //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition } fn main() {} diff --git a/src/test/ui/suggestions/issue-61963.stderr b/src/test/ui/suggestions/issue-61963.stderr index f8c58b6173..6282a69385 100644 --- a/src/test/ui/suggestions/issue-61963.stderr +++ b/src/test/ui/suggestions/issue-61963.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: trait objects without an explicit `dyn` are deprecated @@ -18,7 +18,7 @@ error: trait objects without an explicit `dyn` are deprecated LL | pub struct Foo { | ^^^ help: use `dyn`: `dyn pub` | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-68049-1.stderr b/src/test/ui/suggestions/issue-68049-1.stderr index 32367d2d0c..7f931f0cdc 100644 --- a/src/test/ui/suggestions/issue-68049-1.stderr +++ b/src/test/ui/suggestions/issue-68049-1.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `self.0` which is behind a `&` reference +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference --> $DIR/issue-68049-1.rs:7:9 | LL | self.0 += 1; diff --git a/src/test/ui/suggestions/issue-68049-2.stderr b/src/test/ui/suggestions/issue-68049-2.stderr index f10a83c68a..2f31193e4a 100644 --- a/src/test/ui/suggestions/issue-68049-2.stderr +++ b/src/test/ui/suggestions/issue-68049-2.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `*input` which is behind a `&` reference +error[E0594]: cannot assign to `*input`, which is behind a `&` reference --> $DIR/issue-68049-2.rs:9:7 | LL | fn example(&self, input: &i32); // should suggest here @@ -7,7 +7,7 @@ LL | fn example(&self, input: &i32); // should suggest here LL | *input = self.0; | ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `self.0` which is behind a `&` reference +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference --> $DIR/issue-68049-2.rs:17:5 | LL | fn example(&self, input: &i32); // should suggest here diff --git a/src/test/ui/suggestions/issue-72766.stderr b/src/test/ui/suggestions/issue-72766.stderr index eb67170d47..fcc49ef59d 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -5,7 +5,11 @@ LL | SadGirl {}.call()?; | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future` | = help: the trait `Try` is not implemented for `impl Future` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `await`ing on the `Future` | LL | SadGirl {}.call().await?; diff --git a/src/test/ui/suggestions/issue-84973.stderr b/src/test/ui/suggestions/issue-84973.stderr index 49fa94da85..649517b7d9 100644 --- a/src/test/ui/suggestions/issue-84973.stderr +++ b/src/test/ui/suggestions/issue-84973.stderr @@ -6,9 +6,12 @@ LL | let o = Other::new(f); | | | expected an implementor of trait `SomeTrait` | help: consider borrowing here: `&f` -... + | +note: required by `Other::<'a, G>::new` + --> $DIR/issue-84973.rs:27:5 + | LL | pub fn new(g: G) -> Self { - | ------------------------ required by `Other::<'a, G>::new` + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-86667.rs b/src/test/ui/suggestions/issue-86667.rs new file mode 100644 index 0000000000..6aceb13746 --- /dev/null +++ b/src/test/ui/suggestions/issue-86667.rs @@ -0,0 +1,16 @@ +// Regression test for #86667, where a garbled suggestion was issued for +// a missing named lifetime parameter. + +// compile-flags: --edition 2018 + +async fn a(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +} + +fn b(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr new file mode 100644 index 0000000000..77f7f874a4 --- /dev/null +++ b/src/test/ui/suggestions/issue-86667.stderr @@ -0,0 +1,27 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:6:35 + | +LL | async fn a(s1: &str, s2: &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 `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:11:29 + | +LL | fn b(s1: &str, s2: &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 `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr index 2407d13714..05ba780860 100644 --- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.nll.stderr @@ -9,7 +9,7 @@ LL | fn iter(&self) -> impl Iterator> { help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound | LL | fn iter(&self) -> impl Iterator> + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: lifetime may not live long enough --> $DIR/trait-object-nested-in-impl-trait.rs:39:9 @@ -47,7 +47,7 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> { help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 71b09d4361..4d1b5306bb 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -5,7 +5,11 @@ LL | let fp = BufWriter::new(fp); | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` | = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` - = note: required by `BufWriter::::new` +note: required by `BufWriter::::new` + --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + | +LL | pub fn new(inner: W) -> BufWriter { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied --> $DIR/mut-borrow-needed-by-trait.rs:17:14 diff --git a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr index 797406f869..f332b7213d 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr +++ b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:6:11 + --> $DIR/object-unsafe-trait-references-self.rs:6:12 | LL | fn bar(x: &dyn Trait) {} - | ^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` cannot be made into an object | = help: consider moving `baz` to another trait = help: consider moving `bat` to another trait @@ -17,10 +17,10 @@ LL | fn bat(&self) -> Self {} | ^^^^ ...because method `bat` references the `Self` type in its return type error[E0038]: the trait `Other` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:10:11 + --> $DIR/object-unsafe-trait-references-self.rs:10:12 | LL | fn foo(x: &dyn Other) {} - | ^^^^^^^^^^ `Other` cannot be made into an object + | ^^^^^^^^^ `Other` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-unsafe-trait-references-self.rs:8:14 diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr index a2caf846cc..4c18f6d79d 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:11 + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12 | LL | fn bar(x: &dyn Trait) {} - | ^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8 diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr index 80ed1cdedf..25c73c4c87 100644 --- a/src/test/ui/suggestions/path-display.stderr +++ b/src/test/ui/suggestions/path-display.stderr @@ -6,8 +6,6 @@ LL | println!("{}", path); | = help: the trait `std::fmt::Display` is not implemented for `Path` = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data - = note: required because of the requirements on the impl of `std::fmt::Display` for `&Path` - = note: required by `std::fmt::Display::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-change-mut.stderr b/src/test/ui/suggestions/suggest-change-mut.stderr index 9b8181647a..e68152d5fc 100644 --- a/src/test/ui/suggestions/suggest-change-mut.stderr +++ b/src/test/ui/suggestions/suggest-change-mut.stderr @@ -4,7 +4,11 @@ error[E0277]: the trait bound `&T: std::io::Read` is not satisfied LL | let mut stream_reader = BufReader::new(&stream); | ^^^^^^^ the trait `std::io::Read` is not implemented for `&T` | - = note: required by `BufReader::::new` +note: required by `BufReader::::new` + --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL + | +LL | pub fn new(inner: R) -> BufReader { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the leading `&`-reference | LL | let mut stream_reader = BufReader::new(stream); diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs new file mode 100644 index 0000000000..1dfc078666 --- /dev/null +++ b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs @@ -0,0 +1,10 @@ +mod option { + pub enum O { + Some(T), + None, + } +} + +fn main() { + let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308] +} diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr new file mode 100644 index 0000000000..22a0ce1e91 --- /dev/null +++ b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28 + | +LL | let _: option::O<()> = (); + | ------------- ^^ + | | | + | | expected enum `O`, found `()` + | | help: try using a variant of the expected enum: `option::O::Some(())` + | expected due to this + | + = note: expected enum `O<()>` + 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/suggestions/suggest-mut-method-for-loop.stderr b/src/test/ui/suggestions/suggest-mut-method-for-loop.stderr index 6ab0819744..3eb9e1031d 100644 --- a/src/test/ui/suggestions/suggest-mut-method-for-loop.stderr +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `t.v` which is behind a `&` reference +error[E0594]: cannot assign to `t.v`, which is behind a `&` reference --> $DIR/suggest-mut-method-for-loop.rs:14:9 | LL | for mut t in buzz.values() { diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr index b4981279a2..9fd2658ec7 100644 --- a/src/test/ui/suggestions/suggest-ref-mut.stderr +++ b/src/test/ui/suggestions/suggest-ref-mut.stderr @@ -1,4 +1,4 @@ -error[E0594]: cannot assign to `self.0` which is behind a `&` reference +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:7:9 | LL | fn zap(&self) { @@ -7,7 +7,7 @@ LL | fn zap(&self) { LL | self.0 = 32; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*foo` which is behind a `&` reference +error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:16:5 | LL | let ref foo = 16; @@ -16,7 +16,7 @@ LL | let ref foo = 16; LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*bar` which is behind a `&` reference +error[E0594]: cannot assign to `*bar`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:21:9 | LL | if let Some(ref bar) = Some(16) { @@ -25,7 +25,7 @@ LL | if let Some(ref bar) = Some(16) { LL | *bar = 32; | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written -error[E0594]: cannot assign to `*quo` which is behind a `&` reference +error[E0594]: cannot assign to `*quo`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:25:22 | LL | ref quo => { *quo = 32; }, diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index 4aa0ad219c..a5c01484d4 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -9,7 +9,11 @@ LL | for (i, _) in &v.iter().enumerate() { | = help: the trait `Iterator` is not implemented for `&Enumerate>` = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate>` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.stderr b/src/test/ui/suggestions/suggest-remove-refs-2.stderr index 15c4b7fcb8..b128590f9d 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-2.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-2.stderr @@ -9,7 +9,11 @@ LL | for (i, _) in & & & & &v.iter().enumerate() { | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate>` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr index 0bd6d956af..1c32a33e37 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr @@ -13,7 +13,11 @@ LL | | .enumerate() { | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate>` - = note: required by `into_iter` +note: required by `into_iter` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs new file mode 100644 index 0000000000..f882a159f9 --- /dev/null +++ b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs @@ -0,0 +1,27 @@ +// Regression test for #87051, where a double semicolon was erroneously +// suggested after a `?` operator. + +fn main() -> Result<(), ()> { + a(|| { + b() + //~^ ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found `i32` + //~| HELP: consider using a semicolon here + })?; + + // Here, we do want to suggest a semicolon: + let x = Ok(42); + if true { + //~^ NOTE: expected this to be `()` + x? + //~^ ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found integer + //~| HELP: consider using a semicolon here + } + //~^ HELP: consider using a semicolon here + + Ok(()) +} + +fn a(f: F) -> Result<(), ()> where F: FnMut() { Ok(()) } +fn b() -> i32 { 42 } diff --git a/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr new file mode 100644 index 0000000000..4f7e18742e --- /dev/null +++ b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9 + | +LL | b() + | ^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `i32` + +error[E0308]: mismatched types + --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9 + | +LL | / if true { +LL | | +LL | | x? + | | ^^ expected `()`, found integer +LL | | +LL | | +LL | | +LL | | } + | |_____- expected this to be `()` + | +help: consider using a semicolon here + | +LL | x?; + | ^ +help: consider using a semicolon here + | +LL | }; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/unnamable-types.rs b/src/test/ui/suggestions/unnamable-types.rs new file mode 100644 index 0000000000..483f9bbb48 --- /dev/null +++ b/src/test/ui/suggestions/unnamable-types.rs @@ -0,0 +1,39 @@ +// Test that we do not suggest to add type annotations for unnamable types. + +#![crate_type="lib"] +#![feature(generators)] + +const A = 5; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant + +static B: _ = "abc"; +//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for static variables +//~| NOTE: not allowed in type signatures +//~| HELP: replace with the correct type + + +// FIXME: this should also suggest a function pointer, as the closure is non-capturing +const C: _ = || 42; +//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for constants +//~| NOTE: not allowed in type signatures +//~| NOTE: however, the inferred type + +struct S { t: T } +const D = S { t: { let i = 0; move || -> i32 { i } } }; +//~^ ERROR: missing type for `const` item +//~| NOTE: however, the inferred type + + +fn foo() -> i32 { 42 } +const E = foo; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant +const F = S { t: foo }; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant + + +const G = || -> i32 { yield 0; return 1; }; +//~^ ERROR: missing type for `const` item +//~| NOTE: however, the inferred type diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr new file mode 100644 index 0000000000..3a489a6e94 --- /dev/null +++ b/src/test/ui/suggestions/unnamable-types.stderr @@ -0,0 +1,66 @@ +error: missing type for `const` item + --> $DIR/unnamable-types.rs:6:7 + | +LL | const A = 5; + | ^ help: provide a type for the constant: `A: i32` + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/unnamable-types.rs:10:11 + | +LL | static B: _ = "abc"; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `&str` + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/unnamable-types.rs:17:10 + | +LL | const C: _ = || 42; + | ^ not allowed in type signatures + | +note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:19]` cannot be named + --> $DIR/unnamable-types.rs:17:14 + | +LL | const C: _ = || 42; + | ^^^^^ + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:23:7 + | +LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; + | ^ + | +note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:51]>` cannot be named + --> $DIR/unnamable-types.rs:23:11 + | +LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:29:7 + | +LL | const E = foo; + | ^ help: provide a type for the constant: `E: fn() -> i32` + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:32:7 + | +LL | const F = S { t: foo }; + | ^ help: provide a type for the constant: `F: S i32>` + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:37:7 + | +LL | const G = || -> i32 { yield 0; return 1; }; + | ^ + | +note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:43]` cannot be named + --> $DIR/unnamable-types.rs:37:11 + | +LL | const G = || -> i32 { yield 0; return 1; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/suggestions/use-placement-resolve.fixed b/src/test/ui/suggestions/use-placement-resolve.fixed new file mode 100644 index 0000000000..afe74cff2e --- /dev/null +++ b/src/test/ui/suggestions/use-placement-resolve.fixed @@ -0,0 +1,13 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +use std::fmt::Debug; + +fn main() {} + +fn foobar(x: T) {} //~ ERROR expected trait, found derive macro diff --git a/src/test/ui/suggestions/use-placement-resolve.rs b/src/test/ui/suggestions/use-placement-resolve.rs new file mode 100644 index 0000000000..b30ddb3af0 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-resolve.rs @@ -0,0 +1,11 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +fn main() {} + +fn foobar(x: T) {} //~ ERROR expected trait, found derive macro diff --git a/src/test/ui/suggestions/use-placement-resolve.stderr b/src/test/ui/suggestions/use-placement-resolve.stderr new file mode 100644 index 0000000000..9da9e8e270 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-resolve.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found derive macro `Debug` + --> $DIR/use-placement-resolve.rs:11:14 + | +LL | fn foobar(x: T) {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::fmt::Debug; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/suggestions/use-placement-typeck.fixed b/src/test/ui/suggestions/use-placement-typeck.fixed new file mode 100644 index 0000000000..40c55d1dd0 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-typeck.fixed @@ -0,0 +1,22 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +use m::Foo; + +fn main() { + let s = m::S; + s.abc(); //~ ERROR no method named `abc` +} + +mod m { + pub trait Foo { + fn abc(&self) {} + } + pub struct S; + impl Foo for S{} +} diff --git a/src/test/ui/suggestions/use-placement-typeck.rs b/src/test/ui/suggestions/use-placement-typeck.rs new file mode 100644 index 0000000000..aab20d2e90 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-typeck.rs @@ -0,0 +1,20 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +fn main() { + let s = m::S; + s.abc(); //~ ERROR no method named `abc` +} + +mod m { + pub trait Foo { + fn abc(&self) {} + } + pub struct S; + impl Foo for S{} +} diff --git a/src/test/ui/suggestions/use-placement-typeck.stderr b/src/test/ui/suggestions/use-placement-typeck.stderr new file mode 100644 index 0000000000..21f22dade2 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-typeck.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `abc` found for struct `S` in the current scope + --> $DIR/use-placement-typeck.rs:11:7 + | +LL | s.abc(); + | ^^^ method not found in `S` +... +LL | fn abc(&self) {} + | --- the method is available for `S` here +LL | } +LL | pub struct S; + | ------------- method `abc` not found for this + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use m::Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr index 3dd2b19fbf..de4d35e261 100644 --- a/src/test/ui/symbol-names/basic.legacy.stderr +++ b/src/test/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E) +error: symbol-name(_ZN5basic4main17hd75b915511563828E) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h6c535bbea2051f85) +error: demangling(basic::main::hd75b915511563828) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/basic.rs b/src/test/ui/symbol-names/basic.rs index bd107c1020..d871a4ee82 100644 --- a/src/test/ui/symbol-names/basic.rs +++ b/src/test/ui/symbol-names/basic.rs @@ -9,8 +9,8 @@ //[legacy]~^ ERROR symbol-name(_ZN5basic4main //[legacy]~| ERROR demangling(basic::main //[legacy]~| ERROR demangling-alt(basic::main) - //[v0]~^^^^ ERROR symbol-name(_RNvCs21hi0yVfW1J_5basic4main) - //[v0]~| ERROR demangling(basic[17891616a171812d]::main) + //[v0]~^^^^ ERROR symbol-name(_RNvCsj6j3mjPNGKx_5basic4main) + //[v0]~| ERROR demangling(basic[de7d5b6b69c71f37]::main) //[v0]~| ERROR demangling-alt(basic::main) #[rustc_def_path] //[legacy]~^ ERROR def-path(main) diff --git a/src/test/ui/symbol-names/basic.v0.stderr b/src/test/ui/symbol-names/basic.v0.stderr index 519efc9d7b..e30fa6f66d 100644 --- a/src/test/ui/symbol-names/basic.v0.stderr +++ b/src/test/ui/symbol-names/basic.v0.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_RNvCs21hi0yVfW1J_5basic4main) +error: symbol-name(_RNvCsj6j3mjPNGKx_5basic4main) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic[17891616a171812d]::main) +error: demangling(basic[de7d5b6b69c71f37]::main) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/const-generics-demangling.rs b/src/test/ui/symbol-names/const-generics-demangling.rs index bd7e1c0f33..05c6b8352d 100644 --- a/src/test/ui/symbol-names/const-generics-demangling.rs +++ b/src/test/ui/symbol-names/const-generics-demangling.rs @@ -5,32 +5,32 @@ pub struct Unsigned; #[rustc_symbol_name] -//~^ ERROR symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E) -//~| ERROR demangling(>) +//~^ ERROR symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E) +//~| ERROR demangling(>) //~| ERROR demangling-alt(>) impl Unsigned<11> {} pub struct Signed; #[rustc_symbol_name] -//~^ ERROR symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E) -//~| ERROR demangling(>) +//~^ ERROR symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E) +//~| ERROR demangling(>) //~| ERROR demangling-alt(>) impl Signed<-152> {} pub struct Bool; #[rustc_symbol_name] -//~^ ERROR symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E) -//~| ERROR demangling(>) +//~^ ERROR symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E) +//~| ERROR demangling(>) //~| ERROR demangling-alt(>) impl Bool {} pub struct Char; #[rustc_symbol_name] -//~^ ERROR symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E) -//~| ERROR demangling(>) +//~^ ERROR symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E) +//~| ERROR demangling(>) //~| ERROR demangling-alt(>) impl Char<'∂'> {} diff --git a/src/test/ui/symbol-names/const-generics-demangling.stderr b/src/test/ui/symbol-names/const-generics-demangling.stderr index 13995403f7..05c485d001 100644 --- a/src/test/ui/symbol-names/const-generics-demangling.stderr +++ b/src/test/ui/symbol-names/const-generics-demangling.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E) +error: symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E) --> $DIR/const-generics-demangling.rs:7:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(>) +error: demangling(>) --> $DIR/const-generics-demangling.rs:7:1 | LL | #[rustc_symbol_name] @@ -16,13 +16,13 @@ error: demangling-alt(>) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E) +error: symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E) --> $DIR/const-generics-demangling.rs:15:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(>) +error: demangling(>) --> $DIR/const-generics-demangling.rs:15:1 | LL | #[rustc_symbol_name] @@ -34,13 +34,13 @@ error: demangling-alt(>) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E) +error: symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E) --> $DIR/const-generics-demangling.rs:23:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(>) +error: demangling(>) --> $DIR/const-generics-demangling.rs:23:1 | LL | #[rustc_symbol_name] @@ -52,13 +52,13 @@ error: demangling-alt(>) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E) +error: symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E) --> $DIR/const-generics-demangling.rs:31:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(>) +error: demangling(>) --> $DIR/const-generics-demangling.rs:31:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index b0b31a57d0..960049be79 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -15,8 +15,8 @@ mod foo { //[legacy]~^ ERROR symbol-name(_ZN5impl13foo3Foo3bar //[legacy]~| ERROR demangling(impl1::foo::Foo::bar //[legacy]~| ERROR demangling-alt(impl1::foo::Foo::bar) - //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar) - //[v0]~| ERROR demangling(::bar) + //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar) + //[v0]~| ERROR demangling(::bar) //[v0]~| ERROR demangling-alt(::bar) #[rustc_def_path] //[legacy]~^ ERROR def-path(foo::Foo::bar) @@ -33,8 +33,8 @@ mod bar { //[legacy]~^ ERROR symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz //[legacy]~| ERROR demangling(impl1::bar::::baz //[legacy]~| ERROR demangling-alt(impl1::bar::::baz) - //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz) - //[v0]~| ERROR demangling(::baz) + //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz) + //[v0]~| ERROR demangling(::baz) //[v0]~| ERROR demangling-alt(::baz) #[rustc_def_path] //[legacy]~^ ERROR def-path(bar::::baz) @@ -63,8 +63,8 @@ fn main() { //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) - //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) - //[v0]~| ERROR demangling(<[&dyn impl1[17891616a171812d]::Foo extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method) + //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) + //[v0]~| ERROR demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method) //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) #[rustc_def_path] //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr index e5b0deee36..a7c3a38990 100644 --- a/src/test/ui/symbol-names/impl1.v0.stderr +++ b/src/test/ui/symbol-names/impl1.v0.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar) +error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar) --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(::bar) +error: demangling(::bar) --> $DIR/impl1.rs:14:9 | LL | #[rustc_symbol_name] @@ -22,13 +22,13 @@ error: def-path(foo::Foo::bar) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz) +error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz) --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(::baz) +error: demangling(::baz) --> $DIR/impl1.rs:32:9 | LL | #[rustc_symbol_name] @@ -46,13 +46,13 @@ error: def-path(bar::::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) +error: symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1[17891616a171812d]::Foo extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method) +error: demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:62:13 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 8357678399..52d0c66639 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h18eaa05e22e59176E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h6244e5288326926a) +error: demangling(issue_60925::foo::Foo::foo::h18eaa05e22e59176) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs index 3238eb1e57..a313c1ef38 100644 --- a/src/test/ui/symbol-names/issue-60925.rs +++ b/src/test/ui/symbol-names/issue-60925.rs @@ -22,8 +22,8 @@ mod foo { //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo //[legacy]~| ERROR demangling(issue_60925::foo::Foo::foo //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo::foo) - //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) - //[v0]~| ERROR demangling(>::foo) + //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) + //[v0]~| ERROR demangling(>::foo) //[v0]~| ERROR demangling-alt(>::foo) pub(crate) fn foo() { for _ in 0..0 { diff --git a/src/test/ui/symbol-names/issue-60925.v0.stderr b/src/test/ui/symbol-names/issue-60925.v0.stderr index 6a5885e1ea..5d99abff59 100644 --- a/src/test/ui/symbol-names/issue-60925.v0.stderr +++ b/src/test/ui/symbol-names/issue-60925.v0.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) +error: symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(>::foo) +error: demangling(>::foo) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-75326.rs b/src/test/ui/symbol-names/issue-75326.rs index 4d061cafef..0f721fc1f8 100644 --- a/src/test/ui/symbol-names/issue-75326.rs +++ b/src/test/ui/symbol-names/issue-75326.rs @@ -42,8 +42,8 @@ where //[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next //[legacy]~| ERROR demangling( as issue_75326::Iterator2>::next //[legacy]~| ERROR demangling-alt( as issue_75326::Iterator2>::next) - //[v0]~^^^^ ERROR symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_) - //[v0]~| ERROR demangling( as issue_75326[17891616a171812d]::Iterator2>::next) + //[v0]~^^^^ ERROR symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_) + //[v0]~| ERROR demangling( as issue_75326[dac9b7624645f95d]::Iterator2>::next) //[v0]~| ERROR demangling-alt( as issue_75326::Iterator2>::next) fn next(&mut self) -> Option { self.find(|_| true) diff --git a/src/test/ui/symbol-names/issue-75326.v0.stderr b/src/test/ui/symbol-names/issue-75326.v0.stderr index 98844aafb6..093ba8c857 100644 --- a/src/test/ui/symbol-names/issue-75326.v0.stderr +++ b/src/test/ui/symbol-names/issue-75326.v0.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_) +error: symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_) --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling( as issue_75326[17891616a171812d]::Iterator2>::next) +error: demangling( as issue_75326[dac9b7624645f95d]::Iterator2>::next) --> $DIR/issue-75326.rs:41:5 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/trait-objects.v0.stderr b/src/test/ui/symbol-names/trait-objects.v0.stderr index 2b09318f06..5ada82dfb2 100644 --- a/src/test/ui/symbol-names/trait-objects.v0.stderr +++ b/src/test/ui/symbol-names/trait-objects.v0.stderr @@ -4,7 +4,7 @@ error: symbol-name(_RNvXCRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8 LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method) +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3f8b57f879016e18]::Bar>::method) --> $DIR/trait-objects.rs:16:5 | LL | #[rustc_symbol_name] @@ -22,7 +22,7 @@ error: symbol-name(_RNvXs_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3op LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method) +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Foo>::method) --> $DIR/trait-objects.rs:28:5 | LL | #[rustc_symbol_name] @@ -40,7 +40,7 @@ error: symbol-name(_RNvXs0_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3o LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method) +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Baz>::method) --> $DIR/trait-objects.rs:40:5 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/synthetic-param.stderr b/src/test/ui/synthetic-param.stderr index 951d7edb7f..101132d05f 100644 --- a/src/test/ui/synthetic-param.stderr +++ b/src/test/ui/synthetic-param.stderr @@ -18,3 +18,4 @@ LL | Bar::::func::(42); error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/test-panic-abort-disabled.rs b/src/test/ui/test-attrs/test-panic-abort-disabled.rs similarity index 100% rename from src/test/ui/test-panic-abort-disabled.rs rename to src/test/ui/test-attrs/test-panic-abort-disabled.rs diff --git a/src/test/ui/test-panic-abort-disabled.stderr b/src/test/ui/test-attrs/test-panic-abort-disabled.stderr similarity index 100% rename from src/test/ui/test-panic-abort-disabled.stderr rename to src/test/ui/test-attrs/test-panic-abort-disabled.stderr diff --git a/src/test/ui/test-panic-abort-nocapture.rs b/src/test/ui/test-attrs/test-panic-abort-nocapture.rs similarity index 100% rename from src/test/ui/test-panic-abort-nocapture.rs rename to src/test/ui/test-attrs/test-panic-abort-nocapture.rs diff --git a/src/test/ui/test-panic-abort-nocapture.run.stderr b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stderr similarity index 100% rename from src/test/ui/test-panic-abort-nocapture.run.stderr rename to src/test/ui/test-attrs/test-panic-abort-nocapture.run.stderr diff --git a/src/test/ui/test-panic-abort-nocapture.run.stdout b/src/test/ui/test-attrs/test-panic-abort-nocapture.run.stdout similarity index 100% rename from src/test/ui/test-panic-abort-nocapture.run.stdout rename to src/test/ui/test-attrs/test-panic-abort-nocapture.run.stdout diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-attrs/test-panic-abort.rs similarity index 100% rename from src/test/ui/test-panic-abort.rs rename to src/test/ui/test-attrs/test-panic-abort.rs diff --git a/src/test/ui/test-panic-abort.run.stdout b/src/test/ui/test-attrs/test-panic-abort.run.stdout similarity index 100% rename from src/test/ui/test-panic-abort.run.stdout rename to src/test/ui/test-attrs/test-panic-abort.run.stdout diff --git a/src/test/ui/test-panic-while-printing.rs b/src/test/ui/test-attrs/test-panic-while-printing.rs similarity index 100% rename from src/test/ui/test-panic-while-printing.rs rename to src/test/ui/test-attrs/test-panic-while-printing.rs diff --git a/src/test/ui/test-passed-wasm.rs b/src/test/ui/test-attrs/test-passed-wasm.rs similarity index 100% rename from src/test/ui/test-passed-wasm.rs rename to src/test/ui/test-attrs/test-passed-wasm.rs diff --git a/src/test/ui/test-passed-wasm.run.stdout b/src/test/ui/test-attrs/test-passed-wasm.run.stdout similarity index 100% rename from src/test/ui/test-passed-wasm.run.stdout rename to src/test/ui/test-attrs/test-passed-wasm.run.stdout diff --git a/src/test/ui/test-passed.rs b/src/test/ui/test-attrs/test-passed.rs similarity index 100% rename from src/test/ui/test-passed.rs rename to src/test/ui/test-attrs/test-passed.rs diff --git a/src/test/ui/test-passed.run.stdout b/src/test/ui/test-attrs/test-passed.run.stdout similarity index 100% rename from src/test/ui/test-passed.run.stdout rename to src/test/ui/test-attrs/test-passed.run.stdout diff --git a/src/test/ui/test-thread-capture.rs b/src/test/ui/test-attrs/test-thread-capture.rs similarity index 100% rename from src/test/ui/test-thread-capture.rs rename to src/test/ui/test-attrs/test-thread-capture.rs diff --git a/src/test/ui/test-thread-capture.run.stdout b/src/test/ui/test-attrs/test-thread-capture.run.stdout similarity index 100% rename from src/test/ui/test-thread-capture.run.stdout rename to src/test/ui/test-attrs/test-thread-capture.run.stdout diff --git a/src/test/ui/test-thread-nocapture.rs b/src/test/ui/test-attrs/test-thread-nocapture.rs similarity index 100% rename from src/test/ui/test-thread-nocapture.rs rename to src/test/ui/test-attrs/test-thread-nocapture.rs diff --git a/src/test/ui/test-thread-nocapture.run.stderr b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr similarity index 100% rename from src/test/ui/test-thread-nocapture.run.stderr rename to src/test/ui/test-attrs/test-thread-nocapture.run.stderr diff --git a/src/test/ui/test-thread-nocapture.run.stdout b/src/test/ui/test-attrs/test-thread-nocapture.run.stdout similarity index 100% rename from src/test/ui/test-thread-nocapture.run.stdout rename to src/test/ui/test-attrs/test-thread-nocapture.run.stdout diff --git a/src/test/ui/thir-unsafeck-issue-85871.rs b/src/test/ui/thir-unsafeck-issue-85871.rs new file mode 100644 index 0000000000..aea539b74d --- /dev/null +++ b/src/test/ui/thir-unsafeck-issue-85871.rs @@ -0,0 +1,20 @@ +// Tests that no ICE occurs when a closure appears inside a node +// that does not have a body when compiling with +// compile-flags: -Zthir-unsafeck=yes +// check-pass + +#![allow(dead_code)] + +struct Bug { + inner: [(); match || 1 { + _n => 42, // we may not call the closure here (E0015) + }], +} + +enum E { + V([(); { let _ = || 1; 42 }]), +} + +type Ty = [(); { let _ = || 1; 42 }]; + +fn main() {} diff --git a/src/test/ui/thread-local-static.rs b/src/test/ui/thread-local-static.rs index dc542fe2db..c7fee9e6b4 100644 --- a/src/test/ui/thread-local-static.rs +++ b/src/test/ui/thread-local-static.rs @@ -11,7 +11,6 @@ const fn g(x: &mut [u32; 8]) { //~| ERROR mutable references are not allowed //~| ERROR use of mutable static is unsafe //~| constant functions cannot refer to statics - //~| ERROR calls in constant functions are limited to constant functions } fn main() {} diff --git a/src/test/ui/thread-local-static.stderr b/src/test/ui/thread-local-static.stderr index a213282eb8..08bf593a5a 100644 --- a/src/test/ui/thread-local-static.stderr +++ b/src/test/ui/thread-local-static.stderr @@ -30,12 +30,6 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/thread-local-static.rs:9:5 - | -LL | std::mem::swap(x, &mut STATIC_VAR_2) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0133]: use of mutable static is unsafe and requires unsafe function or block --> $DIR/thread-local-static.rs:9:23 | @@ -44,7 +38,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0013, E0015, E0133, E0658. +Some errors have detailed explanations: E0013, E0133, E0658. For more information about an error, try `rustc --explain E0013`. diff --git a/src/test/ui/thread-local/thread-local-issue-37508.rs b/src/test/ui/thread-local/thread-local-issue-37508.rs new file mode 100644 index 0000000000..219108c77f --- /dev/null +++ b/src/test/ui/thread-local/thread-local-issue-37508.rs @@ -0,0 +1,36 @@ +// only-x86_64 +// compile-flags: -Ccode-model=large --crate-type lib +// build-pass +// +// Regression test for issue #37508 + +#![no_main] +#![no_std] +#![feature(thread_local, lang_items)] + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_panic: &PanicInfo<'_>) -> ! { + loop {} +} + +pub struct BB; + +#[thread_local] +static mut KEY: Key = Key { inner: BB, dtor_running: false }; + +pub unsafe fn set() -> Option<&'static BB> { + if KEY.dtor_running { + return None; + } + Some(&KEY.inner) +} + +pub struct Key { + inner: BB, + dtor_running: bool, +} diff --git a/src/test/ui/traits/bad-sized.stderr b/src/test/ui/traits/bad-sized.stderr index 768893d6e2..5a9d4286ce 100644 --- a/src/test/ui/traits/bad-sized.stderr +++ b/src/test/ui/traits/bad-sized.stderr @@ -29,7 +29,11 @@ LL | let x: Vec = Vec::new(); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` - = note: required by `Vec::::new` +note: required by `Vec::::new` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | +LL | pub const fn new() -> Self { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:37 diff --git a/src/test/ui/traits/bound/not-on-bare-trait.rs b/src/test/ui/traits/bound/not-on-bare-trait.rs index 08355a5563..daf18c6702 100644 --- a/src/test/ui/traits/bound/not-on-bare-trait.rs +++ b/src/test/ui/traits/bound/not-on-bare-trait.rs @@ -7,7 +7,7 @@ trait Foo { fn foo(_x: Foo + Send) { //~^ ERROR the size for values of type //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this was previously accepted by the compiler + //~| WARN this is accepted in the current edition } fn main() {} 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 418e67d56e..e65b8989e0 100644 --- a/src/test/ui/traits/bound/not-on-bare-trait.stderr +++ b/src/test/ui/traits/bound/not-on-bare-trait.stderr @@ -5,7 +5,7 @@ LL | fn foo(_x: Foo + Send) { | ^^^^^^^^^^ help: use `dyn`: `dyn Foo + Send` | = note: `#[warn(bare_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 the 2021 edition! + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see issue #80165 error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time diff --git a/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr b/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr index 967b7320ab..7480d243f4 100644 --- a/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr +++ b/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr @@ -10,11 +10,14 @@ LL | let baz: Foo = loop { }; error[E0277]: the trait bound `{integer}: Trait` is not satisfied --> $DIR/on-structs-and-enums-locals.rs:10:15 | -LL | struct Foo { - | ------------------- required by `Foo` -... LL | let foo = Foo { | ^^^ the trait `Trait` is not implemented for `{integer}` + | +note: required by `Foo` + --> $DIR/on-structs-and-enums-locals.rs:5:1 + | +LL | struct Foo { + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr b/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr index 08f0f20e74..ada2445c1c 100644 --- a/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr +++ b/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr @@ -15,7 +15,11 @@ error[E0277]: the trait bound `{integer}: Trait` is not satisfied LL | let foo = Foo { | ^^^ the trait `Trait` is not implemented for `{integer}` | - = note: required by `Foo` +note: required by `Foo` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:1 + | +LL | pub struct Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 40386f7061..565899677b 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -1,9 +1,6 @@ error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe` --> $DIR/cycle-cache-err-60010.rs:69:5 | -LL | fn parse(&self) { - | --------------- required by `SourceDatabase::parse` -... LL | SourceDatabase::parse(db); | ^^^^^^^^^^^^^^^^^^^^^ | @@ -25,6 +22,11 @@ note: required because of the requirements on the impl of `SourceDatabase` for ` | LL | impl SourceDatabase for T | ^^^^^^^^^^^^^^ ^ +note: required by `SourceDatabase::parse` + --> $DIR/cycle-cache-err-60010.rs:14:5 + | +LL | fn parse(&self) { + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr index bb11f18e54..bc7b863ca4 100644 --- a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -18,21 +18,26 @@ LL | fn with_trait>(c: &C) -> bool { error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:34:5 | -LL | fn same_as(&self, t: T) -> bool; - | -------------------------------- required by `CompareTo::same_as` -... LL | ::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` + | +note: required by `CompareTo::same_as` + --> $DIR/repeated-supertrait-ambig.rs:9:5 + | +LL | fn same_as(&self, t: T) -> bool; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:38:5 | -LL | fn same_as(&self, t: T) -> bool; - | -------------------------------- required by `CompareTo::same_as` -... LL | CompareTo::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `C` | +note: required by `CompareTo::same_as` + --> $DIR/repeated-supertrait-ambig.rs:9:5 + | +LL | fn same_as(&self, t: T) -> bool; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider further restricting this bound | LL | fn with_ufcs2>(c: &C) -> bool { diff --git a/src/test/ui/traits/issue-71136.stderr b/src/test/ui/traits/issue-71136.stderr index d1be955b41..23b78d023b 100644 --- a/src/test/ui/traits/issue-71136.stderr +++ b/src/test/ui/traits/issue-71136.stderr @@ -1,11 +1,18 @@ error[E0277]: the trait bound `Foo: Clone` is not satisfied --> $DIR/issue-71136.rs:5:5 | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct FooHolster { LL | the_foos: Vec, | ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone` | = note: required because of the requirements on the impl of `Clone` for `Vec` - = note: required by `clone` +note: required by `clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr index d788f1871f..68347207bd 100644 --- a/src/test/ui/traits/issue-77982.stderr +++ b/src/test/ui/traits/issue-77982.stderr @@ -17,7 +17,11 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect( | cannot infer type for type parameter `T` declared on the trait `From` | = note: cannot satisfy `u32: From<_>` - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed for `Box` --> $DIR/issue-77982.rs:35:16 diff --git a/src/test/ui/traits/issue-78632.rs b/src/test/ui/traits/issue-78632.rs new file mode 100644 index 0000000000..c72a2aef49 --- /dev/null +++ b/src/test/ui/traits/issue-78632.rs @@ -0,0 +1,59 @@ +// check-pass +// +// Regression test for issue #78632 + +#![crate_type = "lib"] + +pub trait Corge { + type Fred; +} + +impl Corge for () { + type Fred = u32; +} + +pub trait Waldo { + type Quax; +} + +impl Waldo for u32 { + type Quax = u8; +} + +pub trait Grault +where + (): Corge, +{ + type Thud; + fn bar(_: <() as Corge>::Fred) {} +} + +impl Grault for T +where + T: Waldo, + (): Corge, + <() as Corge>::Fred: Waldo, +{ + type Thud = u8; +} + +pub trait Plugh { + fn baz(); +} + +#[derive(Copy, Clone, Debug)] +pub struct Qiz { + foo: T, +} + +impl Plugh<<() as Corge>::Fred> for Qiz +where + T: Grault, + (): Corge, +{ + fn baz() {} +} + +pub fn test() { + as Plugh>::baz(); +} diff --git a/src/test/ui/traits/issue-79458.stderr b/src/test/ui/traits/issue-79458.stderr index 7e990cdc34..2f5b4ad0e6 100644 --- a/src/test/ui/traits/issue-79458.stderr +++ b/src/test/ui/traits/issue-79458.stderr @@ -1,13 +1,20 @@ error[E0277]: the trait bound `&mut T: Clone` is not satisfied --> $DIR/issue-79458.rs:6:5 | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Foo<'a, T> { LL | bar: &'a mut T | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T` | = help: the following implementations were found: <&T as Clone> = note: `Clone` is implemented for `&T`, but not for `&mut T` - = note: required by `clone` +note: required by `clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | fn clone(&self) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs index e186570167..1be0b05fa2 100644 --- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs +++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs @@ -17,8 +17,8 @@ pub struct Second { d: Vec, } -struct Third { - g: Vec, +struct Third<'a, f> { + g: Vec<(f, &'a f)>, } enum Ty { @@ -38,29 +38,29 @@ struct Sixth { } #[rustc_evaluate_where_clauses] -fn forward() +fn forward<'a>() where Vec: Unpin, - Third: Unpin, + Third<'a, Ty>: Unpin, { } #[rustc_evaluate_where_clauses] -fn reverse() +fn reverse<'a>() where - Third: Unpin, + Third<'a, Ty>: Unpin, Vec: Unpin, { } fn main() { - // Key is that Vec is "ok" and Third is "ok modulo regions": + // Key is that Vec is "ok" and Third<'_, Ty> is "ok modulo regions": forward(); //~^ ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) + //~| ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) reverse(); //~^ ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) + //~| ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) } diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr index bfe3e76b21..43acc66fd7 100644 --- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr +++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr @@ -7,20 +7,20 @@ LL | Vec: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | -LL | Third: Unpin, - | ----- predicate +LL | Third<'a, Ty>: Unpin, + | ----- predicate ... LL | forward(); | ^^^^^^^ -error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | -LL | Third: Unpin, - | ----- predicate +LL | Third<'a, Ty>: Unpin, + | ----- predicate ... LL | reverse(); | ^^^^^^^ diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index 30daf8e277..2260dcfc70 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -35,6 +35,9 @@ LL | use method::B; error[E0624]: associated function `a` is private --> $DIR/item-privacy.rs:72:7 | +LL | fn a(&self) { } + | ----------- private associated function defined here +... LL | c.a(); | ^ private associated function @@ -72,6 +75,9 @@ LL | use method::B; error[E0624]: associated function `a` is private --> $DIR/item-privacy.rs:84:14 | +LL | fn a(&self) { } + | ----------- private associated function defined here +... LL | ::a(&S); | ^ private associated function @@ -109,6 +115,9 @@ LL | use assoc_const::B; error[E0624]: associated constant `A` is private --> $DIR/item-privacy.rs:101:14 | +LL | const A: u8 = 0; + | ---------------- private associated constant defined here +... LL | ::A; | ^ private associated constant diff --git a/src/test/ui/traits/method-private.stderr b/src/test/ui/traits/method-private.stderr index 99f330b38a..8e991ec018 100644 --- a/src/test/ui/traits/method-private.stderr +++ b/src/test/ui/traits/method-private.stderr @@ -1,6 +1,9 @@ error[E0624]: associated function `method` is private --> $DIR/method-private.rs:19:9 | +LL | fn method(&self) {} + | ---------------- private associated function defined here +... LL | foo.method(); | ^^^^^^ private associated function | diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr index 4f7d1be793..cad298cf24 100644 --- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -1,13 +1,15 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:23:11 | -LL | struct Outer(T); - | ------------------------- required by `Outer` -... LL | Outer(TestType); | ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `dummy::TestType` +note: required by `Outer` + --> $DIR/negated-auto-traits-error.rs:10:1 + | +LL | struct Outer(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dummy::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:23:5 diff --git a/src/test/ui/traits/object/issue-33140-traitobject-crate.rs b/src/test/ui/traits/object/issue-33140-traitobject-crate.rs index 46b68f1c9f..8abd92da36 100644 --- a/src/test/ui/traits/object/issue-33140-traitobject-crate.rs +++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.rs @@ -1,6 +1,7 @@ // check-pass #![warn(order_dependent_trait_objects)] +#![allow(dyn_drop)] // Check that traitobject 0.1.0 compiles 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 781decb5ae..77d71360b8 100644 --- a/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr +++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr @@ -1,5 +1,5 @@ warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) - --> $DIR/issue-33140-traitobject-crate.rs:85:1 + --> $DIR/issue-33140-traitobject-crate.rs:86:1 | LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { } | ------------------------------------------------------ first implementation here @@ -15,7 +15,7 @@ LL | #![warn(order_dependent_trait_objects)] = note: for more information, see issue #56484 warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) - --> $DIR/issue-33140-traitobject-crate.rs:88:1 + --> $DIR/issue-33140-traitobject-crate.rs:89:1 | LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } | ------------------------------------------------------------- first implementation here @@ -27,7 +27,7 @@ LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } = note: for more information, see issue #56484 warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) - --> $DIR/issue-33140-traitobject-crate.rs:92:1 + --> $DIR/issue-33140-traitobject-crate.rs:93:1 | LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } | ------------------------------------------------------ first implementation here diff --git a/src/test/ui/traits/operator-overloading-issue-52025.rs b/src/test/ui/traits/operator-overloading-issue-52025.rs new file mode 100644 index 0000000000..7ce638832b --- /dev/null +++ b/src/test/ui/traits/operator-overloading-issue-52025.rs @@ -0,0 +1,57 @@ +// only-x86_64 +// build-pass + +use std::arch::x86_64::*; +use std::fmt::Debug; +use std::ops::*; + +pub trait Simd { + type Vf32: Copy + Debug + Add + Add; + + unsafe fn set1_ps(a: f32) -> Self::Vf32; + unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32; +} + +#[derive(Copy, Debug, Clone)] +pub struct F32x4(pub __m128); + +impl Add for F32x4 { + type Output = F32x4; + + fn add(self, rhs: F32x4) -> F32x4 { + F32x4(unsafe { _mm_add_ps(self.0, rhs.0) }) + } +} + +impl Add for F32x4 { + type Output = F32x4; + fn add(self, rhs: f32) -> F32x4 { + F32x4(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }) + } +} + +pub struct Sse2; +impl Simd for Sse2 { + type Vf32 = F32x4; + + #[inline(always)] + unsafe fn set1_ps(a: f32) -> Self::Vf32 { + F32x4(_mm_set1_ps(a)) + } + + #[inline(always)] + unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32 { + F32x4(_mm_add_ps(a.0, b.0)) + } +} + +unsafe fn test() -> S::Vf32 { + let a = S::set1_ps(3.0); + let b = S::set1_ps(2.0); + let result = a + b; + result +} + +fn main() { + println!("{:?}", unsafe { test::() }); +} diff --git a/src/test/ui/traits/reservation-impl/no-use.stderr b/src/test/ui/traits/reservation-impl/no-use.stderr index fb4a443435..526c0e9ed5 100644 --- a/src/test/ui/traits/reservation-impl/no-use.stderr +++ b/src/test/ui/traits/reservation-impl/no-use.stderr @@ -1,14 +1,16 @@ error[E0277]: the trait bound `(): MyTrait` is not satisfied --> $DIR/no-use.rs:10:26 | -LL | trait MyTrait { fn foo(&self); } - | -------------- required by `MyTrait::foo` -... LL | <() as MyTrait>::foo(&()); | ^^^ the trait `MyTrait` is not implemented for `()` | = help: the following implementations were found: <() as MyTrait> +note: required by `MyTrait::foo` + --> $DIR/no-use.rs:5:17 + | +LL | trait MyTrait { fn foo(&self); } + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/reservation-impl/non-lattice-ok.rs b/src/test/ui/traits/reservation-impl/non-lattice-ok.rs index f14589ccf8..b894577c1f 100644 --- a/src/test/ui/traits/reservation-impl/non-lattice-ok.rs +++ b/src/test/ui/traits/reservation-impl/non-lattice-ok.rs @@ -28,7 +28,7 @@ // go with a known approach, we should go with a "marker trait overlap"-style // approach. // -// [ii]: http://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/ +// [ii]: https://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/ #![feature(rustc_attrs, never_type)] diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr index 2b9ce7321e..c8c804a901 100644 --- a/src/test/ui/traits/static-method-generic-inference.stderr +++ b/src/test/ui/traits/static-method-generic-inference.stderr @@ -1,13 +1,15 @@ error[E0283]: type annotations needed --> $DIR/static-method-generic-inference.rs:24:25 | -LL | fn new() -> T; - | -------------- required by `HasNew::new` -... LL | let _f: base::Foo = base::HasNew::new(); | ^^^^^^^^^^^^^^^^^ cannot infer type | = note: cannot satisfy `_: HasNew` +note: required by `HasNew::new` + --> $DIR/static-method-generic-inference.rs:8:9 + | +LL | fn new() -> T; + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/suggest-where-clause.stderr b/src/test/ui/traits/suggest-where-clause.stderr index 0257064808..f15e7e3583 100644 --- a/src/test/ui/traits/suggest-where-clause.stderr +++ b/src/test/ui/traits/suggest-where-clause.stderr @@ -38,7 +38,11 @@ error[E0277]: the trait bound `u64: From` is not satisfied LL | >::from; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `u64` | - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | LL | fn check() where u64: From { @@ -50,7 +54,11 @@ error[E0277]: the trait bound `u64: From<::Item>` is not satisfie LL | ::Item>>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<::Item>` is not implemented for `u64` | - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | LL | fn check() where u64: From<::Item> { @@ -62,7 +70,11 @@ error[E0277]: the trait bound `Misc<_>: From` is not satisfied LL | as From>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `Misc<_>` | - = note: required by `from` +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `[T]` cannot be known at compilation time --> $DIR/suggest-where-clause.rs:28:20 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index de7a431d6f..41a19bff87 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -23,11 +23,14 @@ LL | pub trait Foo { error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:25:15 | -LL | fn test(&self); - | --------------- required by `Foo::test` -... LL | Foo::test(&4i32); | ^^^^^ the trait `Foo` is not implemented for `i32` + | +note: required by `Foo::test` + --> $DIR/trivial-bounds-leak.rs:5:5 + | +LL | fn test(&self); + | ^^^^^^^^^^^^^^^ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:26:22 diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index ec5e91f10c..fce8dbab48 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -8,7 +8,11 @@ LL | Err("")?; = help: the following implementations were found: > = note: required because of the requirements on the impl of `FromResidual>` for `Result` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving ` as Try>::Output == &str` --> $DIR/try-block-bad-type.rs:12:9 @@ -29,7 +33,11 @@ LL | let res: () = try { }; | ^ could not wrap the final value of the block as `()` doesn't implement `Try` | = help: the trait `Try` is not implemented for `()` - = note: required by `from_output` +note: required by `from_output` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_output(output: Self::Output) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) --> $DIR/try-block-bad-type.rs:20:26 @@ -38,7 +46,11 @@ LL | let res: i32 = try { 5 }; | ^ could not wrap the final value of the block as `i32` doesn't implement `Try` | = help: the trait `Try` is not implemented for `i32` - = note: required by `from_output` +note: required by `from_output` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_output(output: Self::Output) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr index c83351d5c4..4270df5b40 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -5,7 +5,11 @@ LL | while try { false } {} | ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try` | = help: the trait `Try` is not implemented for `bool` - = note: required by `from_output` +note: required by `from_output` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_output(output: Self::Output) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index f5b315c251..5cecf9128b 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -11,7 +11,11 @@ LL | Ok(Err(123_i32)?) > > = note: required because of the requirements on the impl of `FromResidual>` for `Result` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` --> $DIR/bad-interconversion.rs:11:12 @@ -25,7 +29,11 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` --> $DIR/bad-interconversion.rs:17:31 @@ -38,7 +46,11 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/bad-interconversion.rs:22:22 @@ -51,7 +63,11 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual>` is not implemented for `Option` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` --> $DIR/bad-interconversion.rs:27:33 @@ -64,7 +80,11 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual>` is not implemented for `Option` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:32:39 @@ -77,7 +97,11 @@ LL | | } | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:37:12 @@ -91,7 +115,11 @@ LL | | } | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator in a function that returns `ControlFlow` can only be used on other `ControlFlow`s (with the same Break type) --> $DIR/bad-interconversion.rs:43:29 @@ -106,7 +134,11 @@ LL | | } | = help: the trait `FromResidual>` is not implemented for `ControlFlow` = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/try-trait/option-to-result.stderr b/src/test/ui/try-trait/option-to-result.stderr index 9f7d80d4f2..f89813e729 100644 --- a/src/test/ui/try-trait/option-to-result.stderr +++ b/src/test/ui/try-trait/option-to-result.stderr @@ -10,7 +10,11 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result<(), ()>` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/option-to-result.rs:11:6 @@ -24,7 +28,11 @@ LL | | } | |_- this function returns an `Option` | = help: the trait `FromResidual>` is not implemented for `Option` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/try-trait/try-on-option-diagnostics.stderr b/src/test/ui/try-trait/try-on-option-diagnostics.stderr index e7c67c21bb..bb65aae561 100644 --- a/src/test/ui/try-trait/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-trait/try-on-option-diagnostics.stderr @@ -10,7 +10,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `u32` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-diagnostics.rs:14:10 @@ -25,7 +29,11 @@ LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `{integer}` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-diagnostics.rs:26:14 @@ -38,7 +46,11 @@ LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `()` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option-diagnostics.rs:39:14 @@ -51,7 +63,11 @@ LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `()` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr index 604baa8550..b522dd5709 100644 --- a/src/test/ui/try-trait/try-on-option.stderr +++ b/src/test/ui/try-trait/try-on-option.stderr @@ -10,7 +10,11 @@ LL | | } | |_- this function returns a `Result` | = help: the trait `FromResidual>` is not implemented for `Result` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option.rs:13:6 @@ -24,7 +28,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `u32` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/try-trait/try-operator-on-main.stderr b/src/test/ui/try-trait/try-operator-on-main.stderr index 7d42c2e4d1..dd893cadff 100644 --- a/src/test/ui/try-trait/try-operator-on-main.stderr +++ b/src/test/ui/try-trait/try-operator-on-main.stderr @@ -12,7 +12,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual>` is not implemented for `()` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/try-operator-on-main.rs:10:5 @@ -21,7 +25,11 @@ LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | = help: the trait `Try` is not implemented for `()` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-operator-on-main.rs:10:7 @@ -39,7 +47,11 @@ LL | | } | |_- this function should return `Result` or `Option` to accept `?` | = help: the trait `FromResidual<_>` is not implemented for `()` - = note: required by `from_residual` +note: required by `from_residual` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn from_residual(residual: R) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(): Try` is not satisfied --> $DIR/try-operator-on-main.rs:14:25 @@ -57,7 +69,11 @@ LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | = help: the trait `Try` is not implemented for `()` - = note: required by `branch` +note: required by `branch` + --> $SRC_DIR/core/src/ops/try_trait.rs:LL:COL + | +LL | fn branch(self) -> ControlFlow; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.rs b/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.rs deleted file mode 100644 index 967d4c3f0f..0000000000 --- a/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.rs +++ /dev/null @@ -1,33 +0,0 @@ -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: .*\n\n" -> "" -// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" - -// compile-flags: --crate-type=rlib - -// Regression test for https://github.com/rust-lang/rust/issues/78450 - -#![feature(min_type_alias_impl_trait)] -#![no_std] - -pub trait AssociatedImpl { - type ImplTrait; - - fn f() -> Self::ImplTrait; -} - -struct S(T); - -trait Associated { - type A; -} - -// ICE -impl<'a, T: Associated> AssociatedImpl for S { - type ImplTrait = impl core::fmt::Debug; - - fn f() -> Self::ImplTrait { - //~^ ERROR unexpected concrete region in borrowck: ReEarlyBound(0, 'a) - () - } -} diff --git a/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.stderr b/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.stderr deleted file mode 100644 index 64ab7b70b1..0000000000 --- a/src/test/ui/type-alias-impl-trait/associated-type-lifetime-ice.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: internal compiler error: unexpected concrete region in borrowck: ReEarlyBound(0, 'a) - --> $DIR/associated-type-lifetime-ice.rs:29:5 - | -LL | / fn f() -> Self::ImplTrait { -LL | | -LL | | () -LL | | } - | |_____^ - | - = error: internal compiler error: unexpected panic - -query stack during panic: -end of query stack diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr index d0f3be336d..28ac61a6b9 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.nll.stderr @@ -28,7 +28,7 @@ LL | type WrongGeneric = impl 'static; found opaque type `impl Sized` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:17:30 + --> $DIR/generic_type_does_not_live_long_enough.rs:16:30 | LL | fn wrong_generic(t: T) -> WrongGeneric { | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr index 6394a1f8e8..90a753b5a6 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.full_tait.stderr @@ -36,16 +36,7 @@ LL | type WrongGeneric = impl 'static; LL | fn wrong_generic(t: T) -> WrongGeneric { | - help: consider adding an explicit lifetime bound...: `T: 'static` -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:12:24 - | -LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'static`... - = note: ...so that the type `T` will meet its required lifetime bounds - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted Some errors have detailed explanations: E0308, E0310. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr index 7496d96fa2..b8ca8e4607 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.nll.stderr @@ -19,7 +19,7 @@ LL | type WrongGeneric = impl 'static; found opaque type `impl Sized` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:17:30 + --> $DIR/generic_type_does_not_live_long_enough.rs:16:30 | LL | fn wrong_generic(t: T) -> WrongGeneric { | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr index 49ead8b094..e502822010 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.min_tait.stderr @@ -27,16 +27,7 @@ LL | type WrongGeneric = impl 'static; LL | fn wrong_generic(t: T) -> WrongGeneric { | - help: consider adding an explicit lifetime bound...: `T: 'static` -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:12:24 - | -LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'static`... - = note: ...so that the type `T` will meet its required lifetime bounds - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0310. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index 3dda34ff66..9f647d9e73 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -11,7 +11,6 @@ fn main() { type WrongGeneric = impl 'static; //~^ ERROR the parameter type `T` may not live long enough -//~| ERROR the parameter type `T` may not live long enough //~| ERROR: at least one trait must be specified fn wrong_generic(t: T) -> WrongGeneric { diff --git a/src/test/ui/type-alias-impl-trait/issue-53096.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-53096.full_tait.stderr index 1a03ce7966..a8dd6a93d3 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53096.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53096.full_tait.stderr @@ -1,18 +1,10 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes +warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-53096.rs:4:32 | -LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] + | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-53096.rs:4:56 - | -LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] - | ^^^^^^^^^^^^^^^^^^^^^ - | = note: see issue #63063 for more information error: fatal error triggered by #[rustc_error] @@ -21,5 +13,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-53096.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-53096.min_tait.stderr index c6c7a51618..4210d0c1cb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53096.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53096.min_tait.stderr @@ -1,12 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-53096.rs:10:19 +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-53096.rs:14:1 | -LL | const BAZR: Foo = bar(); - | ^^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable +LL | fn main() {} + | ^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/type-alias-impl-trait/issue-53096.rs b/src/test/ui/type-alias-impl-trait/issue-53096.rs index fb621dc0bc..7bb0066b7e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53096.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53096.rs @@ -1,14 +1,14 @@ #![feature(const_impl_trait, const_fn_fn_ptr_basics, rustc_attrs)] // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] -#![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete type Foo = impl Fn() -> usize; -const fn bar() -> Foo { || 0usize } +const fn bar() -> Foo { + || 0usize +} const BAZR: Foo = bar(); -//[min_tait]~^ ERROR not permitted here #[rustc_error] -fn main() {} //[full_tait]~ ERROR +fn main() {} //~ ERROR diff --git a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.full_tait.stderr index 70d049ffa7..b23fed5dad 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.full_tait.stderr @@ -1,25 +1,17 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes +warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-53678-generator-and-const-fn.rs:4:32 | -LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] + | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information - -warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-53678-generator-and-const-fn.rs:4:56 - | -LL | #![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] - | ^^^^^^^^^^^^^^^^^^^^^ - | = note: see issue #63063 for more information error: fatal error triggered by #[rustc_error] - --> $DIR/issue-53678-generator-and-const-fn.rs:23:1 + --> $DIR/issue-53678-generator-and-const-fn.rs:22:1 | LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.min_tait.stderr index a3dea45a6a..fabba21835 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.min_tait.stderr @@ -1,12 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-53678-generator-and-const-fn.rs:20:36 +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-53678-generator-and-const-fn.rs:22:1 | -LL | const FOO: GenOnce = const_generator(10, 100); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable +LL | fn main() {} + | ^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs index bf607d29ce..a8215c4182 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs @@ -1,9 +1,8 @@ #![feature(const_impl_trait, generators, generator_trait, rustc_attrs)] // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] -#![cfg_attr(full_tait, feature(impl_trait_in_bindings, type_alias_impl_trait))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete use std::ops::Generator; @@ -17,7 +16,7 @@ const fn const_generator(yielding: Y, returning: R) -> GenOnce { } } -const FOO: GenOnce = const_generator(10, 100); //[min_tait]~ ERROR not permitted here +const FOO: GenOnce = const_generator(10, 100); #[rustc_error] -fn main() {} //[full_tait]~ ERROR +fn main() {} //~ ERROR diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr index 481d66dd81..e2b8b19aeb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.nll.stderr @@ -8,13 +8,13 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: see issue #63063 for more information error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:28:9 + --> $DIR/issue-57611-trait-alias.rs:24:9 | LL | |x| x | ^^^^^ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:28:9 + --> $DIR/issue-57611-trait-alias.rs:24:9 | LL | |x| x | ^^^^^ @@ -28,7 +28,7 @@ LL | type Bar = impl Baz; = note: expected type `for<'r> Fn<(&'r X,)>` found type `Fn<(&'static X,)>` note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:28:9 + --> $DIR/issue-57611-trait-alias.rs:24:9 | LL | |x| x | ^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr index d90f328708..61e8da91bb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.full_tait.stderr @@ -16,52 +16,5 @@ LL | type Bar = impl Baz; = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` -error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected type `for<'r> Fn<(&'r X,)>` - found type `Fn<(&' X,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:28:9 - | -LL | |x| x - | ^^^^^ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` - -error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected type `for<'r> Fn<(&'r X,)>` - found type `Fn<(&' X,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:28:9 - | -LL | |x| x - | ^^^^^ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` - -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr index 0343a76956..3a4d1d90c0 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.nll.stderr @@ -1,11 +1,11 @@ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:28:9 + --> $DIR/issue-57611-trait-alias.rs:24:9 | LL | |x| x | ^^^^^ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:28:9 + --> $DIR/issue-57611-trait-alias.rs:24:9 | LL | |x| x | ^^^^^ @@ -19,7 +19,7 @@ LL | type Bar = impl Baz; = note: expected type `for<'r> Fn<(&'r X,)>` found type `Fn<(&'static X,)>` note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:28:9 + --> $DIR/issue-57611-trait-alias.rs:24:9 | LL | |x| x | ^^^^^ diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr index d019f40757..f65e91e52c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.min_tait.stderr @@ -7,52 +7,5 @@ LL | type Bar = impl Baz; = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` -error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected type `for<'r> Fn<(&'r X,)>` - found type `Fn<(&' X,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:28:9 - | -LL | |x| x - | ^^^^^ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` - -error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = note: expected type `for<'r> Fn<(&'r X,)>` - found type `Fn<(&' X,)>` -note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:28:9 - | -LL | |x| x - | ^^^^^ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:20:16 - | -LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` - -error: aborting due to 5 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index ccc727e0bf..508ecdd88a 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -19,10 +19,6 @@ struct X; impl Foo for X { type Bar = impl Baz; //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough - //~| ERROR mismatched types - //~| ERROR mismatched types fn bar(&self) -> Self::Bar { |x| x diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs index 4ac7f9423f..cee5e5a01c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs @@ -9,7 +9,6 @@ trait Bug { impl Bug for &() { type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable //~^ ERROR the trait bound `(): Bug` is not satisfied - //~^^ ERROR could not find defining uses const FUN: fn() -> Self::Item = || (); //~^ ERROR type alias impl trait is not permitted here diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 255d381bf0..a9df74689d 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -8,13 +8,13 @@ LL | type Item = impl Bug; = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-60371.rs:14:37 + --> $DIR/issue-60371.rs:13:40 | LL | const FUN: fn() -> Self::Item = || (); - | ^^^^^ + | ^ | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0277]: the trait bound `(): Bug` is not satisfied --> $DIR/issue-60371.rs:10:17 @@ -25,13 +25,7 @@ LL | type Item = impl Bug; = help: the following implementations were found: <&() as Bug> -error: could not find defining uses - --> $DIR/issue-60371.rs:10:17 - | -LL | type Item = impl Bug; - | ^^^^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-60407.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-60407.full_tait.stderr index 5edf73c8ce..9d3f366ad8 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60407.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60407.full_tait.stderr @@ -1,25 +1,17 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-60407.rs:3:32 | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-60407.rs:3:55 - | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - error: fatal error triggered by #[rustc_error] - --> $DIR/issue-60407.rs:12:1 + --> $DIR/issue-60407.rs:11:1 | LL | fn main() { | ^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-60407.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-60407.min_tait.stderr index edb8141c1b..1a3ceafa3e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60407.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60407.min_tait.stderr @@ -1,24 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-60407.rs:9:39 +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-60407.rs:11:1 | -LL | static mut TEST: Option = None; - | ^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable - -error: concrete type differs from previous defining opaque type use - --> $DIR/issue-60407.rs:16:1 - | -LL | fn foo() -> Debuggable { - | ^^^^^^^^^^^^^^^^^^^^^^ expected `[type error]`, got `u32` - | -note: previous use here - --> $DIR/issue-60407.rs:9:1 - | -LL | static mut TEST: Option = None; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn main() { + | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/type-alias-impl-trait/issue-60407.rs b/src/test/ui/type-alias-impl-trait/issue-60407.rs index afcbf313cc..3c6b873b4c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60407.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60407.rs @@ -1,18 +1,18 @@ // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait, rustc_attrs)] -#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete type Debuggable = impl core::fmt::Debug; -static mut TEST: Option = None; //[min_tait]~ ERROR not permitted here +static mut TEST: Option = None; #[rustc_error] -fn main() { //[full_tait]~ ERROR +fn main() { + //~^ ERROR unsafe { TEST = Some(foo()) } } -fn foo() -> Debuggable { //[min_tait]~ ERROR concrete type differs +fn foo() -> Debuggable { 0u32 } diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.rs b/src/test/ui/type-alias-impl-trait/issue-63355.rs new file mode 100644 index 0000000000..8762d189c7 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-63355.rs @@ -0,0 +1,50 @@ +#![feature(min_type_alias_impl_trait)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +pub trait Foo {} + +pub trait Bar { + type Foo: Foo; + + fn foo() -> Self::Foo; +} + +pub trait Baz { + type Foo: Foo; + type Bar: Bar; + + fn foo() -> Self::Foo; + fn bar() -> Self::Bar; +} + +impl Foo for () {} + +impl Bar for () { + type Foo = FooImpl; + + fn foo() -> Self::Foo { + () + } +} + +// FIXME(#86731): The below is illegal use of `min_type_alias_impl_trait` +// but the compiler doesn't report it, we should fix it. +pub type FooImpl = impl Foo; +pub type BarImpl = impl Bar; +//~^ ERROR: type mismatch resolving `<() as Bar>::Foo == ()` + +impl Baz for () { + type Foo = FooImpl; + type Bar = BarImpl; + + fn foo() -> Self::Foo { + () + } + + fn bar() -> Self::Bar { + () + } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-63355.stderr b/src/test/ui/type-alias-impl-trait/issue-63355.stderr new file mode 100644 index 0000000000..dc5370a266 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-63355.stderr @@ -0,0 +1,14 @@ +error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()` + --> $DIR/issue-63355.rs:34:20 + | +LL | pub type FooImpl = impl Foo; + | -------- the found opaque type +LL | pub type BarImpl = impl Bar; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type + | + = note: expected unit type `()` + found opaque type `impl Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.rs b/src/test/ui/type-alias-impl-trait/issue-65384.rs new file mode 100644 index 0000000000..63666c497c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-65384.rs @@ -0,0 +1,16 @@ +#![feature(min_type_alias_impl_trait)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +trait MyTrait {} + +impl MyTrait for () {} + +type Bar = impl MyTrait; + +impl MyTrait for Bar {} +//~^ ERROR: cannot implement trait on type alias impl trait + +fn bazr() -> Bar { } + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-65384.stderr b/src/test/ui/type-alias-impl-trait/issue-65384.stderr new file mode 100644 index 0000000000..01d037266e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-65384.stderr @@ -0,0 +1,14 @@ +error: cannot implement trait on type alias impl trait + --> $DIR/issue-65384.rs:11:1 + | +LL | impl MyTrait for Bar {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: type alias impl trait defined here + --> $DIR/issue-65384.rs:9:12 + | +LL | type Bar = impl MyTrait; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.full_tait.stderr index cf668fc6e0..ee26789d20 100644 --- a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.full_tait.stderr @@ -1,25 +1,17 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:5:32 | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:5:55 - | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - error: fatal error triggered by #[rustc_error] - --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:19:1 + --> $DIR/issue-65679-inst-opaque-ty-from-val-twice.rs:18:1 | LL | fn main() { | ^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs index b7f05bd83e..d37be640e0 100644 --- a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs +++ b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -2,9 +2,8 @@ // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait, rustc_attrs)] -#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete type T = impl Sized; // The concrete type referred by impl-trait-type-alias(`T`) is guaranteed @@ -16,7 +15,8 @@ type T = impl Sized; fn take(_: fn() -> T) {} #[rustc_error] -fn main() { //[full_tait]~ ERROR fatal error triggered by #[rustc_error] +fn main() { + //[full_tait]~^ ERROR fatal error triggered by #[rustc_error] take(|| {}); //[min_tait]~^ ERROR not permitted here take(|| {}); diff --git a/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr b/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr new file mode 100644 index 0000000000..71cc6f61c3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-69323.full.stderr @@ -0,0 +1,11 @@ +warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-69323.rs:5:27 + | +LL | #![cfg_attr(full, feature(type_alias_impl_trait))] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63063 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/type-alias-impl-trait/issue-69323.rs b/src/test/ui/type-alias-impl-trait/issue-69323.rs new file mode 100644 index 0000000000..824558c1b3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-69323.rs @@ -0,0 +1,19 @@ +// check-pass + +// revisions: min full +#![feature(min_type_alias_impl_trait)] +#![cfg_attr(full, feature(type_alias_impl_trait))] +//[full]~^ WARN incomplete + +use std::iter::{once, Chain}; + +fn test1>(x: A) -> Chain> { + x.chain(once(",")) +} + +type I = Chain>; +fn test2>(x: A) -> I { + x.chain(once(",")) +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.rs b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs new file mode 100644 index 0000000000..4b0f2afee5 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs @@ -0,0 +1,19 @@ +#![feature(member_constraints)] +#![feature(type_alias_impl_trait)] +//~^ WARN incomplete + +pub trait A { + type B; + fn f(&self) -> Self::B; +} +impl<'a, 'b> A for () { + //~^ ERROR the lifetime parameter `'a` is not constrained + //~| ERROR the lifetime parameter `'b` is not constrained + type B = impl core::fmt::Debug; + //~^ ERROR is unstable + + + fn f(&self) -> Self::B {} +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr new file mode 100644 index 0000000000..4506a6e23d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr @@ -0,0 +1,34 @@ +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/issue-74761-2.rs:12:14 + | +LL | type B = impl core::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(min_type_alias_impl_trait)]` to the crate attributes to enable + +warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-74761-2.rs:2:12 + | +LL | #![feature(type_alias_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63063 for more information + +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761-2.rs:9:6 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761-2.rs:9:10 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0658. +For more information about an error, try `rustc --explain E0207`. diff --git a/src/test/ui/type-alias-impl-trait/issue-78450.rs b/src/test/ui/type-alias-impl-trait/issue-78450.rs new file mode 100644 index 0000000000..640f929f8f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-78450.rs @@ -0,0 +1,27 @@ +// check-pass + +#![feature(min_type_alias_impl_trait)] +#![feature(type_alias_impl_trait)] +//~^ WARNING: the feature `type_alias_impl_trait` is incomplete + +pub trait AssociatedImpl { + type ImplTrait; + + fn f() -> Self::ImplTrait; +} + +struct S(T); + +trait Associated { + type A; +} + +impl<'a, T: Associated> AssociatedImpl for S { + type ImplTrait = impl core::fmt::Debug; + + fn f() -> Self::ImplTrait { + () + } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-78450.stderr b/src/test/ui/type-alias-impl-trait/issue-78450.stderr new file mode 100644 index 0000000000..efccf6241f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-78450.stderr @@ -0,0 +1,11 @@ +warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-78450.rs:4:12 + | +LL | #![feature(type_alias_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63063 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs b/src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs new file mode 100644 index 0000000000..80a74eb63a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs @@ -0,0 +1,73 @@ +// check-pass + +use std::error::Error as StdError; +use std::pin::Pin; +use std::task::{Context, Poll}; + +pub trait Stream { + type Item; + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + fn size_hint(&self) -> (usize, Option) { + (0, None) + } +} + +pub trait TryStream: Stream { + type Ok; + type Error; + + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>>; +} + +impl TryStream for S +where + S: ?Sized + Stream>, +{ + type Ok = T; + type Error = E; + + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + self.poll_next(cx) + } +} + +pub trait ServerSentEvent: Sized + Send + Sync + 'static {} + +impl ServerSentEvent for T {} + +struct SseKeepAlive { + event_stream: S, +} + +struct SseComment(T); + +impl Stream for SseKeepAlive +where + S: TryStream + Send + 'static, + S::Ok: ServerSentEvent, + S::Error: StdError + Send + Sync + 'static, +{ + type Item = Result, ()>; + fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll> { + unimplemented!() + } +} + +pub fn keep( + event_stream: S, +) -> impl TryStream + Send + 'static +where + S: TryStream + Send + 'static, + S::Ok: ServerSentEvent + Send, + S::Error: StdError + Send + Sync + 'static, +{ + SseKeepAlive { event_stream } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs index 38aa18fe40..11756017ad 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs @@ -5,9 +5,9 @@ #![feature(min_type_alias_impl_trait)] type X = impl ToString; -//~^ ERROR could not find defining uses fn f(a: A, b: B) -> (X, X) { + //~^ ERROR concrete type differs from previous defining opaque type (a.clone(), a) } diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr index c00973c076..52b0462de9 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -1,8 +1,14 @@ -error: could not find defining uses - --> $DIR/multiple-def-uses-in-one-fn2.rs:7:52 +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1 | -LL | type X = impl ToString; - | ^^^^^^^^^^^^^ +LL | fn f(a: A, b: B) -> (X, X) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `B` + | +note: previous use here + --> $DIR/multiple-def-uses-in-one-fn2.rs:9:1 + | +LL | fn f(a: A, b: B) -> (X, X) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs index 17e9000581..5f25365666 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs @@ -11,6 +11,7 @@ fn f(a: A, b: B) -> (X, X) } fn g(a: A, b: B) -> (X, X) { + //~^ ERROR concrete type differs from previous defining opaque type (a, b) //~^ ERROR mismatched types } diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr index bbe709dcca..3d943b77af 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -1,10 +1,11 @@ error[E0308]: mismatched types - --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9 + --> $DIR/multiple-def-uses-in-one-fn3.rs:15:9 | LL | fn g(a: A, b: B) -> (X, X) { | - - found type parameter | | | expected type parameter +LL | LL | (a, b) | ^ expected type parameter `A`, found type parameter `B` | @@ -13,6 +14,18 @@ LL | (a, b) = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn3.rs:13:1 + | +LL | fn g(a: A, b: B) -> (X, X) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]` + | +note: previous use here + --> $DIR/multiple-def-uses-in-one-fn3.rs:9:1 + | +LL | fn f(a: A, b: B) -> (X, X) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.full_tait.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.full_tait.stderr index 40949c84d2..faddecb217 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.full_tait.stderr @@ -1,25 +1,17 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/no_inferrable_concrete_type.rs:6:32 | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/no_inferrable_concrete_type.rs:6:55 - | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - error: could not find defining uses - --> $DIR/no_inferrable_concrete_type.rs:10:12 + --> $DIR/no_inferrable_concrete_type.rs:9:12 | LL | type Foo = impl Copy; | ^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.min_tait.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.min_tait.stderr index d69e4cccdf..3194bd7610 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.min_tait.stderr @@ -1,18 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/no_inferrable_concrete_type.rs:16:12 - | -LL | let _: Foo = std::mem::transmute(0u8); - | ^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable - error: could not find defining uses - --> $DIR/no_inferrable_concrete_type.rs:10:12 + --> $DIR/no_inferrable_concrete_type.rs:9:12 | LL | type Foo = impl Copy; | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs index 8ff588ef27..409eec7250 100644 --- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs +++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -3,15 +3,16 @@ // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] -#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete type Foo = impl Copy; //~ could not find defining uses // make compiler happy about using 'Foo' -fn bar(x: Foo) -> Foo { x } +fn bar(x: Foo) -> Foo { + x +} fn main() { - let _: Foo = std::mem::transmute(0u8); //[min_tait]~ ERROR not permitted here + let _: Foo = std::mem::transmute(0u8); } diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.full_tait.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.full_tait.stderr index b560c0c918..d5a4fa52df 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.full_tait.stderr @@ -1,25 +1,17 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/structural-match-no-leak.rs:4:32 | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/structural-match-no-leak.rs:4:55 - | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - error: `impl Send` cannot be used in patterns - --> $DIR/structural-match-no-leak.rs:19:9 + --> $DIR/structural-match-no-leak.rs:18:9 | LL | LEAK_FREE => (), | ^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.min_tait.stderr b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.min_tait.stderr index e962b23a58..b7caf8ed29 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.min_tait.stderr @@ -1,12 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/structural-match-no-leak.rs:15:24 +error: `impl Send` cannot be used in patterns + --> $DIR/structural-match-no-leak.rs:18:9 | -LL | const LEAK_FREE: Bar = leak_free(); - | ^^^^^^^^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable +LL | LEAK_FREE => (), + | ^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs index d0bae30f99..e2b10e7355 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -1,9 +1,8 @@ #![feature(const_impl_trait)] // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] -#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete type Bar = impl Send; @@ -12,12 +11,12 @@ type Bar = impl Send; const fn leak_free() -> Bar { 7i32 } -const LEAK_FREE: Bar = leak_free(); //[min_tait]~ ERROR not permitted here +const LEAK_FREE: Bar = leak_free(); fn leak_free_test() { match todo!() { LEAK_FREE => (), - //[full_tait]~^ `impl Send` cannot be used in patterns + //~^ `impl Send` cannot be used in patterns _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/structural-match.full_tait.stderr b/src/test/ui/type-alias-impl-trait/structural-match.full_tait.stderr index b94e06e6d0..d394c99df8 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match.full_tait.stderr @@ -1,25 +1,17 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/structural-match.rs:4:32 | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/structural-match.rs:4:55 - | -LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #63065 for more information - error: `impl Send` cannot be used in patterns - --> $DIR/structural-match.rs:20:9 + --> $DIR/structural-match.rs:19:9 | LL | VALUE => (), | ^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/structural-match.min_tait.stderr b/src/test/ui/type-alias-impl-trait/structural-match.min_tait.stderr index 36c49a954b..f63b1fb23d 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/structural-match.min_tait.stderr @@ -1,12 +1,8 @@ -error[E0658]: type alias impl trait is not permitted here - --> $DIR/structural-match.rs:16:20 +error: `impl Send` cannot be used in patterns + --> $DIR/structural-match.rs:19:9 | -LL | const VALUE: Foo = value(); - | ^^^^^^^ - | - = note: see issue #63065 for more information - = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable +LL | VALUE => (), + | ^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs index daf914cc49..aed9334b3c 100644 --- a/src/test/ui/type-alias-impl-trait/structural-match.rs +++ b/src/test/ui/type-alias-impl-trait/structural-match.rs @@ -1,9 +1,8 @@ #![feature(const_impl_trait)] // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] -#![cfg_attr(full_tait, feature(type_alias_impl_trait, impl_trait_in_bindings))] +#![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -//[full_tait]~| WARN incomplete type Foo = impl Send; @@ -13,12 +12,12 @@ struct A; const fn value() -> Foo { A } -const VALUE: Foo = value(); //[min_tait]~ ERROR not permitted here +const VALUE: Foo = value(); fn test() { match todo!() { VALUE => (), - //[full_tait]~^ `impl Send` cannot be used in patterns + //~^ `impl Send` cannot be used in patterns _ => (), } } diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.full_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.full_tait.stderr index 894d61502a..6f817757cc 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.full_tait.stderr @@ -1,5 +1,5 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/type-alias-impl-trait-const.rs:5:32 + --> $DIR/type-alias-impl-trait-const.rs:3:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,13 +7,24 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/type-alias-impl-trait-const.rs:11:12 +error[E0308]: mismatched types + --> $DIR/type-alias-impl-trait-const.rs:13:19 | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | pub type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | const _FOO: Foo = 5; + | ^ expected opaque type, found integer | - = note: see issue #63065 for more information + = note: expected opaque type `impl Debug` + found type `{integer}` -warning: 2 warnings emitted +error: could not find defining uses + --> $DIR/type-alias-impl-trait-const.rs:10:16 + | +LL | pub type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.min_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.min_tait.stderr index 66e4c24216..ce98318333 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.min_tait.stderr @@ -1,11 +1,21 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/type-alias-impl-trait-const.rs:11:12 +error[E0308]: mismatched types + --> $DIR/type-alias-impl-trait-const.rs:13:19 | -LL | #![feature(impl_trait_in_bindings)] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | pub type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | const _FOO: Foo = 5; + | ^ expected opaque type, found integer | - = note: `#[warn(incomplete_features)]` on by default - = note: see issue #63065 for more information + = note: expected opaque type `impl Debug` + found type `{integer}` -warning: 1 warning emitted +error: could not find defining uses + --> $DIR/type-alias-impl-trait-const.rs:10:16 + | +LL | pub type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs index 0b0551cd96..751512c5df 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs @@ -1,23 +1,16 @@ -// check-pass - // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete -// Currently, the `type_alias_impl_trait` feature implicitly -// depends on `impl_trait_in_bindings` in order to work properly. -// Specifically, this line requires `impl_trait_in_bindings` to be enabled: -// https://github.com/rust-lang/rust/blob/481068a707679257e2a738b40987246e0420e787/compiler/rustc_typeck/check/mod.rs#L856 -#![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete // Ensures that `const` items can constrain an opaque `impl Trait`. use std::fmt::Debug; pub type Foo = impl Debug; +//~^ ERROR could not find defining uses const _FOO: Foo = 5; +//~^ ERROR mismatched types [E0308] -fn main() { -} +fn main() {} diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index ddfa31cf62..adf3fa2c80 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -23,28 +23,37 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/type-check-defaults.rs:11:17 | LL | struct Bounds(T); - | ----------------^^^^------------ - | | | - | | the trait `Copy` is not implemented for `String` - | required by `Bounds` + | ^^^^ the trait `Copy` is not implemented for `String` + | +note: required by `Bounds` + --> $DIR/type-check-defaults.rs:11:1 + | +LL | struct Bounds(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/type-check-defaults.rs:14:42 | LL | struct WhereClause(T) where T: Copy; - | -----------------------------------------^^^^- - | | | - | | the trait `Copy` is not implemented for `String` - | required by `WhereClause` + | ^^^^ the trait `Copy` is not implemented for `String` + | +note: required by `WhereClause` + --> $DIR/type-check-defaults.rs:14:1 + | +LL | struct WhereClause(T) where T: Copy; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/type-check-defaults.rs:17:20 | LL | trait TraitBound {} - | -------------------^^^^-------- - | | | - | | the trait `Copy` is not implemented for `String` - | required by `TraitBound` + | ^^^^ the trait `Copy` is not implemented for `String` + | +note: required by `TraitBound` + --> $DIR/type-check-defaults.rs:17:1 + | +LL | trait TraitBound {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/type-check-defaults.rs:21:25 @@ -63,12 +72,14 @@ error[E0277]: cannot add `u8` to `i32` --> $DIR/type-check-defaults.rs:24:66 | LL | trait ProjectionPred> where T::Item : Add {} - | -----------------------------------------------------------------^^^^^^^ - | | | - | | no implementation for `i32 + u8` - | required by `ProjectionPred` + | ^^^^^^^ no implementation for `i32 + u8` | = help: the trait `Add` is not implemented for `i32` +note: required by `ProjectionPred` + --> $DIR/type-check-defaults.rs:24:1 + | +LL | trait ProjectionPred> where T::Item : Add {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr index e0039f2a31..a6b41520d6 100644 --- a/src/test/ui/type/type-params-in-different-spaces-2.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr @@ -1,12 +1,14 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:10:9 | -LL | fn op(_: T) -> Self; - | -------------------- required by `Tr::op` -... LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` | +note: required by `Tr::op` + --> $DIR/type-params-in-different-spaces-2.rs:5:5 + | +LL | fn op(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^ help: consider further restricting `Self` | LL | fn test(u: U) -> Self where Self: Tr { @@ -15,12 +17,14 @@ LL | fn test(u: U) -> Self where Self: Tr { error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:16:9 | -LL | fn op(_: T) -> Self; - | -------------------- required by `Tr::op` -... LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` | +note: required by `Tr::op` + --> $DIR/type-params-in-different-spaces-2.rs:5:5 + | +LL | fn op(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^ help: consider further restricting `Self` | LL | fn test(u: U) -> Self where Self: Tr { diff --git a/src/test/ui/conversion-methods.rs b/src/test/ui/typeck/conversion-methods.rs similarity index 100% rename from src/test/ui/conversion-methods.rs rename to src/test/ui/typeck/conversion-methods.rs diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/typeck/conversion-methods.stderr similarity index 100% rename from src/test/ui/conversion-methods.stderr rename to src/test/ui/typeck/conversion-methods.stderr diff --git a/src/test/ui/issues/issue-74086.rs b/src/test/ui/typeck/issue-74086.rs similarity index 71% rename from src/test/ui/issues/issue-74086.rs rename to src/test/ui/typeck/issue-74086.rs index f68a665b2f..1de9cd8007 100644 --- a/src/test/ui/issues/issue-74086.rs +++ b/src/test/ui/typeck/issue-74086.rs @@ -1,4 +1,4 @@ fn main() { static BUG: fn(_) -> u8 = |_| 8; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121] + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions [E0121] } diff --git a/src/test/ui/issues/issue-74086.stderr b/src/test/ui/typeck/issue-74086.stderr similarity index 89% rename from src/test/ui/issues/issue-74086.stderr rename to src/test/ui/typeck/issue-74086.stderr index e602425059..ac1752e17d 100644 --- a/src/test/ui/issues/issue-74086.stderr +++ b/src/test/ui/typeck/issue-74086.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/issue-74086.rs:2:20 | LL | static BUG: fn(_) -> u8 = |_| 8; diff --git a/src/test/ui/typeck/issue-75883.rs b/src/test/ui/typeck/issue-75883.rs index 8cd34f4883..0d1534df09 100644 --- a/src/test/ui/typeck/issue-75883.rs +++ b/src/test/ui/typeck/issue-75883.rs @@ -5,7 +5,7 @@ pub struct UI {} impl UI { pub fn run() -> Result<_> { //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied - //~| ERROR: the type placeholder `_` is not allowed within types on item signatures + //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types let mut ui = UI {}; ui.interact(); @@ -14,7 +14,7 @@ impl UI { pub fn interact(&mut self) -> Result<_> { //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied - //~| ERROR: the type placeholder `_` is not allowed within types on item signatures + //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for return types unimplemented!(); } } diff --git a/src/test/ui/typeck/issue-75883.stderr b/src/test/ui/typeck/issue-75883.stderr index 71f4138c81..a722c4b5e3 100644 --- a/src/test/ui/typeck/issue-75883.stderr +++ b/src/test/ui/typeck/issue-75883.stderr @@ -34,13 +34,13 @@ help: add missing generic argument LL | pub fn interact(&mut self) -> Result<_, E> { | ^^^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-75883.rs:15:42 | LL | pub fn interact(&mut self) -> Result<_> { | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-75883.rs:6:28 | LL | pub fn run() -> Result<_> { diff --git a/src/test/ui/typeck/issue-75889.rs b/src/test/ui/typeck/issue-75889.rs new file mode 100644 index 0000000000..84c067ed0c --- /dev/null +++ b/src/test/ui/typeck/issue-75889.rs @@ -0,0 +1,6 @@ +// Regression test for #75889. + +const FOO: dyn Fn() -> _ = ""; //~ ERROR E0121 +static BOO: dyn Fn() -> _ = ""; //~ ERROR E0121 + +fn main() {} diff --git a/src/test/ui/typeck/issue-75889.stderr b/src/test/ui/typeck/issue-75889.stderr new file mode 100644 index 0000000000..de4bdf4e6d --- /dev/null +++ b/src/test/ui/typeck/issue-75889.stderr @@ -0,0 +1,15 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constant items + --> $DIR/issue-75889.rs:3:24 + | +LL | const FOO: dyn Fn() -> _ = ""; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static items + --> $DIR/issue-75889.rs:4:25 + | +LL | static BOO: dyn Fn() -> _ = ""; + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/issue-80779.rs b/src/test/ui/typeck/issue-80779.rs index 6791976196..99a93b1863 100644 --- a/src/test/ui/typeck/issue-80779.rs +++ b/src/test/ui/typeck/issue-80779.rs @@ -3,11 +3,11 @@ pub struct T<'a>(&'a str); pub fn f<'a>(val: T<'a>) -> _ { - //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types g(val) } pub fn g(_: T<'static>) -> _ {} -//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for return types fn main() {} diff --git a/src/test/ui/typeck/issue-80779.stderr b/src/test/ui/typeck/issue-80779.stderr index aca494520f..5a695fecc2 100644 --- a/src/test/ui/typeck/issue-80779.stderr +++ b/src/test/ui/typeck/issue-80779.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80779.rs:10:28 | LL | pub fn g(_: T<'static>) -> _ {} @@ -7,7 +7,7 @@ LL | pub fn g(_: T<'static>) -> _ {} | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/issue-80779.rs:5:29 | LL | pub fn f<'a>(val: T<'a>) -> _ { diff --git a/src/test/ui/issues/issue-81885.rs b/src/test/ui/typeck/issue-81885.rs similarity index 62% rename from src/test/ui/issues/issue-81885.rs rename to src/test/ui/typeck/issue-81885.rs index 86c39d4a48..5117f250fe 100644 --- a/src/test/ui/issues/issue-81885.rs +++ b/src/test/ui/typeck/issue-81885.rs @@ -1,10 +1,8 @@ const TEST4: fn() -> _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item - //signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn main() { const TEST5: fn() -> _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item - //signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions } diff --git a/src/test/ui/issues/issue-81885.stderr b/src/test/ui/typeck/issue-81885.stderr similarity index 82% rename from src/test/ui/issues/issue-81885.stderr rename to src/test/ui/typeck/issue-81885.stderr index 955b428387..8206156a61 100644 --- a/src/test/ui/issues/issue-81885.stderr +++ b/src/test/ui/typeck/issue-81885.stderr @@ -1,11 +1,11 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/issue-81885.rs:1:22 | LL | const TEST4: fn() -> _ = 42; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/issue-81885.rs:6:26 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/issue-81885.rs:5:26 | LL | const TEST5: fn() -> _ = 42; | ^ not allowed in type signatures diff --git a/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr index b1bec4c082..7c5cf1082b 100644 --- a/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr +++ b/src/test/ui/typeck/issue-83621-placeholder-static-in-extern.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/issue-83621-placeholder-static-in-extern.rs:4:15 | LL | static x: _; diff --git a/src/test/ui/typeck/issue-84160.rs b/src/test/ui/typeck/issue-84160.rs new file mode 100644 index 0000000000..7b444df852 --- /dev/null +++ b/src/test/ui/typeck/issue-84160.rs @@ -0,0 +1,9 @@ +fn mismatched_types_with_reference(x: &u32) -> &u32 { + if false { + return x; + } + return "test"; + //~^ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-84160.stderr b/src/test/ui/typeck/issue-84160.stderr new file mode 100644 index 0000000000..24c188b3fc --- /dev/null +++ b/src/test/ui/typeck/issue-84160.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-84160.rs:5:12 + | +LL | fn mismatched_types_with_reference(x: &u32) -> &u32 { + | ---- expected `&u32` because of return type +... +LL | return "test"; + | ^^^^^^ expected `u32`, found `str` + | + = note: expected reference `&u32` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr new file mode 100644 index 0000000000..b1111fcf14 --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:9:22 + | +LL | const U: usize = return; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr new file mode 100644 index 0000000000..f489ae2002 --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:15:20 + | +LL | fn foo(a: [(); return]); + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rs b/src/test/ui/typeck/issue-86721-return-expr-ice.rs new file mode 100644 index 0000000000..cd7135f18b --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rs @@ -0,0 +1,17 @@ +// Regression test for the ICE described in #86721. + +// revisions: rev1 rev2 +#![cfg_attr(any(), rev1, rev2)] +#![crate_type="lib"] + +#[cfg(any(rev1))] +trait T { + const U: usize = return; + //[rev1]~^ ERROR: return statement outside of function body [E0572] +} + +#[cfg(any(rev2))] +trait T2 { + fn foo(a: [(); return]); + //[rev2]~^ ERROR: return statement outside of function body [E0572] +} diff --git a/src/test/ui/typeck/struct-enum-wrong-args.rs b/src/test/ui/typeck/struct-enum-wrong-args.rs new file mode 100644 index 0000000000..19de4d6772 --- /dev/null +++ b/src/test/ui/typeck/struct-enum-wrong-args.rs @@ -0,0 +1,14 @@ +// Regression test of #86481. +struct Wrapper(i32); +struct DoubleWrapper(i32, i32); + +fn main() { + let _ = Some(3, 2); //~ ERROR this enum variant takes + let _ = Ok(3, 6, 2); //~ ERROR this enum variant takes + let _ = Ok(); //~ ERROR this enum variant takes + let _ = Wrapper(); //~ ERROR this struct takes + let _ = Wrapper(5, 2); //~ ERROR this struct takes + let _ = DoubleWrapper(); //~ ERROR this struct takes + let _ = DoubleWrapper(5); //~ ERROR this struct takes + let _ = DoubleWrapper(5, 2, 7); //~ ERROR this struct takes +} diff --git a/src/test/ui/typeck/struct-enum-wrong-args.stderr b/src/test/ui/typeck/struct-enum-wrong-args.stderr new file mode 100644 index 0000000000..d77ef73028 --- /dev/null +++ b/src/test/ui/typeck/struct-enum-wrong-args.stderr @@ -0,0 +1,67 @@ +error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:6:13 + | +LL | let _ = Some(3, 2); + | ^^^^ - - supplied 2 arguments + | | + | expected 1 argument + +error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:7:13 + | +LL | let _ = Ok(3, 6, 2); + | ^^ - - - supplied 3 arguments + | | + | expected 1 argument + +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:8:13 + | +LL | let _ = Ok(); + | ^^-- supplied 0 arguments + | | + | expected 1 argument + +error[E0061]: this struct takes 1 argument but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:9:13 + | +LL | let _ = Wrapper(); + | ^^^^^^^-- supplied 0 arguments + | | + | expected 1 argument + +error[E0061]: this struct takes 1 argument but 2 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:10:13 + | +LL | let _ = Wrapper(5, 2); + | ^^^^^^^ - - supplied 2 arguments + | | + | expected 1 argument + +error[E0061]: this struct takes 2 arguments but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:11:13 + | +LL | let _ = DoubleWrapper(); + | ^^^^^^^^^^^^^-- supplied 0 arguments + | | + | expected 2 arguments + +error[E0061]: this struct takes 2 arguments but 1 argument was supplied + --> $DIR/struct-enum-wrong-args.rs:12:13 + | +LL | let _ = DoubleWrapper(5); + | ^^^^^^^^^^^^^ - supplied 1 argument + | | + | expected 2 arguments + +error[E0061]: this struct takes 2 arguments but 3 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:13:13 + | +LL | let _ = DoubleWrapper(5, 2, 7); + | ^^^^^^^^^^^^^ - - - supplied 3 arguments + | | + | expected 2 arguments + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.rs b/src/test/ui/typeck/type-placeholder-fn-in-const.rs new file mode 100644 index 0000000000..f657bea164 --- /dev/null +++ b/src/test/ui/typeck/type-placeholder-fn-in-const.rs @@ -0,0 +1,14 @@ +struct MyStruct; + +trait Test { + const TEST: fn() -> _; + //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: the type placeholder `_` is not allowed within types on item signatures for constants [E0121] +} + +impl Test for MyStruct { + const TEST: fn() -> _ = 42; + //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures for functions [E0121] +} + +fn main() {} diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.stderr b/src/test/ui/typeck/type-placeholder-fn-in-const.stderr new file mode 100644 index 0000000000..62f4db8638 --- /dev/null +++ b/src/test/ui/typeck/type-placeholder-fn-in-const.stderr @@ -0,0 +1,21 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/type-placeholder-fn-in-const.rs:4:25 + | +LL | const TEST: fn() -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/type-placeholder-fn-in-const.rs:4:25 + | +LL | const TEST: fn() -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/type-placeholder-fn-in-const.rs:10:25 + | +LL | const TEST: fn() -> _ = 42; + | ^ not allowed in type signatures + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck-closure-to-unsafe-fn-ptr.rs b/src/test/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs similarity index 100% rename from src/test/ui/typeck-closure-to-unsafe-fn-ptr.rs rename to src/test/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs diff --git a/src/test/ui/typeck-fn-to-unsafe-fn-ptr.rs b/src/test/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs similarity index 100% rename from src/test/ui/typeck-fn-to-unsafe-fn-ptr.rs rename to src/test/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs diff --git a/src/test/ui/typeck_type_placeholder_1.rs b/src/test/ui/typeck/typeck_type_placeholder_1.rs similarity index 100% rename from src/test/ui/typeck_type_placeholder_1.rs rename to src/test/ui/typeck/typeck_type_placeholder_1.rs diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr index bd7cbd444d..b6aea9586b 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr @@ -1,35 +1,35 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:158:18 + --> $DIR/typeck_type_placeholder_item.rs:157:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:161:16 + --> $DIR/typeck_type_placeholder_item.rs:160:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:19 + --> $DIR/typeck_type_placeholder_item.rs:170:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:176:19 + --> $DIR/typeck_type_placeholder_item.rs:175:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:209:5 + --> $DIR/typeck_type_placeholder_item.rs:208:5 | LL | const C: _; | ^^^^^^^^^^- @@ -37,7 +37,7 @@ LL | const C: _; | help: provide a definition for the constant: `= ;` error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:171:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -53,7 +53,7 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:10:14 | LL | fn test() -> _ { 5 } @@ -62,7 +62,7 @@ LL | fn test() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:13:16 | LL | fn test2() -> (_, _) { (5, 5) } @@ -72,7 +72,7 @@ LL | fn test2() -> (_, _) { (5, 5) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:16:15 | LL | static TEST3: _ = "test"; @@ -81,7 +81,7 @@ LL | static TEST3: _ = "test"; | not allowed in type signatures | help: replace with the correct type: `&str` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:19:15 | LL | static TEST4: _ = 145; @@ -90,13 +90,13 @@ LL | static TEST4: _ = 145; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:22:15 | LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:25:13 | LL | fn test6(_: _) { } @@ -107,7 +107,7 @@ help: use type parameters instead LL | fn test6(_: T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:28:18 | LL | fn test6_b(_: _, _: T) { } @@ -118,7 +118,7 @@ help: use type parameters instead LL | fn test6_b(_: U, _: T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:31:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } @@ -129,7 +129,7 @@ help: use type parameters instead LL | fn test6_c(_: U, _: (T, K, L, A, B)) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:34:13 | LL | fn test7(x: _) { let _x: usize = x; } @@ -140,7 +140,7 @@ help: use type parameters instead LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:37:22 | LL | fn test8(_f: fn() -> _) { } @@ -149,7 +149,7 @@ LL | fn test8(_f: fn() -> _) { } | not allowed in type signatures | help: use type parameters instead: `T` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:37:22 | LL | fn test8(_f: fn() -> _) { } @@ -160,7 +160,7 @@ help: use type parameters instead LL | fn test8(_f: fn() -> T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:51:26 | LL | fn test11(x: &usize) -> &_ { @@ -169,7 +169,7 @@ LL | fn test11(x: &usize) -> &_ { | |not allowed in type signatures | help: replace with the correct return type: `&'static &'static usize` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:56:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { @@ -178,7 +178,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | | not allowed in type signatures | help: replace with the correct return type: `*const *const usize` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:70:8 | LL | a: _, @@ -201,9 +201,9 @@ error: missing type for `static` item --> $DIR/typeck_type_placeholder_item.rs:76:12 | LL | static A = 42; - | ^ help: provide a type for the item: `A: i32` + | ^ help: provide a type for the static variable: `A: i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:78:15 | LL | static B: _ = 42; @@ -212,14 +212,14 @@ LL | static B: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:80:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:83:21 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:82:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -227,8 +227,8 @@ LL | fn fn_test() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:86:23 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:85:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -237,8 +237,8 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:89:22 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:88:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -246,8 +246,8 @@ LL | static FN_TEST3: _ = "test"; | not allowed in type signatures | help: replace with the correct type: `&str` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:92:22 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:91:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -255,14 +255,14 @@ LL | static FN_TEST4: _ = 145; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:95:22 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:94:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:98:20 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:97:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -272,8 +272,8 @@ help: use type parameters instead LL | fn fn_test6(_: T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:101:20 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:100:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -283,8 +283,8 @@ help: use type parameters instead LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:104:29 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:103:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ @@ -292,8 +292,8 @@ LL | fn fn_test8(_f: fn() -> _) { } | not allowed in type signatures | help: use type parameters instead: `T` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:104:29 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:103:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -303,8 +303,8 @@ help: use type parameters instead LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:127:12 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:126:12 | LL | a: _, | ^ not allowed in type signatures @@ -323,21 +323,21 @@ LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:132:18 + --> $DIR/typeck_type_placeholder_item.rs:131:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:132:28 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:131:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures | | | not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:136:30 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:135:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -346,8 +346,8 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:139:33 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:138:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -355,8 +355,8 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | | not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:21 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:157:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -366,8 +366,8 @@ help: use type parameters instead LL | struct BadStruct(T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:163:15 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for implementations + --> $DIR/typeck_type_placeholder_item.rs:162:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -379,14 +379,14 @@ help: use type parameters instead LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:166:34 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types + --> $DIR/typeck_type_placeholder_item.rs:165:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:171:25 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:170:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -396,8 +396,8 @@ help: use type parameters instead LL | struct BadStruct1(T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:176:25 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:175:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -407,20 +407,20 @@ help: use type parameters instead LL | struct BadStruct2(U, T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:180:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases + --> $DIR/typeck_type_placeholder_item.rs:179:14 | LL | type X = Box<_>; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types + --> $DIR/typeck_type_placeholder_item.rs:185:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:220:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:219:31 | LL | fn value() -> Option<&'static _> { | ----------------^- @@ -428,8 +428,8 @@ LL | fn value() -> Option<&'static _> { | | not allowed in type signatures | help: replace with the correct return type: `Option<&'static u8>` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:225:10 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:224:10 | LL | const _: Option<_> = map(value); | ^^^^^^^^^ @@ -437,8 +437,8 @@ LL | const _: Option<_> = map(value); | not allowed in type signatures | help: replace with the correct type: `Option` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:144:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:143:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -448,8 +448,8 @@ help: use type parameters instead LL | fn method_test1(&self, x: T); | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:146:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:145:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -461,8 +461,8 @@ help: use type parameters instead LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:148:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:147:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -472,8 +472,8 @@ help: use type parameters instead LL | fn method_test3(&self) -> T; | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:150:26 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:149:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -483,8 +483,8 @@ help: use type parameters instead LL | fn assoc_fn_test1(x: T); | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:152:26 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:151:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -496,8 +496,8 @@ help: use type parameters instead LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:154:28 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:153:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -507,20 +507,20 @@ help: use type parameters instead LL | fn assoc_fn_test3() -> T; | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:194:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:193:14 | LL | type B = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:196:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:195:14 | LL | const C: _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:198:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:197:14 | LL | const D: _ = 42; | ^ @@ -528,13 +528,13 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:201:26 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:200:26 | LL | type F: std::ops::Fn(_); | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:44:24 | LL | fn test9(&self) -> _ { () } @@ -543,7 +543,7 @@ LL | fn test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:47:27 | LL | fn test10(&self, _x : _) { } @@ -554,7 +554,7 @@ help: use type parameters instead LL | fn test10(&self, _x : T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:62:24 | LL | fn clone(&self) -> _ { Test9 } @@ -563,7 +563,7 @@ LL | fn clone(&self) -> _ { Test9 } | not allowed in type signatures | help: replace with the correct return type: `Test9` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:65:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } @@ -574,8 +574,8 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:110:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -583,8 +583,8 @@ LL | fn fn_test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:114:34 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:113:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -594,8 +594,8 @@ help: use type parameters instead LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:119:28 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:118:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -603,8 +603,8 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `FnTest9` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:41 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:121:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -614,26 +614,26 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:205:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:204:14 | LL | type A = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:207:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:206:14 | LL | type B = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:209:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:208:14 | LL | const C: _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:212:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:211:14 | LL | const D: _ = 42; | ^ diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr index afd6aaf4e5..88cc3bfc7f 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr @@ -1,35 +1,35 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:158:18 + --> $DIR/typeck_type_placeholder_item.rs:157:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:161:16 + --> $DIR/typeck_type_placeholder_item.rs:160:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:19 + --> $DIR/typeck_type_placeholder_item.rs:170:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:176:19 + --> $DIR/typeck_type_placeholder_item.rs:175:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:209:5 + --> $DIR/typeck_type_placeholder_item.rs:208:5 | LL | const C: _; | ^^^^^^^^^^- @@ -37,14 +37,14 @@ LL | const C: _; | help: provide a definition for the constant: `= ;` error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:171:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used | | | first use of `_` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:10:14 | LL | fn test() -> _ { 5 } @@ -53,7 +53,7 @@ LL | fn test() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:13:16 | LL | fn test2() -> (_, _) { (5, 5) } @@ -63,7 +63,7 @@ LL | fn test2() -> (_, _) { (5, 5) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:16:15 | LL | static TEST3: _ = "test"; @@ -72,7 +72,7 @@ LL | static TEST3: _ = "test"; | not allowed in type signatures | help: replace with the correct type: `&str` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:19:15 | LL | static TEST4: _ = 145; @@ -81,13 +81,13 @@ LL | static TEST4: _ = 145; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:22:15 | LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:25:13 | LL | fn test6(_: _) { } @@ -98,7 +98,7 @@ help: use type parameters instead LL | fn test6(_: T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:28:18 | LL | fn test6_b(_: _, _: T) { } @@ -109,7 +109,7 @@ help: use type parameters instead LL | fn test6_b(_: U, _: T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:31:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } @@ -120,7 +120,7 @@ help: use type parameters instead LL | fn test6_c(_: U, _: (T, K, L, A, B)) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:34:13 | LL | fn test7(x: _) { let _x: usize = x; } @@ -131,7 +131,7 @@ help: use type parameters instead LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:37:22 | LL | fn test8(_f: fn() -> _) { } @@ -140,7 +140,7 @@ LL | fn test8(_f: fn() -> _) { } | not allowed in type signatures | help: use type parameters instead: `T` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:37:22 | LL | fn test8(_f: fn() -> _) { } @@ -151,7 +151,7 @@ help: use type parameters instead LL | fn test8(_f: fn() -> T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:51:26 | LL | fn test11(x: &usize) -> &_ { @@ -160,7 +160,7 @@ LL | fn test11(x: &usize) -> &_ { | |not allowed in type signatures | help: replace with the correct return type: `&'static &'static usize` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:56:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { @@ -169,7 +169,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | | not allowed in type signatures | help: replace with the correct return type: `*const *const usize` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:70:8 | LL | a: _, @@ -192,9 +192,9 @@ error: missing type for `static` item --> $DIR/typeck_type_placeholder_item.rs:76:12 | LL | static A = 42; - | ^ help: provide a type for the item: `A: i32` + | ^ help: provide a type for the static variable: `A: i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:78:15 | LL | static B: _ = 42; @@ -203,14 +203,14 @@ LL | static B: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables --> $DIR/typeck_type_placeholder_item.rs:80:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:83:21 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:82:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -218,8 +218,8 @@ LL | fn fn_test() -> _ { 5 } | not allowed in type signatures | help: replace with the correct return type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:86:23 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:85:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -228,8 +228,8 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:89:22 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:88:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -237,8 +237,8 @@ LL | static FN_TEST3: _ = "test"; | not allowed in type signatures | help: replace with the correct type: `&str` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:92:22 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:91:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -246,14 +246,14 @@ LL | static FN_TEST4: _ = 145; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:95:22 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:94:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:98:20 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:97:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -263,8 +263,8 @@ help: use type parameters instead LL | fn fn_test6(_: T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:101:20 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:100:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -274,8 +274,8 @@ help: use type parameters instead LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:104:29 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:103:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ @@ -283,8 +283,8 @@ LL | fn fn_test8(_f: fn() -> _) { } | not allowed in type signatures | help: use type parameters instead: `T` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:104:29 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:103:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -294,8 +294,8 @@ help: use type parameters instead LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:127:12 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:126:12 | LL | a: _, | ^ not allowed in type signatures @@ -314,21 +314,21 @@ LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:132:18 + --> $DIR/typeck_type_placeholder_item.rs:131:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:132:28 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:131:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures | | | not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:136:30 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:135:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -337,8 +337,8 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | |not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:139:33 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:138:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -346,8 +346,8 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | | not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:21 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:157:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -357,8 +357,8 @@ help: use type parameters instead LL | struct BadStruct(T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:163:15 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for implementations + --> $DIR/typeck_type_placeholder_item.rs:162:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -370,14 +370,14 @@ help: use type parameters instead LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:166:34 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types + --> $DIR/typeck_type_placeholder_item.rs:165:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:171:25 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:170:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -387,8 +387,8 @@ help: use type parameters instead LL | struct BadStruct1(T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:176:25 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:175:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -398,20 +398,20 @@ help: use type parameters instead LL | struct BadStruct2(U, T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:180:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases + --> $DIR/typeck_type_placeholder_item.rs:179:14 | LL | type X = Box<_>; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types + --> $DIR/typeck_type_placeholder_item.rs:185:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:220:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:219:31 | LL | fn value() -> Option<&'static _> { | ----------------^- @@ -419,8 +419,8 @@ LL | fn value() -> Option<&'static _> { | | not allowed in type signatures | help: replace with the correct return type: `Option<&'static u8>` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:225:10 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:224:10 | LL | const _: Option<_> = map(value); | ^^^^^^^^^ @@ -428,8 +428,8 @@ LL | const _: Option<_> = map(value); | not allowed in type signatures | help: replace with the correct type: `Option` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:144:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:143:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -439,8 +439,8 @@ help: use type parameters instead LL | fn method_test1(&self, x: T); | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:146:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:145:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -452,8 +452,8 @@ help: use type parameters instead LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:148:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:147:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -463,8 +463,8 @@ help: use type parameters instead LL | fn method_test3(&self) -> T; | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:150:26 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:149:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -474,8 +474,8 @@ help: use type parameters instead LL | fn assoc_fn_test1(x: T); | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:152:26 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:151:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -487,8 +487,8 @@ help: use type parameters instead LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:154:28 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:153:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -498,20 +498,20 @@ help: use type parameters instead LL | fn assoc_fn_test3() -> T; | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:194:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:193:14 | LL | type B = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:196:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:195:14 | LL | const C: _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:198:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:197:14 | LL | const D: _ = 42; | ^ @@ -519,13 +519,13 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:201:26 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:200:26 | LL | type F: std::ops::Fn(_); | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:44:24 | LL | fn test9(&self) -> _ { () } @@ -534,7 +534,7 @@ LL | fn test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:47:27 | LL | fn test10(&self, _x : _) { } @@ -545,7 +545,7 @@ help: use type parameters instead LL | fn test10(&self, _x : T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:62:24 | LL | fn clone(&self) -> _ { Test9 } @@ -554,7 +554,7 @@ LL | fn clone(&self) -> _ { Test9 } | not allowed in type signatures | help: replace with the correct return type: `Test9` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:65:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } @@ -565,8 +565,8 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:31 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:110:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -574,8 +574,8 @@ LL | fn fn_test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:114:34 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:113:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -585,8 +585,8 @@ help: use type parameters instead LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:119:28 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:118:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -594,8 +594,8 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `FnTest9` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:41 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:121:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -605,26 +605,26 @@ help: use type parameters instead LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:205:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:204:14 | LL | type A = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:207:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:206:14 | LL | type B = _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:209:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:208:14 | LL | const C: _; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:212:14 +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:211:14 | LL | const D: _ = 42; | ^ diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 8a52556ed3..55f5d44d46 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -8,67 +8,67 @@ // inference by using the `_` type placeholder. fn test() -> _ { 5 } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types fn test2() -> (_, _) { (5, 5) } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types static TEST3: _ = "test"; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables static TEST4: _ = 145; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables static TEST5: (_, _) = (1, 2); -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables fn test6(_: _) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn test6_b(_: _, _: T) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn test6_c(_: _, _: (T, K, L, A, B)) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn test7(x: _) { let _x: usize = x; } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn test8(_f: fn() -> _) { } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions +//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions struct Test9; impl Test9 { fn test9(&self) -> _ { () } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types fn test10(&self, _x : _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions } fn test11(x: &usize) -> &_ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types &x } unsafe fn test12(x: *const usize) -> *const *const _ { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types &x } impl Clone for Test9 { fn clone(&self) -> _ { Test9 } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types fn clone_from(&mut self, other: _) { *self = Test9; } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions } struct Test10 { a: _, - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs b: (_, _), } @@ -76,95 +76,94 @@ pub fn main() { static A = 42; //~^ ERROR missing type for `static` item static B: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables static C: Option<_> = Some(42); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables fn fn_test() -> _ { 5 } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types fn fn_test2() -> (_, _) { (5, 5) } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types static FN_TEST3: _ = "test"; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables static FN_TEST4: _ = 145; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables static FN_TEST5: (_, _) = (1, 2); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for static variables fn fn_test6(_: _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn fn_test7(x: _) { let _x: usize = x; } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn fn_test8(_f: fn() -> _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions + //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions struct FnTest9; impl FnTest9 { fn fn_test9(&self) -> _ { () } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types fn fn_test10(&self, _x : _) { } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions } impl Clone for FnTest9 { fn clone(&self) -> _ { FnTest9 } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types fn clone_from(&mut self, other: _) { *self = FnTest9; } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions } struct FnTest10 { a: _, - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for structs b: (_, _), } fn fn_test11(_: _) -> (_, _) { panic!() } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types //~| ERROR type annotations needed fn fn_test12(x: i32) -> (_, _) { (x, x) } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types fn fn_test13(x: _) -> (i32, _) { (x, x) } - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types } trait T { fn method_test1(&self, x: _); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn method_test2(&self, x: _) -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn method_test3(&self) -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn assoc_fn_test1(x: _); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn assoc_fn_test2(x: _) -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions fn assoc_fn_test3() -> _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions } struct BadStruct<_>(_); //~^ ERROR expected identifier, found reserved identifier `_` -//~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for implementations fn impl_trait() -> impl BadTrait<_> { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types unimplemented!() } @@ -172,19 +171,19 @@ struct BadStruct1<_, _>(_); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR expected identifier, found reserved identifier `_` //~| ERROR the name `_` is already used -//~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs struct BadStruct2<_, T>(_, T); //~^ ERROR expected identifier, found reserved identifier `_` -//~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures for structs type X = Box<_>; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for type aliases struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for opaque types fn foo() -> Y { Struct } @@ -192,25 +191,25 @@ fn foo() -> Y { trait Qux { type A; type B = _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types const C: _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants const D: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants // type E: _; // FIXME: make the parser propagate the existence of `B` type F: std::ops::Fn(_); - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types } impl Qux for Struct { type A = _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types type B = _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for associated types const C: _; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants //~| ERROR associated constant in `impl` without body const D: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants } fn map(_: fn() -> Option<&'static T>) -> Option { @@ -218,9 +217,9 @@ fn map(_: fn() -> Option<&'static T>) -> Option { } fn value() -> Option<&'static _> { -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types Option::<&'static u8>::None } const _: Option<_> = map(value); -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs index 0c890f88c6..3af5cf926a 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.rs @@ -2,27 +2,27 @@ // using the `_` type placeholder. fn test1() -> _ { Some(42) } -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for return types const TEST2: _ = 42u32; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants const TEST3: _ = Some(42); -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants const TEST4: fn() -> _ = 42; -//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures for functions trait Test5 { const TEST5: _ = 42; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants } struct Test6; impl Test6 { const TEST6: _ = 13; - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures for constants } pub fn main() { diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr index 2b64df774b..1b56b1033a 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -1,4 +1,4 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item_help.rs:4:15 | LL | fn test1() -> _ { Some(42) } @@ -7,7 +7,7 @@ LL | fn test1() -> _ { Some(42) } | not allowed in type signatures | help: replace with the correct return type: `Option` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:7:14 | LL | const TEST2: _ = 42u32; @@ -16,7 +16,7 @@ LL | const TEST2: _ = 42u32; | not allowed in type signatures | help: replace with the correct type: `u32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:10:14 | LL | const TEST3: _ = Some(42); @@ -25,13 +25,13 @@ LL | const TEST3: _ = Some(42); | not allowed in type signatures | help: replace with the correct type: `Option` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item_help.rs:13:22 | LL | const TEST4: fn() -> _ = 42; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:17:18 | LL | const TEST5: _ = 42; @@ -40,7 +40,7 @@ LL | const TEST5: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants --> $DIR/typeck_type_placeholder_item_help.rs:24:18 | LL | const TEST6: _ = 13; diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index a2bf963044..e30e4f5e7d 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -5,7 +5,11 @@ LL | >::add(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add` is not implemented for `i32` - = note: required by `add` +note: required by `add` + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | fn add(self, rhs: Rhs) -> Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:6:28 diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr index 2079f6fd53..be6ed8d562 100644 --- a/src/test/ui/unevaluated_fixed_size_array_len.stderr +++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr @@ -1,14 +1,16 @@ error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied --> $DIR/unevaluated_fixed_size_array_len.rs:12:5 | -LL | fn foo(); - | --------- required by `Foo::foo` -... LL | <[(); 0] as Foo>::foo() | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` | = help: the following implementations were found: <[(); 1] as Foo> +note: required by `Foo::foo` + --> $DIR/unevaluated_fixed_size_array_len.rs:4:5 + | +LL | fn foo(); + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/union/union-align.rs b/src/test/ui/union/union-align.rs index 1340ae43cd..6a44f27dbb 100644 --- a/src/test/ui/union/union-align.rs +++ b/src/test/ui/union/union-align.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] use std::mem::{size_of, size_of_val, align_of, align_of_val}; diff --git a/src/test/ui/union/union-backcomp.rs b/src/test/ui/union/union-backcomp.rs index 4efd4c4d3d..b19eab9f52 100644 --- a/src/test/ui/union/union-backcomp.rs +++ b/src/test/ui/union/union-backcomp.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(path_statements)] #![allow(dead_code)] diff --git a/src/test/ui/union/union-basic.rs b/src/test/ui/union/union-basic.rs index 73cc9793f2..dcc552ac75 100644 --- a/src/test/ui/union/union-basic.rs +++ b/src/test/ui/union/union-basic.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(unused_imports)] // aux-build:union.rs diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr similarity index 89% rename from src/test/ui/union/union-borrow-move-parent-sibling.stderr rename to src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr index 8ba155bafb..e785a2ee73 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:53:13 + --> $DIR/union-borrow-move-parent-sibling.rs:56:13 | LL | let a = &mut u.x.0; | ---------- mutable borrow occurs here (via `u.x.0`) @@ -11,7 +11,7 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:60:13 + --> $DIR/union-borrow-move-parent-sibling.rs:63:13 | LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait @@ -21,7 +21,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:66:13 + --> $DIR/union-borrow-move-parent-sibling.rs:69:13 | LL | let a = &mut (u.x.0).0; | -------------- mutable borrow occurs here (via `u.x.0.0`) @@ -33,7 +33,7 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:73:13 + --> $DIR/union-borrow-move-parent-sibling.rs:76:13 | LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait @@ -43,7 +43,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) - --> $DIR/union-borrow-move-parent-sibling.rs:79:13 + --> $DIR/union-borrow-move-parent-sibling.rs:82:13 | LL | let a = &mut *u.y; | --- mutable borrow occurs here (via `u.y`) diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.rs b/src/test/ui/union/union-borrow-move-parent-sibling.rs index edf08e6ca6..e56d87255d 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.rs +++ b/src/test/ui/union/union-borrow-move-parent-sibling.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(untagged_unions)] #![allow(unused)] diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr new file mode 100644 index 0000000000..e785a2ee73 --- /dev/null +++ b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr @@ -0,0 +1,60 @@ +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`) + --> $DIR/union-borrow-move-parent-sibling.rs:56:13 + | +LL | let a = &mut u.x.0; + | ---------- mutable borrow occurs here (via `u.x.0`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0` + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:63:13 + | +LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = u.x.0; + | ----- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) + --> $DIR/union-borrow-move-parent-sibling.rs:69:13 + | +LL | let a = &mut (u.x.0).0; + | -------------- mutable borrow occurs here (via `u.x.0.0`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0` + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:76:13 + | +LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = (u.x.0).0; + | --------- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) + --> $DIR/union-borrow-move-parent-sibling.rs:82:13 + | +LL | let a = &mut *u.y; + | --- mutable borrow occurs here (via `u.y`) +LL | let b = &u.x; + | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/union/union-const-codegen.rs b/src/test/ui/union/union-const-codegen.rs index d5b3055959..32a546cf35 100644 --- a/src/test/ui/union/union-const-codegen.rs +++ b/src/test/ui/union/union-const-codegen.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck union U { a: u64, diff --git a/src/test/ui/union/union-const-eval-field.rs b/src/test/ui/union/union-const-eval-field.rs index 15a20899a7..ca48785cd9 100644 --- a/src/test/ui/union/union-const-eval-field.rs +++ b/src/test/ui/union/union-const-eval-field.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck type Field1 = (i32, u32); type Field2 = f32; diff --git a/src/test/ui/union/union-const-eval.rs b/src/test/ui/union/union-const-eval.rs index 90af8de447..0b6788b422 100644 --- a/src/test/ui/union/union-const-eval.rs +++ b/src/test/ui/union/union-const-eval.rs @@ -1,4 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(const_fn_union)] union U { diff --git a/src/test/ui/union/union-deref.stderr b/src/test/ui/union/union-deref.mirunsafeck.stderr similarity index 91% rename from src/test/ui/union/union-deref.stderr rename to src/test/ui/union/union-deref.mirunsafeck.stderr index 6af050bc4b..ff37e6fd91 100644 --- a/src/test/ui/union/union-deref.stderr +++ b/src/test/ui/union/union-deref.mirunsafeck.stderr @@ -1,5 +1,5 @@ error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:14:14 + --> $DIR/union-deref.rs:17:14 | LL | unsafe { u.f.0 = Vec::new() }; | ^^^ @@ -8,7 +8,7 @@ LL | unsafe { u.f.0 = Vec::new() }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:16:19 + --> $DIR/union-deref.rs:19:19 | LL | unsafe { &mut u.f.0 }; | ^^^ @@ -17,7 +17,7 @@ LL | unsafe { &mut u.f.0 }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:18:14 + --> $DIR/union-deref.rs:21:14 | LL | unsafe { u.f.0.push(0) }; | ^^^ @@ -26,7 +26,7 @@ LL | unsafe { u.f.0.push(0) }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:22:14 + --> $DIR/union-deref.rs:25:14 | LL | unsafe { u.f.0.0 = Vec::new() }; | ^^^^^ @@ -35,7 +35,7 @@ LL | unsafe { u.f.0.0 = Vec::new() }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:24:19 + --> $DIR/union-deref.rs:27:19 | LL | unsafe { &mut u.f.0.0 }; | ^^^^^ @@ -44,7 +44,7 @@ LL | unsafe { &mut u.f.0.0 }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:26:14 + --> $DIR/union-deref.rs:29:14 | LL | unsafe { u.f.0.0.push(0) }; | ^^^^^ diff --git a/src/test/ui/union/union-deref.rs b/src/test/ui/union/union-deref.rs index 48f5b36bd1..4bf2ba2f1b 100644 --- a/src/test/ui/union/union-deref.rs +++ b/src/test/ui/union/union-deref.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + //! Test the part of RFC 2514 that is about not applying `DerefMut` coercions //! of union fields. #![feature(untagged_unions)] diff --git a/src/test/ui/union/union-deref.thirunsafeck.stderr b/src/test/ui/union/union-deref.thirunsafeck.stderr new file mode 100644 index 0000000000..ff37e6fd91 --- /dev/null +++ b/src/test/ui/union/union-deref.thirunsafeck.stderr @@ -0,0 +1,56 @@ +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:17:14 + | +LL | unsafe { u.f.0 = Vec::new() }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:19:19 + | +LL | unsafe { &mut u.f.0 }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:21:14 + | +LL | unsafe { u.f.0.push(0) }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:25:14 + | +LL | unsafe { u.f.0.0 = Vec::new() }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:27:19 + | +LL | unsafe { &mut u.f.0.0 }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:29:14 + | +LL | unsafe { u.f.0.0.push(0) }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr similarity index 94% rename from src/test/ui/union/union-derive-clone.stderr rename to src/test/ui/union/union-derive-clone.mirunsafeck.stderr index 789bcc92fc..41e828c6d9 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `U1: Copy` is not satisfied - --> $DIR/union-derive-clone.rs:3:10 + --> $DIR/union-derive-clone.rs:6:10 | LL | #[derive(Clone)] | ^^^^^ the trait `Copy` is not implemented for `U1` @@ -12,7 +12,7 @@ LL | pub struct AssertParamIsCopy { = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied - --> $DIR/union-derive-clone.rs:35:15 + --> $DIR/union-derive-clone.rs:38:15 | LL | union U5 { | ----------- diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs index 7ab19edb47..7aa62146e5 100644 --- a/src/test/ui/union/union-derive-clone.rs +++ b/src/test/ui/union/union-derive-clone.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + use std::mem::ManuallyDrop; #[derive(Clone)] //~ ERROR the trait bound `U1: Copy` is not satisfied diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr new file mode 100644 index 0000000000..41e828c6d9 --- /dev/null +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `U1: Copy` is not satisfied + --> $DIR/union-derive-clone.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ the trait `Copy` is not implemented for `U1` + | + ::: $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | pub struct AssertParamIsCopy { + | ---- required by this bound in `AssertParamIsCopy` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied + --> $DIR/union-derive-clone.rs:38:15 + | +LL | union U5 { + | ----------- + | | + | method `clone` not found for this + | doesn't satisfy `U5: Clone` +... +LL | struct CloneNoCopy; + | ------------------- doesn't satisfy `CloneNoCopy: Copy` +... +LL | let w = u.clone(); + | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `CloneNoCopy: Copy` + which is required by `U5: Clone` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-derive-eq.stderr b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr similarity index 83% rename from src/test/ui/union/union-derive-eq.stderr rename to src/test/ui/union/union-derive-eq.mirunsafeck.stderr index 3198e97552..c2fd8545f6 100644 --- a/src/test/ui/union/union-derive-eq.stderr +++ b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied - --> $DIR/union-derive-eq.rs:13:5 + --> $DIR/union-derive-eq.rs:16:5 | +LL | #[derive(Eq)] + | -- in this derive macro expansion +LL | union U2 { LL | a: PartialEqNotEq, | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` | diff --git a/src/test/ui/union/union-derive-eq.rs b/src/test/ui/union/union-derive-eq.rs index e689f8c27d..b7e7f343f8 100644 --- a/src/test/ui/union/union-derive-eq.rs +++ b/src/test/ui/union/union-derive-eq.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #[derive(Eq)] // OK union U1 { a: u8, diff --git a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr new file mode 100644 index 0000000000..c2fd8545f6 --- /dev/null +++ b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied + --> $DIR/union-derive-eq.rs:16:5 + | +LL | #[derive(Eq)] + | -- in this derive macro expansion +LL | union U2 { +LL | a: PartialEqNotEq, + | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` + | + ::: $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | pub struct AssertParamIsEq { + | -- required by this bound in `AssertParamIsEq` + | + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-derive-rpass.rs b/src/test/ui/union/union-derive-rpass.rs index db18a81c1f..8276bc635f 100644 --- a/src/test/ui/union/union-derive-rpass.rs +++ b/src/test/ui/union/union-derive-rpass.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] #![allow(unused_variables)] diff --git a/src/test/ui/union/union-drop.thirunsafeck.stderr b/src/test/ui/union/union-drop.thirunsafeck.stderr new file mode 100644 index 0000000000..9766ae4e43 --- /dev/null +++ b/src/test/ui/union/union-drop.thirunsafeck.stderr @@ -0,0 +1,22 @@ +warning: unnecessary `unsafe` block + --> $DIR/union-drop.rs:27:9 + | +LL | unsafe { CHECK += 1; } + | ^^^^^^ unnecessary `unsafe` block + | + = note: `#[warn(unused_unsafe)]` on by default + +warning: unnecessary `unsafe` block + --> $DIR/union-drop.rs:33:9 + | +LL | unsafe { CHECK += 1; } + | ^^^^^^ unnecessary `unsafe` block + +warning: unnecessary `unsafe` block + --> $DIR/union-drop.rs:40:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +warning: 3 warnings emitted + diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.mirunsafeck.stderr similarity index 77% rename from src/test/ui/union/union-fields-1.stderr rename to src/test/ui/union/union-fields-1.mirunsafeck.stderr index 87621cc01b..9f1e2947c8 100644 --- a/src/test/ui/union/union-fields-1.stderr +++ b/src/test/ui/union/union-fields-1.mirunsafeck.stderr @@ -1,29 +1,29 @@ error: field is never read: `c` - --> $DIR/union-fields-1.rs:6:5 + --> $DIR/union-fields-1.rs:9:5 | LL | c: u8, | ^^^^^ | note: the lint level is defined here - --> $DIR/union-fields-1.rs:1:9 + --> $DIR/union-fields-1.rs:4:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ error: field is never read: `a` - --> $DIR/union-fields-1.rs:9:5 + --> $DIR/union-fields-1.rs:12:5 | LL | a: u8, | ^^^^^ error: field is never read: `a` - --> $DIR/union-fields-1.rs:13:20 + --> $DIR/union-fields-1.rs:16:20 | LL | union NoDropLike { a: u8 } | ^^^^^ error: field is never read: `c` - --> $DIR/union-fields-1.rs:18:5 + --> $DIR/union-fields-1.rs:21:5 | LL | c: u8, | ^^^^^ diff --git a/src/test/ui/union/union-fields-1.rs b/src/test/ui/union/union-fields-1.rs index edef41de15..3d3e2355a2 100644 --- a/src/test/ui/union/union-fields-1.rs +++ b/src/test/ui/union/union-fields-1.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![deny(dead_code)] union U1 { diff --git a/src/test/ui/union/union-fields-1.thirunsafeck.stderr b/src/test/ui/union/union-fields-1.thirunsafeck.stderr new file mode 100644 index 0000000000..9f1e2947c8 --- /dev/null +++ b/src/test/ui/union/union-fields-1.thirunsafeck.stderr @@ -0,0 +1,32 @@ +error: field is never read: `c` + --> $DIR/union-fields-1.rs:9:5 + | +LL | c: u8, + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/union-fields-1.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: field is never read: `a` + --> $DIR/union-fields-1.rs:12:5 + | +LL | a: u8, + | ^^^^^ + +error: field is never read: `a` + --> $DIR/union-fields-1.rs:16:20 + | +LL | union NoDropLike { a: u8 } + | ^^^^^ + +error: field is never read: `c` + --> $DIR/union-fields-1.rs:21:5 + | +LL | c: u8, + | ^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/union/union-fields-2.stderr b/src/test/ui/union/union-fields-2.mirunsafeck.stderr similarity index 85% rename from src/test/ui/union/union-fields-2.stderr rename to src/test/ui/union/union-fields-2.mirunsafeck.stderr index 4865434728..867bf75dfd 100644 --- a/src/test/ui/union/union-fields-2.stderr +++ b/src/test/ui/union/union-fields-2.mirunsafeck.stderr @@ -1,17 +1,17 @@ error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:7:13 + --> $DIR/union-fields-2.rs:10:13 | LL | let u = U {}; | ^ error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:9:13 + --> $DIR/union-fields-2.rs:12:13 | LL | let u = U { a: 0, b: 1 }; | ^ error[E0560]: union `U` has no field named `c` - --> $DIR/union-fields-2.rs:10:29 + --> $DIR/union-fields-2.rs:13:29 | LL | let u = U { a: 0, b: 1, c: 2 }; | ^ `U` does not have this field @@ -19,61 +19,61 @@ LL | let u = U { a: 0, b: 1, c: 2 }; = note: available fields are: `a`, `b` error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:10:13 + --> $DIR/union-fields-2.rs:13:13 | LL | let u = U { a: 0, b: 1, c: 2 }; | ^ error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:12:13 + --> $DIR/union-fields-2.rs:15:13 | LL | let u = U { ..u }; | ^ error[E0436]: functional record update syntax requires a struct - --> $DIR/union-fields-2.rs:12:19 + --> $DIR/union-fields-2.rs:15:19 | LL | let u = U { ..u }; | ^ error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:15:9 + --> $DIR/union-fields-2.rs:18:9 | LL | let U {} = u; | ^^^^ error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:17:9 + --> $DIR/union-fields-2.rs:20:9 | LL | let U { a, b } = u; | ^^^^^^^^^^ error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:18:9 + --> $DIR/union-fields-2.rs:21:9 | LL | let U { a, b, c } = u; | ^^^^^^^^^^^^^ error[E0026]: union `U` does not have a field named `c` - --> $DIR/union-fields-2.rs:18:19 + --> $DIR/union-fields-2.rs:21:19 | LL | let U { a, b, c } = u; | ^ union `U` does not have this field error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:20:9 + --> $DIR/union-fields-2.rs:23:9 | LL | let U { .. } = u; | ^^^^^^^^ error: `..` cannot be used in union patterns - --> $DIR/union-fields-2.rs:20:9 + --> $DIR/union-fields-2.rs:23:9 | LL | let U { .. } = u; | ^^^^^^^^ error: `..` cannot be used in union patterns - --> $DIR/union-fields-2.rs:22:9 + --> $DIR/union-fields-2.rs:25:9 | LL | let U { a, .. } = u; | ^^^^^^^^^^^ diff --git a/src/test/ui/union/union-fields-2.rs b/src/test/ui/union/union-fields-2.rs index 71b204fcdc..e738b18470 100644 --- a/src/test/ui/union/union-fields-2.rs +++ b/src/test/ui/union/union-fields-2.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + union U { a: u8, b: u16, diff --git a/src/test/ui/union/union-fields-2.thirunsafeck.stderr b/src/test/ui/union/union-fields-2.thirunsafeck.stderr new file mode 100644 index 0000000000..867bf75dfd --- /dev/null +++ b/src/test/ui/union/union-fields-2.thirunsafeck.stderr @@ -0,0 +1,84 @@ +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:10:13 + | +LL | let u = U {}; + | ^ + +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:12:13 + | +LL | let u = U { a: 0, b: 1 }; + | ^ + +error[E0560]: union `U` has no field named `c` + --> $DIR/union-fields-2.rs:13:29 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ `U` does not have this field + | + = note: available fields are: `a`, `b` + +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:13:13 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ + +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:15:13 + | +LL | let u = U { ..u }; + | ^ + +error[E0436]: functional record update syntax requires a struct + --> $DIR/union-fields-2.rs:15:19 + | +LL | let u = U { ..u }; + | ^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:18:9 + | +LL | let U {} = u; + | ^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:20:9 + | +LL | let U { a, b } = u; + | ^^^^^^^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:21:9 + | +LL | let U { a, b, c } = u; + | ^^^^^^^^^^^^^ + +error[E0026]: union `U` does not have a field named `c` + --> $DIR/union-fields-2.rs:21:19 + | +LL | let U { a, b, c } = u; + | ^ union `U` does not have this field + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:25:9 + | +LL | let U { a, .. } = u; + | ^^^^^^^^^^^ + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0026, E0436, E0560. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/union/union-generic-rpass.rs b/src/test/ui/union/union-generic-rpass.rs index 69837f31ca..25f1f5050f 100644 --- a/src/test/ui/union/union-generic-rpass.rs +++ b/src/test/ui/union/union-generic-rpass.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] use std::mem::ManuallyDrop; diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.mirunsafeck.stderr similarity index 69% rename from src/test/ui/union/union-generic.stderr rename to src/test/ui/union/union-generic.mirunsafeck.stderr index c418b27ce6..cd85778186 100644 --- a/src/test/ui/union/union-generic.stderr +++ b/src/test/ui/union/union-generic.mirunsafeck.stderr @@ -1,20 +1,26 @@ error[E0277]: the trait bound `Rc: Copy` is not satisfied - --> $DIR/union-generic.rs:8:13 + --> $DIR/union-generic.rs:11:13 | -LL | union U { - | ---------------- required by `U` -... LL | let u = U { a: Rc::new(0u32) }; | ^ the trait `Copy` is not implemented for `Rc` + | +note: required by `U` + --> $DIR/union-generic.rs:6:1 + | +LL | union U { + | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Rc: Copy` is not satisfied - --> $DIR/union-generic.rs:10:13 + --> $DIR/union-generic.rs:13:13 | -LL | union U { - | ---------------- required by `U` -... LL | let u = U::> { a: Default::default() }; | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc` + | +note: required by `U` + --> $DIR/union-generic.rs:6:1 + | +LL | union U { + | ^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/union/union-generic.rs b/src/test/ui/union/union-generic.rs index ff87789257..3d68ecb87d 100644 --- a/src/test/ui/union/union-generic.rs +++ b/src/test/ui/union/union-generic.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + use std::rc::Rc; union U { diff --git a/src/test/ui/union/union-generic.thirunsafeck.stderr b/src/test/ui/union/union-generic.thirunsafeck.stderr new file mode 100644 index 0000000000..cd85778186 --- /dev/null +++ b/src/test/ui/union/union-generic.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:11:13 + | +LL | let u = U { a: Rc::new(0u32) }; + | ^ the trait `Copy` is not implemented for `Rc` + | +note: required by `U` + --> $DIR/union-generic.rs:6:1 + | +LL | union U { + | ^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:13:13 + | +LL | let u = U::> { a: Default::default() }; + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc` + | +note: required by `U` + --> $DIR/union-generic.rs:6:1 + | +LL | union U { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-inherent-method.rs b/src/test/ui/union/union-inherent-method.rs index 2e75cce7b1..b0fd22da73 100644 --- a/src/test/ui/union/union-inherent-method.rs +++ b/src/test/ui/union/union-inherent-method.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck union U { a: u8, diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr similarity index 72% rename from src/test/ui/union/union-lint-dead-code.stderr rename to src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr index 7de70ec338..22d4428c90 100644 --- a/src/test/ui/union/union-lint-dead-code.stderr +++ b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr @@ -1,11 +1,11 @@ error: field is never read: `b` - --> $DIR/union-lint-dead-code.rs:5:5 + --> $DIR/union-lint-dead-code.rs:8:5 | LL | b: bool, | ^^^^^^^ | note: the lint level is defined here - --> $DIR/union-lint-dead-code.rs:1:9 + --> $DIR/union-lint-dead-code.rs:4:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/union/union-lint-dead-code.rs b/src/test/ui/union/union-lint-dead-code.rs index ae5337c618..64c28d72e9 100644 --- a/src/test/ui/union/union-lint-dead-code.rs +++ b/src/test/ui/union/union-lint-dead-code.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![deny(dead_code)] union Foo { diff --git a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr new file mode 100644 index 0000000000..22d4428c90 --- /dev/null +++ b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr @@ -0,0 +1,14 @@ +error: field is never read: `b` + --> $DIR/union-lint-dead-code.rs:8:5 + | +LL | b: bool, + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/union-lint-dead-code.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/union/union-macro.rs b/src/test/ui/union/union-macro.rs index e938cd5a61..7fd9d8221c 100644 --- a/src/test/ui/union/union-macro.rs +++ b/src/test/ui/union/union-macro.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(unused_variables)] macro_rules! duplicate { diff --git a/src/test/ui/union/union-manuallydrop-rpass.rs b/src/test/ui/union/union-manuallydrop-rpass.rs index 977d12f108..826bdf07ce 100644 --- a/src/test/ui/union/union-manuallydrop-rpass.rs +++ b/src/test/ui/union/union-manuallydrop-rpass.rs @@ -1,5 +1,8 @@ -#![allow(dead_code)] // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] use std::mem::needs_drop; use std::mem::ManuallyDrop; diff --git a/src/test/ui/union/union-move.stderr b/src/test/ui/union/union-move.mirunsafeck.stderr similarity index 92% rename from src/test/ui/union/union-move.stderr rename to src/test/ui/union/union-move.mirunsafeck.stderr index 5679192b64..f55fbea633 100644 --- a/src/test/ui/union/union-move.stderr +++ b/src/test/ui/union/union-move.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x` - --> $DIR/union-move.rs:26:18 + --> $DIR/union-move.rs:29:18 | LL | fn test1(x: U1) { | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait @@ -10,7 +10,7 @@ LL | move_out(x.f2_nocopy); | ^^^^^^^^^^^ value used here after move error[E0382]: use of moved value: `x` - --> $DIR/union-move.rs:42:18 + --> $DIR/union-move.rs:45:18 | LL | fn test3(x: U1) { | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait @@ -21,7 +21,7 @@ LL | move_out(x.f3_copy); | ^^^^^^^^^ value used here after move error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait - --> $DIR/union-move.rs:49:18 + --> $DIR/union-move.rs:52:18 | LL | move_out(x.f1_nocopy); | ^^^^^^^^^^^ diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs index a0a2d0d659..8f78c30d67 100644 --- a/src/test/ui/union/union-move.rs +++ b/src/test/ui/union/union-move.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + //! Test the behavior of moving out of non-`Copy` union fields. //! Avoid types that `Drop`, we want to focus on moving. #![feature(untagged_unions)] diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr new file mode 100644 index 0000000000..f55fbea633 --- /dev/null +++ b/src/test/ui/union/union-move.thirunsafeck.stderr @@ -0,0 +1,35 @@ +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:29:18 + | +LL | fn test1(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f1_nocopy); + | ----------- value moved here +LL | move_out(x.f2_nocopy); + | ^^^^^^^^^^^ value used here after move + +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:45:18 + | +LL | fn test3(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f2_nocopy); + | ----------- value moved here +LL | move_out(x.f3_copy); + | ^^^^^^^^^ value used here after move + +error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait + --> $DIR/union-move.rs:52:18 + | +LL | move_out(x.f1_nocopy); + | ^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `x.f1_nocopy` has type `RefCell`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0509. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/union/union-nodrop.rs b/src/test/ui/union/union-nodrop.rs index bc58c5995c..6e6b105a73 100644 --- a/src/test/ui/union/union-nodrop.rs +++ b/src/test/ui/union/union-nodrop.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck #![allow(dead_code)] diff --git a/src/test/ui/union/union-nonzero.rs b/src/test/ui/union/union-nonzero.rs index bd84b46bf3..d29e7a9718 100644 --- a/src/test/ui/union/union-nonzero.rs +++ b/src/test/ui/union/union-nonzero.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] // Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations. diff --git a/src/test/ui/union/union-overwrite.rs b/src/test/ui/union/union-overwrite.rs index 399ed9ae45..0eea14d9de 100644 --- a/src/test/ui/union/union-overwrite.rs +++ b/src/test/ui/union/union-overwrite.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck #[repr(C)] #[derive(Copy, Clone)] diff --git a/src/test/ui/union/union-packed.rs b/src/test/ui/union/union-packed.rs index 9cde44c06b..9c6398bf5a 100644 --- a/src/test/ui/union/union-packed.rs +++ b/src/test/ui/union/union-packed.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] #![allow(non_snake_case)] diff --git a/src/test/ui/union/union-pat-refutability.rs b/src/test/ui/union/union-pat-refutability.rs index ebb0672664..d628a200a0 100644 --- a/src/test/ui/union/union-pat-refutability.rs +++ b/src/test/ui/union/union-pat-refutability.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] #![allow(illegal_floating_point_literal_pattern)] diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.mirunsafeck.stderr similarity index 86% rename from src/test/ui/union/union-suggest-field.stderr rename to src/test/ui/union/union-suggest-field.mirunsafeck.stderr index 461db17120..26fc25b96b 100644 --- a/src/test/ui/union/union-suggest-field.stderr +++ b/src/test/ui/union/union-suggest-field.mirunsafeck.stderr @@ -1,17 +1,17 @@ error[E0560]: union `U` has no field named `principle` - --> $DIR/union-suggest-field.rs:10:17 + --> $DIR/union-suggest-field.rs:13:17 | LL | let u = U { principle: 0 }; | ^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0609]: no field `principial` on type `U` - --> $DIR/union-suggest-field.rs:14:15 + --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; | ^^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0615]: attempted to take value of method `calculate` on type `U` - --> $DIR/union-suggest-field.rs:18:15 + --> $DIR/union-suggest-field.rs:21:15 | LL | let y = u.calculate; | ^^^^^^^^^ method, not a field diff --git a/src/test/ui/union/union-suggest-field.rs b/src/test/ui/union/union-suggest-field.rs index 71b93e873c..601a22a060 100644 --- a/src/test/ui/union/union-suggest-field.rs +++ b/src/test/ui/union/union-suggest-field.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + union U { principal: u8, } diff --git a/src/test/ui/union/union-suggest-field.thirunsafeck.stderr b/src/test/ui/union/union-suggest-field.thirunsafeck.stderr new file mode 100644 index 0000000000..26fc25b96b --- /dev/null +++ b/src/test/ui/union/union-suggest-field.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0560]: union `U` has no field named `principle` + --> $DIR/union-suggest-field.rs:13:17 + | +LL | let u = U { principle: 0 }; + | ^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0609]: no field `principial` on type `U` + --> $DIR/union-suggest-field.rs:17:15 + | +LL | let w = u.principial; + | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0615]: attempted to take value of method `calculate` on type `U` + --> $DIR/union-suggest-field.rs:21:15 + | +LL | let y = u.calculate; + | ^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let y = u.calculate(); + | ^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0560, E0609, E0615. +For more information about an error, try `rustc --explain E0560`. diff --git a/src/test/ui/union/union-trait-impl.rs b/src/test/ui/union/union-trait-impl.rs index 8a7ac81724..6134e91f31 100644 --- a/src/test/ui/union/union-trait-impl.rs +++ b/src/test/ui/union/union-trait-impl.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck use std::fmt; diff --git a/src/test/ui/union/union-transmute.rs b/src/test/ui/union/union-transmute.rs index be8062f627..1a3b32d55f 100644 --- a/src/test/ui/union/union-transmute.rs +++ b/src/test/ui/union/union-transmute.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck union U { a: (u8, u8), diff --git a/src/test/ui/union/union-unsafe.stderr b/src/test/ui/union/union-unsafe.mir.stderr similarity index 92% rename from src/test/ui/union/union-unsafe.stderr rename to src/test/ui/union/union-unsafe.mir.stderr index a25c09144f..84a7eb2ef2 100644 --- a/src/test/ui/union/union-unsafe.stderr +++ b/src/test/ui/union/union-unsafe.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:31:5 + --> $DIR/union-unsafe.rs:34:5 | LL | *(u.p) = 13; | ^^^^^^^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:35:5 + --> $DIR/union-unsafe.rs:39:5 | LL | u.a = (RefCell::new(0), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping @@ -15,7 +15,7 @@ LL | u.a = (RefCell::new(0), 1); = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:36:5 + --> $DIR/union-unsafe.rs:40:5 | LL | u.a.0 = RefCell::new(0); | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping @@ -23,7 +23,7 @@ LL | u.a.0 = RefCell::new(0); = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:43:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:49:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -39,7 +39,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:57:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -47,7 +47,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -55,7 +55,7 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:61:20 + --> $DIR/union-unsafe.rs:65:20 | LL | if let U1 { a: 12 } = u1 {} | ^^ access to union field @@ -63,7 +63,7 @@ LL | if let U1 { a: 12 } = u1 {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:66:6 + --> $DIR/union-unsafe.rs:70:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -71,7 +71,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:70:6 + --> $DIR/union-unsafe.rs:74:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -79,7 +79,7 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:74:6 + --> $DIR/union-unsafe.rs:78:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field diff --git a/src/test/ui/union/union-unsafe.rs b/src/test/ui/union/union-unsafe.rs index 6adf0ac59b..e8414903d5 100644 --- a/src/test/ui/union/union-unsafe.rs +++ b/src/test/ui/union/union-unsafe.rs @@ -1,3 +1,6 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + #![feature(untagged_unions)] use std::mem::ManuallyDrop; use std::cell::RefCell; @@ -32,8 +35,9 @@ fn deref_union_field(mut u: URef) { } fn assign_noncopy_union_field(mut u: URefCell) { - u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping - u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping + // FIXME(thir-unsafeck) + u.a = (RefCell::new(0), 1); //[mir]~ ERROR assignment to union field that might need dropping + u.a.0 = RefCell::new(0); //[mir]~ ERROR assignment to union field that might need dropping u.a.1 = 1; // OK } diff --git a/src/test/ui/union/union-unsafe.thir.stderr b/src/test/ui/union/union-unsafe.thir.stderr new file mode 100644 index 0000000000..51f19879c8 --- /dev/null +++ b/src/test/ui/union/union-unsafe.thir.stderr @@ -0,0 +1,75 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:34:6 + | +LL | *(u.p) = 13; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:47:6 + | +LL | *u3.a = T::default(); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:53:6 + | +LL | *u3.a = T::default(); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:61:13 + | +LL | let a = u1.a; + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:64:14 + | +LL | let U1 { a } = u1; + | ^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:65:20 + | +LL | if let U1 { a: 12 } = u1 {} + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:70:6 + | +LL | *u2.a = String::from("new"); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:74:6 + | +LL | *u3.a = 1; + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:78:6 + | +LL | *u3.a = String::from("new"); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/union/union-unsized.stderr b/src/test/ui/union/union-unsized.mirunsafeck.stderr similarity index 95% rename from src/test/ui/union/union-unsized.stderr rename to src/test/ui/union/union-unsized.mirunsafeck.stderr index 454580dcba..86a13c1e7c 100644 --- a/src/test/ui/union/union-unsized.stderr +++ b/src/test/ui/union/union-unsized.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/union-unsized.rs:4:8 + --> $DIR/union-unsized.rs:7:8 | LL | a: str, | ^^^ doesn't have a size known at compile-time @@ -17,7 +17,7 @@ LL | a: Box, | ^^^^ ^ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/union-unsized.rs:12:8 + --> $DIR/union-unsized.rs:15:8 | LL | b: str, | ^^^ doesn't have a size known at compile-time diff --git a/src/test/ui/union/union-unsized.rs b/src/test/ui/union/union-unsized.rs index 16f2a73d42..e9792f527d 100644 --- a/src/test/ui/union/union-unsized.rs +++ b/src/test/ui/union/union-unsized.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(untagged_unions)] union U { diff --git a/src/test/ui/union/union-unsized.thirunsafeck.stderr b/src/test/ui/union/union-unsized.thirunsafeck.stderr new file mode 100644 index 0000000000..86a13c1e7c --- /dev/null +++ b/src/test/ui/union/union-unsized.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:7:8 + | +LL | a: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | a: &str, + | ^ +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | a: Box, + | ^^^^ ^ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:15:8 + | +LL | b: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | b: &str, + | ^ +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | b: Box, + | ^^^^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-with-drop-fields.stderr b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr similarity index 74% rename from src/test/ui/union/union-with-drop-fields.stderr rename to src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr index 0e77279be6..2062fb7473 100644 --- a/src/test/ui/union/union-with-drop-fields.stderr +++ b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr @@ -1,35 +1,35 @@ error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:9:5 + --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:9:5 + --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:17:5 + --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:17:5 + --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:22:5 + --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:22:5 + --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ diff --git a/src/test/ui/union/union-with-drop-fields.rs b/src/test/ui/union/union-with-drop-fields.rs index e3c63a6d5b..96c293418b 100644 --- a/src/test/ui/union/union-with-drop-fields.rs +++ b/src/test/ui/union/union-with-drop-fields.rs @@ -1,4 +1,6 @@ -#![feature(untagged_unions)] +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] union U { diff --git a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr new file mode 100644 index 0000000000..2062fb7473 --- /dev/null +++ b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:11:5 + | +LL | a: String, + | ^^^^^^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:11:5 + | +LL | a: String, + | ^^^^^^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:19:5 + | +LL | a: S, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:19:5 + | +LL | a: S, + | ^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:24:5 + | +LL | a: T, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:24:5 + | +LL | a: T, + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0740`. diff --git a/src/test/ui/unpretty-expr-fn-arg.rs b/src/test/ui/unpretty-expr-fn-arg.rs new file mode 100644 index 0000000000..6e1132a337 --- /dev/null +++ b/src/test/ui/unpretty-expr-fn-arg.rs @@ -0,0 +1,13 @@ +// Regression test for the ICE described in #82328. The pretty-printer for +// `-Zunpretty=hir,typed` would previously retrieve type-checking results +// when entering a body, which means that type information was not available +// for expressions occurring in function signatures, as in the `foo` example +// below, leading to an ICE. + +// check-pass +// compile-flags: -Zunpretty=hir,typed +#![allow(dead_code)] + +fn main() {} + +fn foo(-128..=127: i8) {} diff --git a/src/test/ui/unpretty-expr-fn-arg.stdout b/src/test/ui/unpretty-expr-fn-arg.stdout new file mode 100644 index 0000000000..cb04dfead7 --- /dev/null +++ b/src/test/ui/unpretty-expr-fn-arg.stdout @@ -0,0 +1,17 @@ +// Regression test for the ICE described in #82328. The pretty-printer for +// `-Zunpretty=hir,typed` would previously retrieve type-checking results +// when entering a body, which means that type information was not available +// for expressions occurring in function signatures, as in the `foo` example +// below, leading to an ICE. + +// check-pass +// compile-flags: -Zunpretty=hir,typed +#![allow(dead_code)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +fn main() ({ } as ()) + +fn foo((-(128 as i8) as i8) ...(127 as i8): i8) ({ } as ()) diff --git a/src/test/ui/unsafe/access_union_field.mir.stderr b/src/test/ui/unsafe/access_union_field.mir.stderr new file mode 100644 index 0000000000..98bc407779 --- /dev/null +++ b/src/test/ui/unsafe/access_union_field.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:13:13 + | +LL | let a = foo.bar; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:14:13 + | +LL | let b = foo.baz; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/access_union_field.rs b/src/test/ui/unsafe/access_union_field.rs new file mode 100644 index 0000000000..5c4e695df5 --- /dev/null +++ b/src/test/ui/unsafe/access_union_field.rs @@ -0,0 +1,15 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![allow(unused_variables)] + +union Foo { + bar: i8, + baz: u8, +} + +fn main() { + let foo = Foo { bar: 5 }; + let a = foo.bar; //~ ERROR access to union field is unsafe and requires unsafe function or block + let b = foo.baz; //~ ERROR access to union field is unsafe and requires unsafe function or block +} diff --git a/src/test/ui/unsafe/access_union_field.thir.stderr b/src/test/ui/unsafe/access_union_field.thir.stderr new file mode 100644 index 0000000000..98bc407779 --- /dev/null +++ b/src/test/ui/unsafe/access_union_field.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:13:13 + | +LL | let a = foo.bar; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:14:13 + | +LL | let b = foo.baz; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints2.stderr b/src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr similarity index 92% rename from src/test/ui/unsafe/ranged_ints2.stderr rename to src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr index ee1d1f10e7..427843f8d4 100644 --- a/src/test/ui/unsafe/ranged_ints2.stderr +++ b/src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/ranged_ints2.rs:8:13 + --> $DIR/ranged_ints2.rs:11:13 | LL | let y = &mut x.0; | ^^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints2.rs b/src/test/ui/unsafe/ranged_ints2.rs index 68ba120b27..9a6bb18f92 100644 --- a/src/test/ui/unsafe/ranged_ints2.rs +++ b/src/test/ui/unsafe/ranged_ints2.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr new file mode 100644 index 0000000000..427843f8d4 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:11:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr similarity index 90% rename from src/test/ui/unsafe/ranged_ints2_const.stderr rename to src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr index a0dc950e76..c16550a580 100644 --- a/src/test/ui/unsafe/ranged_ints2_const.stderr +++ b/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:11:13 + --> $DIR/ranged_ints2_const.rs:14:13 | LL | let y = &mut x.0; | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | let y = &mut x.0; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:18:22 + --> $DIR/ranged_ints2_const.rs:21:22 | LL | let y = unsafe { &mut x.0 }; | ^^^^^^^^ @@ -17,7 +17,7 @@ LL | let y = unsafe { &mut x.0 }; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:24:22 + --> $DIR/ranged_ints2_const.rs:27:22 | LL | unsafe { let y = &mut x.0; } | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | unsafe { let y = &mut x.0; } = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/ranged_ints2_const.rs:11:13 + --> $DIR/ranged_ints2_const.rs:14:13 | LL | let y = &mut x.0; | ^^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints2_const.rs b/src/test/ui/unsafe/ranged_ints2_const.rs index b7178c2b52..56f5407bb6 100644 --- a/src/test/ui/unsafe/ranged_ints2_const.rs +++ b/src/test/ui/unsafe/ranged_ints2_const.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr new file mode 100644 index 0000000000..b3f139f721 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:21:22 + | +LL | let y = unsafe { &mut x.0 }; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:27:22 + | +LL | unsafe { let y = &mut x.0; } + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3.stderr b/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr similarity index 93% rename from src/test/ui/unsafe/ranged_ints3.stderr rename to src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr index 4d4c916715..9eec0b09e9 100644 --- a/src/test/ui/unsafe/ranged_ints3.stderr +++ b/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block - --> $DIR/ranged_ints3.rs:10:13 + --> $DIR/ranged_ints3.rs:13:13 | LL | let y = &x.0; | ^^^^ borrow of layout constrained field with interior mutability diff --git a/src/test/ui/unsafe/ranged_ints3.rs b/src/test/ui/unsafe/ranged_ints3.rs index 47d67fac67..76d4bfe953 100644 --- a/src/test/ui/unsafe/ranged_ints3.rs +++ b/src/test/ui/unsafe/ranged_ints3.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr new file mode 100644 index 0000000000..9eec0b09e9 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3.rs:13:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr similarity index 91% rename from src/test/ui/unsafe/ranged_ints3_const.stderr rename to src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr index 215005571f..62df933306 100644 --- a/src/test/ui/unsafe/ranged_ints3_const.stderr +++ b/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/ranged_ints3_const.rs:12:13 + --> $DIR/ranged_ints3_const.rs:15:13 | LL | let y = &x.0; | ^^^^ @@ -8,7 +8,7 @@ LL | let y = &x.0; = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/ranged_ints3_const.rs:19:22 + --> $DIR/ranged_ints3_const.rs:22:22 | LL | let y = unsafe { &x.0 }; | ^^^^ @@ -17,7 +17,7 @@ LL | let y = unsafe { &x.0 }; = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block - --> $DIR/ranged_ints3_const.rs:12:13 + --> $DIR/ranged_ints3_const.rs:15:13 | LL | let y = &x.0; | ^^^^ borrow of layout constrained field with interior mutability diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs index c069ae7da0..637198d360 100644 --- a/src/test/ui/unsafe/ranged_ints3_const.rs +++ b/src/test/ui/unsafe/ranged_ints3_const.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr new file mode 100644 index 0000000000..5dbc563aad --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr @@ -0,0 +1,30 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:22:22 + | +LL | let y = unsafe { &x.0 }; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr new file mode 100644 index 0000000000..27c0664092 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr @@ -0,0 +1,19 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:14:17 + | +LL | NonZero(ref x) => { x } + | ^^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:20:23 + | +LL | match y { NonZero(ref mut y) => { y } }; + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3_match.rs b/src/test/ui/unsafe/ranged_ints3_match.rs new file mode 100644 index 0000000000..d9fcf0bd66 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_match.rs @@ -0,0 +1,22 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(Cell::new(1)) }; + match x { + NonZero(ref x) => { x } + //~^ ERROR borrow of layout constrained field with interior mutability + }; + + let mut y = unsafe { NonZero(42) }; + match y { NonZero(ref y) => { y } }; // OK, type of `y` is freeze + match y { NonZero(ref mut y) => { y } }; + //~^ ERROR mutation of layout constrained field +} diff --git a/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr new file mode 100644 index 0000000000..27c0664092 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr @@ -0,0 +1,19 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:14:17 + | +LL | NonZero(ref x) => { x } + | ^^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:20:23 + | +LL | match y { NonZero(ref mut y) => { y } }; + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints4.stderr b/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr similarity index 92% rename from src/test/ui/unsafe/ranged_ints4.stderr rename to src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr index 68c22589d3..493483d2c4 100644 --- a/src/test/ui/unsafe/ranged_ints4.stderr +++ b/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/ranged_ints4.rs:8:5 + --> $DIR/ranged_ints4.rs:11:5 | LL | x.0 = 0; | ^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints4.rs b/src/test/ui/unsafe/ranged_ints4.rs index d8632c4843..fe80af454c 100644 --- a/src/test/ui/unsafe/ranged_ints4.rs +++ b/src/test/ui/unsafe/ranged_ints4.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints4_const.stderr b/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr similarity index 90% rename from src/test/ui/unsafe/ranged_ints4_const.stderr rename to src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr index fe83b15ce5..493483d2c4 100644 --- a/src/test/ui/unsafe/ranged_ints4_const.stderr +++ b/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/ranged_ints4_const.rs:10:5 + --> $DIR/ranged_ints4.rs:11:5 | LL | x.0 = 0; | ^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr new file mode 100644 index 0000000000..a06c6f479b --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4_const.rs:13:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints4_const.rs b/src/test/ui/unsafe/ranged_ints4_const.rs index f09168c3d3..a43c8be71c 100644 --- a/src/test/ui/unsafe/ranged_ints4_const.rs +++ b/src/test/ui/unsafe/ranged_ints4_const.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr new file mode 100644 index 0000000000..a06c6f479b --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4_const.rs:13:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/union.mir.stderr b/src/test/ui/unsafe/union.mir.stderr new file mode 100644 index 0000000000..f7bd411a74 --- /dev/null +++ b/src/test/ui/unsafe/union.mir.stderr @@ -0,0 +1,16 @@ +warning: unnecessary `unsafe` block + --> $DIR/union.rs:61:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: `#[warn(unused_unsafe)]` on by default + +warning: unnecessary `unsafe` block + --> $DIR/union.rs:66:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +warning: 2 warnings emitted + diff --git a/src/test/ui/unsafe/union.rs b/src/test/ui/unsafe/union.rs new file mode 100644 index 0000000000..0130fa67f2 --- /dev/null +++ b/src/test/ui/unsafe/union.rs @@ -0,0 +1,80 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(untagged_unions)] + +union Foo { + bar: i8, + zst: (), + pizza: Pizza, +} + +struct Pizza { + topping: Option +} + +#[allow(dead_code)] +enum PizzaTopping { + Cheese, + Pineapple, +} + +struct FooHolder { + inner_foo: Foo +} + +fn do_nothing(_x: &mut Foo) {} + +pub fn main() { + let mut foo = Foo { bar: 5 }; + do_nothing(&mut foo); + foo.bar = 6; + unsafe { foo.bar += 1; } + assert_eq!(unsafe { foo.bar }, 7); + unsafe { + let Foo { bar: inner } = foo; + assert_eq!(inner, 7); + } + let foo = if let true = true { foo } else { foo }; + + unsafe { + match foo { + Foo { bar: _a } => {}, + } + } + unsafe { + match foo { + Foo { + pizza: Pizza { + topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None + } + } => {}, + } + } + // binding to wildcard is okay + match foo { + Foo { bar: _ } => {}, + } + let Foo { bar: _ } = foo; + // MIR unsafeck incorrectly thinks that it is safe to do these + unsafe { //[mir]~ WARNING + match foo { + Foo { zst: () } => {}, + } + } + unsafe { //[mir]~ WARNING + match foo { + Foo { pizza: Pizza { .. } } => {}, + } + } + let foo = Foo { bar: 5 }; + let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo }; + + let (_foo2, _random) = (foo, 42); + + let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } }; + foo_holder.inner_foo.bar = 4; + assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4); + drop(foo_holder); +} diff --git a/src/test/ui/unsafe/union_access_through_block.rs b/src/test/ui/unsafe/union_access_through_block.rs new file mode 100644 index 0000000000..e4c0976b82 --- /dev/null +++ b/src/test/ui/unsafe/union_access_through_block.rs @@ -0,0 +1,18 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#[derive(Copy, Clone)] +pub struct Foo { a: bool } + +pub union Bar { + a: Foo, + b: u32, +} +pub fn baz(mut bar: Bar) { + unsafe { + { bar.a }.a = true; + } +} + +fn main() {} diff --git a/src/test/ui/unsafe/union_destructure.mir.stderr b/src/test/ui/unsafe/union_destructure.mir.stderr new file mode 100644 index 0000000000..818f5ce03b --- /dev/null +++ b/src/test/ui/unsafe/union_destructure.mir.stderr @@ -0,0 +1,16 @@ +warning: unnecessary `unsafe` block + --> $DIR/union_destructure.rs:35:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: `#[warn(unused_unsafe)]` on by default + +warning: unnecessary `unsafe` block + --> $DIR/union_destructure.rs:41:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +warning: 2 warnings emitted + diff --git a/src/test/ui/unsafe/union_destructure.rs b/src/test/ui/unsafe/union_destructure.rs new file mode 100644 index 0000000000..6c88344b5f --- /dev/null +++ b/src/test/ui/unsafe/union_destructure.rs @@ -0,0 +1,51 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#[derive(Copy, Clone)] +#[allow(dead_code)] +struct Pie { + slices: u8, + size: u8, +} + +union Foo { + #[allow(dead_code)] + bar: i8, + baz: Pie +} + +fn main() { + let u = Foo { bar: 5 }; + let (Some(Foo { bar: _ }) | None) = Some(u); + let u = Foo { bar: 6 }; + let (Some(Foo { bar: _ }) | Some(Foo { bar: _ }) | None) = Some(u); + unsafe { + let u = Foo { bar: 7 }; + let (Foo { bar } | Foo { bar }) = u; + assert_eq!(bar, 7) + } + let u = Foo { bar: 8 }; + match Some(u) { + Some(Foo { bar: _ }) => 3, + None => 4, + }; + + let u = Foo { bar: 9 }; + unsafe { //[mir]~ WARNING unnecessary `unsafe` block + match u { + Foo { baz: Pie { .. } } => {}, + }; + } + let u = Foo { bar: 10 }; + unsafe { //[mir]~ WARNING unnecessary `unsafe` block + match u { + Foo { baz: Pie { slices: _, size: _ } } => {}, + }; + } + + let u = Foo { bar: 11 }; + match u { + Foo { baz: _ } => {}, + }; +} diff --git a/src/test/ui/unsafe/union_wild_or_wild.rs b/src/test/ui/unsafe/union_wild_or_wild.rs new file mode 100644 index 0000000000..52a0a7abf2 --- /dev/null +++ b/src/test/ui/unsafe/union_wild_or_wild.rs @@ -0,0 +1,12 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +union X { a: i8 } + +fn main() { + let x = X { a: 5 }; + match x { + X { a: _ | _ } => {}, + } +} diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr index 6810132686..29bd84cd0d 100644 --- a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr +++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr @@ -1,11 +1,11 @@ error: unnecessary `unsafe` block - --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:5 + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9 | -LL | unsafe { println!("foo"); } - | ^^^^^^ unnecessary `unsafe` block +LL | unsafe { async {}.await; } + | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-around-compiler-generated-unsafe.rs:6:9 + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9 | LL | #![deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs index 08801f9ef5..e9c7efb9e8 100644 --- a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs +++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs @@ -1,10 +1,11 @@ -// issue #12418 - +// edition:2018 // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck #![deny(unused_unsafe)] fn main() { - unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe` + let _ = async { + unsafe { async {}.await; } //~ ERROR unnecessary `unsafe` + }; } diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr index 6810132686..29bd84cd0d 100644 --- a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr +++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr @@ -1,11 +1,11 @@ error: unnecessary `unsafe` block - --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:5 + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9 | -LL | unsafe { println!("foo"); } - | ^^^^^^ unnecessary `unsafe` block +LL | unsafe { async {}.await; } + | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-around-compiler-generated-unsafe.rs:6:9 + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9 | LL | #![deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr new file mode 100644 index 0000000000..9abc51424a --- /dev/null +++ b/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-assign.rs:12:5 + | +LL | foo.0.0 = 0; + | ^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/unsafe-assign.rs b/src/test/ui/unsafe/unsafe-assign.rs new file mode 100644 index 0000000000..15273165b5 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-assign.rs @@ -0,0 +1,25 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn nested_field() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + foo.0.0 = 0; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn block() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + { foo.0 }.0 = 0; + // ^ not unsafe because the result of the block expression is a new place +} + +fn main() {} diff --git a/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr new file mode 100644 index 0000000000..9abc51424a --- /dev/null +++ b/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-assign.rs:12:5 + | +LL | foo.0.0 = 0; + | ^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr new file mode 100644 index 0000000000..a206722495 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:12:13 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:32:13 + | +LL | let a = &mut foo.0[2]; + | ^^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:51:18 + | +LL | NonZero((a,)) => *a = 0, + | ^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/unsafe-borrow.rs b/src/test/ui/unsafe/unsafe-borrow.rs new file mode 100644 index 0000000000..8dddc70be4 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-borrow.rs @@ -0,0 +1,56 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn tuple_struct() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + let a = &mut foo.0.0; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn slice() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero<'a, T>(&'a mut [T]); + + let mut nums = [1, 2, 3, 4]; + let mut foo = unsafe { NonZero(&mut nums[..]) }; + let a = &mut foo.0[2]; + // ^ not unsafe because there is an implicit dereference here +} + +fn array() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero([T; 4]); + + let nums = [1, 2, 3, 4]; + let mut foo = unsafe { NonZero(nums) }; + let a = &mut foo.0[2]; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn block() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let foo = unsafe { NonZero((1,)) }; + &mut { foo.0 }.0; + // ^ not unsafe because the result of the block expression is a new place +} + +fn mtch() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + match &mut foo { + NonZero((a,)) => *a = 0, + //~^ ERROR: mutation of layout constrained field is unsafe + } +} + +fn main() {} diff --git a/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr new file mode 100644 index 0000000000..a206722495 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:12:13 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:32:13 + | +LL | let a = &mut foo.0[2]; + | ^^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:51:18 + | +LL | NonZero((a,)) => *a = 0, + | ^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsized/unsized3-rpass.rs b/src/test/ui/unsized/unsized3-rpass.rs index 65efbd6b52..c5c5ed26c7 100644 --- a/src/test/ui/unsized/unsized3-rpass.rs +++ b/src/test/ui/unsized/unsized3-rpass.rs @@ -1,12 +1,11 @@ // run-pass // Test structs with always-unsized fields. - #![allow(warnings)] -#![feature(box_syntax, unsize, raw)] +#![feature(box_syntax, unsize, ptr_metadata)] use std::mem; -use std::raw; +use std::ptr; use std::slice; struct Foo { @@ -28,7 +27,7 @@ trait Tr { } struct St { - f: usize + f: usize, } impl Tr for St { @@ -38,7 +37,7 @@ impl Tr for St { } struct Qux<'a> { - f: Tr+'a + f: Tr + 'a, } pub fn main() { @@ -56,10 +55,10 @@ pub fn main() { unsafe { struct Foo_ { - f: [T; 3] + f: [T; 3], } - let data: Box> = box Foo_{f: [1, 2, 3] }; + let data: Box> = box Foo_ { f: [1, 2, 3] }; let x: &Foo = mem::transmute(slice::from_raw_parts(&*data, 3)); assert_eq!(x.f.len(), 3); assert_eq!(x.f[0], 1); @@ -69,8 +68,8 @@ pub fn main() { f2: [u8; 5], } - let data: Box<_> = box Baz_ { - f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; + let data: Box<_> = + box Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5)); assert_eq!(x.f1, 42); let chs: Vec = x.f2.chars().collect(); @@ -82,15 +81,13 @@ pub fn main() { assert_eq!(chs[4], 'e'); struct Qux_ { - f: St + f: St, } let obj: Box = box St { f: 42 }; let obj: &Tr = &*obj; - let obj: raw::TraitObject = mem::transmute(&*obj); - let data: Box<_> = box Qux_{ f: St { f: 234 } }; - let x: &Qux = mem::transmute(raw::TraitObject { vtable: obj.vtable, - data: mem::transmute(&*data) }); + let data: Box<_> = box Qux_ { f: St { f: 234 } }; + let x: &Qux = &*ptr::from_raw_parts::((&*data as *const _).cast(), ptr::metadata(obj)); assert_eq!(x.f.foo(), 234); } } diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.rs b/src/test/ui/unused/unused-doc-comments-edge-cases.rs new file mode 100644 index 0000000000..fd9baf8c6b --- /dev/null +++ b/src/test/ui/unused/unused-doc-comments-edge-cases.rs @@ -0,0 +1,29 @@ +#![deny(unused_doc_comments)] + +fn doc_comment_on_match_arms(num: u8) -> bool { + match num { + 3 => true, + /// useless doc comment + //~^ ERROR: unused doc comment + _ => false, + } +} + +fn doc_comment_between_if_else(num: u8) -> bool { + if num == 3 { + true //~ ERROR: mismatched types + } + /// useless doc comment + else { //~ ERROR: expected expression, found keyword `else` + false + } +} + +fn doc_comment_on_expr(num: u8) -> bool { + /// useless doc comment + //~^ ERROR: attributes on expressions are experimental + //~| ERROR: unused doc comment + num == 3 +} + +fn main() {} diff --git a/src/test/ui/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/unused/unused-doc-comments-edge-cases.stderr new file mode 100644 index 0000000000..14db5f64b0 --- /dev/null +++ b/src/test/ui/unused/unused-doc-comments-edge-cases.stderr @@ -0,0 +1,61 @@ +error: expected expression, found keyword `else` + --> $DIR/unused-doc-comments-edge-cases.rs:17:5 + | +LL | else { + | ^^^^ expected expression + +error[E0658]: attributes on expressions are experimental + --> $DIR/unused-doc-comments-edge-cases.rs:23:5 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = help: `///` is for documentation comments. For a plain comment, use `//`. + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:6:9 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | _ => false, + | ---------- rustdoc does not generate documentation for match arms + | +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 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | num == 3 + | --- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error[E0308]: mismatched types + --> $DIR/unused-doc-comments-edge-cases.rs:14:9 + | +LL | / if num == 3 { +LL | | true + | | ^^^^ expected `()`, found `bool` +LL | | } + | |_____- expected this to be `()` + | +help: you might have meant to return this value + | +LL | return true; + | ^^^^^^ ^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/unused/useless-comment.stderr b/src/test/ui/unused/useless-comment.stderr index 5a0af8db7c..0054426fb1 100644 --- a/src/test/ui/unused/useless-comment.stderr +++ b/src/test/ui/unused/useless-comment.stderr @@ -26,6 +26,8 @@ LL | /// a | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | let x = 12; | ----------- rustdoc does not generate documentation for statements + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:16:5 @@ -40,6 +42,8 @@ LL | | 1 => {}, LL | | _ => {} LL | | } | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:20:9 @@ -48,6 +52,8 @@ LL | /// c | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | 1 => {}, | ------- rustdoc does not generate documentation for match arms + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:25:5 @@ -56,6 +62,8 @@ LL | /// foo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | unsafe {} | --------- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:28:5 @@ -65,6 +73,8 @@ LL | #[doc = "foo"] LL | #[doc = "bar"] LL | 3; | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:29:5 @@ -73,12 +83,16 @@ LL | #[doc = "bar"] | ^^^^^^^^^^^^^^ LL | 3; | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:35:13 | LL | let x = /** comment */ 47; | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions + | + = help: use `/* */` for a plain comment error: unused doc comment --> $DIR/useless-comment.rs:37:5 @@ -89,6 +103,8 @@ LL | / { LL | | LL | | } | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment error: aborting due to 10 previous errors diff --git a/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.rs b/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.rs index 7d4dc8c934..cfa8eb3cad 100644 --- a/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.rs +++ b/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.rs @@ -1,13 +1,30 @@ -// ignore-arm stdcall isn't supported -// ignore-aarch64 stdcall isn't supported -// ignore-riscv64 stdcall isn't supported +// gate-test-c_unwind +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } // Test that the "stdcall-unwind" ABI is feature-gated, and cannot be used when // the `c_unwind` feature gate is not used. -extern "stdcall-unwind" fn f() {} -//~^ ERROR stdcall-unwind ABI is experimental and subject to change [E0658] +extern "stdcall-unwind" fn fu() {} //~ ERROR stdcall-unwind ABI is experimental -fn main() { - f(); +trait T { + extern "stdcall-unwind" fn mu(); //~ ERROR stdcall-unwind ABI is experimental + extern "stdcall-unwind" fn dmu() {} //~ ERROR stdcall-unwind ABI is experimental } + +struct S; +impl T for S { + extern "stdcall-unwind" fn mu() {} //~ ERROR stdcall-unwind ABI is experimental +} + +impl S { + extern "stdcall-unwind" fn imu() {} //~ ERROR stdcall-unwind ABI is experimental +} + +type TAU = extern "stdcall-unwind" fn(); //~ ERROR stdcall-unwind ABI is experimental + +extern "stdcall-unwind" {} //~ ERROR stdcall-unwind ABI is experimental diff --git a/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.stderr b/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.stderr index e3d569f464..c2cce0e119 100644 --- a/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.stderr +++ b/src/test/ui/unwind-abis/feature-gate-stdcall-unwind.stderr @@ -1,12 +1,66 @@ error[E0658]: stdcall-unwind ABI is experimental and subject to change - --> $DIR/feature-gate-stdcall-unwind.rs:8:8 + --> $DIR/feature-gate-stdcall-unwind.rs:12:8 | -LL | extern "stdcall-unwind" fn f() {} +LL | extern "stdcall-unwind" fn fu() {} | ^^^^^^^^^^^^^^^^ | = note: see issue #74990 for more information = help: add `#![feature(c_unwind)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:15:12 + | +LL | extern "stdcall-unwind" fn mu(); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:16:12 + | +LL | extern "stdcall-unwind" fn dmu() {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:21:12 + | +LL | extern "stdcall-unwind" fn mu() {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:25:12 + | +LL | extern "stdcall-unwind" fn imu() {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:28:19 + | +LL | type TAU = extern "stdcall-unwind" fn(); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:30:8 + | +LL | extern "stdcall-unwind" {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.rs b/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.rs index 2f4cefccc1..0a323e50fc 100644 --- a/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.rs +++ b/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.rs @@ -1,13 +1,39 @@ -// ignore-arm thiscall isn't supported -// ignore-aarch64 thiscall isn't supported -// ignore-riscv64 thiscall isn't supported +// gate-test-abi_thiscall +// gate-test-c_unwind +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } // Test that the "thiscall-unwind" ABI is feature-gated, and cannot be used when // the `c_unwind` feature gate is not used. -extern "thiscall-unwind" fn f() {} -//~^ ERROR thiscall-unwind ABI is experimental and subject to change [E0658] +extern "thiscall-unwind" fn fu() {} //~ ERROR thiscall-unwind ABI is experimental +extern "thiscall" fn f() {} //~ ERROR thiscall is experimental -fn main() { - f(); +trait T { + extern "thiscall" fn m(); //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn mu(); //~ ERROR thiscall-unwind ABI is experimental + + extern "thiscall" fn dm() {} //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn dmu() {} //~ ERROR thiscall-unwind ABI is experimental +} + +struct S; +impl T for S { + extern "thiscall" fn m() {} //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn mu() {} //~ ERROR thiscall-unwind ABI is experimental } + +impl S { + extern "thiscall" fn im() {} //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn imu() {} //~ ERROR thiscall-unwind ABI is experimental +} + +type TA = extern "thiscall" fn(); //~ ERROR thiscall is experimental +type TAU = extern "thiscall-unwind" fn(); //~ ERROR thiscall-unwind ABI is experimental + +extern "thiscall" {} //~ ERROR thiscall is experimental +extern "thiscall-unwind" {} //~ ERROR thiscall-unwind ABI is experimental diff --git a/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.stderr b/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.stderr index b103bb8d56..9ca00a55cd 100644 --- a/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.stderr +++ b/src/test/ui/unwind-abis/feature-gate-thiscall-unwind.stderr @@ -1,12 +1,122 @@ error[E0658]: thiscall-unwind ABI is experimental and subject to change - --> $DIR/feature-gate-thiscall-unwind.rs:8:8 + --> $DIR/feature-gate-thiscall-unwind.rs:13:8 | -LL | extern "thiscall-unwind" fn f() {} +LL | extern "thiscall-unwind" fn fu() {} | ^^^^^^^^^^^^^^^^^ | = note: see issue #74990 for more information = help: add `#![feature(c_unwind)]` to the crate attributes to enable -error: aborting due to previous error +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:14:8 + | +LL | extern "thiscall" fn f() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:17:12 + | +LL | extern "thiscall" fn m(); + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:18:12 + | +LL | extern "thiscall-unwind" fn mu(); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:20:12 + | +LL | extern "thiscall" fn dm() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:21:12 + | +LL | extern "thiscall-unwind" fn dmu() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:26:12 + | +LL | extern "thiscall" fn m() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:27:12 + | +LL | extern "thiscall-unwind" fn mu() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:31:12 + | +LL | extern "thiscall" fn im() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:32:12 + | +LL | extern "thiscall-unwind" fn imu() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:35:18 + | +LL | type TA = extern "thiscall" fn(); + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:36:19 + | +LL | type TAU = extern "thiscall-unwind" fn(); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:38:8 + | +LL | extern "thiscall" {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:39:8 + | +LL | extern "thiscall-unwind" {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr index be18737b5f..4b653238aa 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr @@ -39,7 +39,47 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:18:5 + --> $DIR/variance-btree-invariant-types.rs:17:5 + | +LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = help: consider replacing `'new` with `'static` + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:20:5 + | +LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = help: consider replacing `'new` with `'static` + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:23:5 + | +LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = help: consider replacing `'new` with `'static` + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:26:5 + | +LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = help: consider replacing `'new` with `'static` + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:31:5 | LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) | ---- lifetime `'new` defined here @@ -50,7 +90,7 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:22:5 + --> $DIR/variance-btree-invariant-types.rs:35:5 | LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) | ---- lifetime `'new` defined here @@ -61,7 +101,7 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:26:5 + --> $DIR/variance-btree-invariant-types.rs:39:5 | LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) | ---- lifetime `'new` defined here @@ -72,7 +112,7 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:30:5 + --> $DIR/variance-btree-invariant-types.rs:43:5 | LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) | ---- lifetime `'new` defined here @@ -83,7 +123,7 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:35:5 + --> $DIR/variance-btree-invariant-types.rs:48:5 | LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) | ---- lifetime `'new` defined here @@ -94,7 +134,7 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:39:5 + --> $DIR/variance-btree-invariant-types.rs:52:5 | LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) | ---- lifetime `'new` defined here @@ -105,7 +145,7 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:43:5 + --> $DIR/variance-btree-invariant-types.rs:56:5 | LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) | ---- lifetime `'new` defined here @@ -116,7 +156,7 @@ LL | v = help: consider replacing `'new` with `'static` error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:47:5 + --> $DIR/variance-btree-invariant-types.rs:60:5 | LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) | ---- lifetime `'new` defined here @@ -126,5 +166,5 @@ LL | v | = help: consider replacing `'new` with `'static` -error: aborting due to 12 previous errors +error: aborting due to 16 previous errors diff --git a/src/test/ui/variance/variance-btree-invariant-types.rs b/src/test/ui/variance/variance-btree-invariant-types.rs index 2e5dc671db..4549622f24 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.rs +++ b/src/test/ui/variance/variance-btree-invariant-types.rs @@ -1,4 +1,4 @@ -use std::collections::btree_map::{IterMut, OccupiedEntry, VacantEntry}; +use std::collections::btree_map::{IterMut, OccupiedEntry, RangeMut, VacantEntry}; fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { v //~ ERROR mismatched types @@ -13,6 +13,19 @@ fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &' v //~ ERROR mismatched types } +fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { + v //~ ERROR mismatched types +} +fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { + v //~ ERROR mismatched types +} +fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { + v //~ ERROR mismatched types +} +fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { + v //~ ERROR mismatched types +} + fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) -> OccupiedEntry<'a, &'new (), ()> { v //~ ERROR mismatched types diff --git a/src/test/ui/variance/variance-btree-invariant-types.stderr b/src/test/ui/variance/variance-btree-invariant-types.stderr index 8172a019b6..ba47bdff28 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.stderr @@ -59,125 +59,185 @@ LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, ( = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:18:5 + --> $DIR/variance-btree-invariant-types.rs:17:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `RangeMut<'_, &'new (), _>` + found struct `RangeMut<'_, &'static (), _>` +note: the lifetime `'new` as defined on the function body at 16:22... + --> $DIR/variance-btree-invariant-types.rs:16:22 + | +LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:20:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `RangeMut<'_, _, &'new ()>` + found struct `RangeMut<'_, _, &'static ()>` +note: the lifetime `'new` as defined on the function body at 19:22... + --> $DIR/variance-btree-invariant-types.rs:19:22 + | +LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:23:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `RangeMut<'_, &'static (), _>` + found struct `RangeMut<'_, &'new (), _>` +note: the lifetime `'new` as defined on the function body at 22:25... + --> $DIR/variance-btree-invariant-types.rs:22:25 + | +LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:26:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `RangeMut<'_, _, &'static ()>` + found struct `RangeMut<'_, _, &'new ()>` +note: the lifetime `'new` as defined on the function body at 25:25... + --> $DIR/variance-btree-invariant-types.rs:25:25 + | +LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:31:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` found struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 16:20... - --> $DIR/variance-btree-invariant-types.rs:16:20 +note: the lifetime `'new` as defined on the function body at 29:20... + --> $DIR/variance-btree-invariant-types.rs:29:20 | LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:22:5 + --> $DIR/variance-btree-invariant-types.rs:35:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 20:20... - --> $DIR/variance-btree-invariant-types.rs:20:20 +note: the lifetime `'new` as defined on the function body at 33:20... + --> $DIR/variance-btree-invariant-types.rs:33:20 | LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:26:5 + --> $DIR/variance-btree-invariant-types.rs:39:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` found struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 24:23... - --> $DIR/variance-btree-invariant-types.rs:24:23 +note: the lifetime `'new` as defined on the function body at 37:23... + --> $DIR/variance-btree-invariant-types.rs:37:23 | LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:30:5 + --> $DIR/variance-btree-invariant-types.rs:43:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 28:23... - --> $DIR/variance-btree-invariant-types.rs:28:23 +note: the lifetime `'new` as defined on the function body at 41:23... + --> $DIR/variance-btree-invariant-types.rs:41:23 | LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:35:5 + --> $DIR/variance-btree-invariant-types.rs:48:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>` found struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 33:20... - --> $DIR/variance-btree-invariant-types.rs:33:20 +note: the lifetime `'new` as defined on the function body at 46:20... + --> $DIR/variance-btree-invariant-types.rs:46:20 | LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:39:5 + --> $DIR/variance-btree-invariant-types.rs:52:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` found struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 37:20... - --> $DIR/variance-btree-invariant-types.rs:37:20 +note: the lifetime `'new` as defined on the function body at 50:20... + --> $DIR/variance-btree-invariant-types.rs:50:20 | LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:43:5 + --> $DIR/variance-btree-invariant-types.rs:56:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>` found struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 41:23... - --> $DIR/variance-btree-invariant-types.rs:41:23 +note: the lifetime `'new` as defined on the function body at 54:23... + --> $DIR/variance-btree-invariant-types.rs:54:23 | LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:47:5 + --> $DIR/variance-btree-invariant-types.rs:60:5 | LL | v | ^ lifetime mismatch | = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` found struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 45:23... - --> $DIR/variance-btree-invariant-types.rs:45:23 +note: the lifetime `'new` as defined on the function body at 58:23... + --> $DIR/variance-btree-invariant-types.rs:58:23 | LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime -error: aborting due to 12 previous errors +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/wait-forked-but-failed-child.rs b/src/test/ui/wait-forked-but-failed-child.rs index 2683590775..0eb0fe071f 100644 --- a/src/test/ui/wait-forked-but-failed-child.rs +++ b/src/test/ui/wait-forked-but-failed-child.rs @@ -28,7 +28,7 @@ use std::process::Command; fn find_zombies() { let my_pid = unsafe { libc::getpid() }; - // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html let ps_cmd_output = Command::new("ps").args(&["-A", "-o", "pid,ppid,args"]).output().unwrap(); let ps_output = String::from_utf8_lossy(&ps_cmd_output.stdout); diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.rs b/src/test/ui/wf/hir-wf-check-erase-regions.rs new file mode 100644 index 0000000000..bb398e5698 --- /dev/null +++ b/src/test/ui/wf/hir-wf-check-erase-regions.rs @@ -0,0 +1,14 @@ +// Regression test for #87549. +// compile-flags: -C incremental=tmp/wf/hir-wf-check-erase-regions + +pub struct Table([Option; N]); + +impl<'a, T, const N: usize> IntoIterator for &'a Table { + type IntoIter = std::iter::Flatten>; //~ ERROR `&T` is not an iterator + type Item = &'a T; + + fn into_iter(self) -> Self::IntoIter { //~ ERROR `&T` is not an iterator + unimplemented!() + } +} +fn main() {} diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr new file mode 100644 index 0000000000..203f09994e --- /dev/null +++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr @@ -0,0 +1,31 @@ +error[E0277]: `&T` is not an iterator + --> $DIR/hir-wf-check-erase-regions.rs:7:5 + | +LL | type IntoIter = std::iter::Flatten>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator + | + ::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL + | +LL | pub struct Flatten> { + | ------------ required by this bound in `Flatten` + | + = help: the trait `Iterator` is not implemented for `&T` + = note: required because of the requirements on the impl of `IntoIterator` for `&T` + +error[E0277]: `&T` is not an iterator + --> $DIR/hir-wf-check-erase-regions.rs:10:27 + | +LL | fn into_iter(self) -> Self::IntoIter { + | ^^^^^^^^^^^^^^ `&T` is not an iterator + | + ::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL + | +LL | pub struct Flatten> { + | ------------ required by this bound in `Flatten` + | + = help: the trait `Iterator` is not implemented for `&T` + = note: required because of the requirements on the impl of `IntoIterator` for `&T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/wf/wf-complex-assoc-type.rs b/src/test/ui/wf/wf-complex-assoc-type.rs new file mode 100644 index 0000000000..c3811e8239 --- /dev/null +++ b/src/test/ui/wf/wf-complex-assoc-type.rs @@ -0,0 +1,12 @@ +trait MyTrait {} +struct AssertMyTrait(T); + +trait HelperTrait { + type MyItem; +} + +impl HelperTrait for () { + type MyItem = Option<((AssertMyTrait, u8))>; //~ ERROR the trait bound +} + +fn main() {} diff --git a/src/test/ui/wf/wf-complex-assoc-type.stderr b/src/test/ui/wf/wf-complex-assoc-type.stderr new file mode 100644 index 0000000000..c366519a8d --- /dev/null +++ b/src/test/ui/wf/wf-complex-assoc-type.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `bool: MyTrait` is not satisfied + --> $DIR/wf-complex-assoc-type.rs:9:28 + | +LL | struct AssertMyTrait(T); + | ------- required by this bound in `AssertMyTrait` +... +LL | type MyItem = Option<((AssertMyTrait, u8))>; + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr index 9081b7929d..f6b48938f9 100644 --- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr +++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -1,8 +1,11 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/wf-foreign-fn-decl-ret.rs:11:5 + --> $DIR/wf-foreign-fn-decl-ret.rs:11:25 | +LL | pub trait Foo { + | ------------- required by this bound in `Foo` +... LL | pub fn lint_me() -> <() as Foo>::Assoc; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 diff --git a/src/test/ui/wf/wf-impl-associated-type-trait.stderr b/src/test/ui/wf/wf-impl-associated-type-trait.stderr index 89399e30ca..0d4480fbf2 100644 --- a/src/test/ui/wf/wf-impl-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-trait.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: MyHash` is not satisfied - --> $DIR/wf-impl-associated-type-trait.rs:17:5 + --> $DIR/wf-impl-associated-type-trait.rs:17:16 | LL | pub struct MySet { | ------ required by this bound in `MySet` ... LL | type Bar = MySet; - | ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T` + | ^^^^^^^^ the trait `MyHash` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr index 9687658feb..ca90e9222d 100644 --- a/src/test/ui/wf/wf-in-fn-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-arg.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/wf-in-fn-arg.rs:10:14 + --> $DIR/wf-in-fn-arg.rs:10:15 | LL | struct MustBeCopy { | ---- required by this bound in `MustBeCopy` ... LL | fn bar(_: &MustBeCopy) - | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/wf/wf-in-fn-type-arg.stderr b/src/test/ui/wf/wf-in-fn-type-arg.stderr index 33300b3964..20aa977071 100644 --- a/src/test/ui/wf/wf-in-fn-type-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/wf-in-fn-type-arg.rs:9:8 + --> $DIR/wf-in-fn-type-arg.rs:9:11 | LL | struct MustBeCopy { | ---- required by this bound in `MustBeCopy` ... LL | x: fn(MustBeCopy) - | ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/wf/wf-in-fn-type-ret.stderr b/src/test/ui/wf/wf-in-fn-type-ret.stderr index 1ffc47e6d8..48af696c3a 100644 --- a/src/test/ui/wf/wf-in-fn-type-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/wf-in-fn-type-ret.rs:9:8 + --> $DIR/wf-in-fn-type-ret.rs:9:16 | LL | struct MustBeCopy { | ---- required by this bound in `MustBeCopy` ... LL | x: fn() -> MustBeCopy - | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs index 8386959cfb..4fcf8f403b 100644 --- a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs +++ b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs @@ -13,5 +13,5 @@ pub struct Ref<'a>(&'a u8); impl Trait for Ref {} //~ ERROR: implicit elided lifetime not allowed here extern "C" { - pub fn repro(_: Wrapper); //~ ERROR: mismatched types + pub fn repro(_: Wrapper); //~ ERROR: incompatible lifetime on type } diff --git a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr index bb839d0a5e..4e927cd983 100644 --- a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr +++ b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr @@ -3,22 +3,30 @@ error[E0726]: implicit elided lifetime not allowed here | LL | impl Trait for Ref {} | ^^^- help: indicate the anonymous lifetime: `<'_>` + | + = note: assuming a `'static` lifetime... -error[E0308]: mismatched types +error: incompatible lifetime on type --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21 | LL | pub fn repro(_: Wrapper); - | ^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:8:23 | - = note: expected trait `Trait` - found trait `Trait` +LL | pub struct Wrapper(T); + | ^^^^^ introduces a `'static` lifetime requirement note: the anonymous lifetime #1 defined on the method body at 16:5... --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5 | LL | pub fn repro(_: Wrapper); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...does not necessarily outlive the static lifetime +note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1 + | +LL | impl Trait for Ref {} + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/wf/wf-in-obj-type-trait.stderr b/src/test/ui/wf/wf-in-obj-type-trait.stderr index 8606eabf59..b3b919a569 100644 --- a/src/test/ui/wf/wf-in-obj-type-trait.stderr +++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/wf-in-obj-type-trait.rs:11:8 + --> $DIR/wf-in-obj-type-trait.rs:11:19 | LL | struct MustBeCopy { | ---- required by this bound in `MustBeCopy` ... LL | x: dyn Object> - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.rs b/src/test/ui/wf/wf-trait-associated-type-trait.rs index ddc0b323a1..d67e110ede 100644 --- a/src/test/ui/wf/wf-trait-associated-type-trait.rs +++ b/src/test/ui/wf/wf-trait-associated-type-trait.rs @@ -8,7 +8,7 @@ struct IsCopy { x: T } trait SomeTrait { type Type1; - type Type2 = IsCopy; + type Type2 = (IsCopy, bool); //~^ ERROR E0277 } diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr index a139186ebb..d1c2c65043 100644 --- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `::Type1: Copy` is not satisfied - --> $DIR/wf-trait-associated-type-trait.rs:11:5 + --> $DIR/wf-trait-associated-type-trait.rs:11:19 | LL | struct IsCopy { x: T } | ---- required by this bound in `IsCopy` ... -LL | type Type2 = IsCopy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `::Type1` +LL | type Type2 = (IsCopy, bool); + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `::Type1` | help: consider further restricting the associated type | diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr index c3d5d2b966..2a129538f7 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied - --> $DIR/wf-trait-default-fn-arg.rs:11:22 + --> $DIR/wf-trait-default-fn-arg.rs:11:23 | LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self, x: &Bar) { - | ^^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr index 4510f50fee..7693aa6d2d 100644 --- a/src/test/ui/wf/wf-trait-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-fn-arg.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied - --> $DIR/wf-trait-fn-arg.rs:10:22 + --> $DIR/wf-trait-fn-arg.rs:10:23 | LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self, x: &Bar); - | ^^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/write-fmt-errors.rs b/src/test/ui/write-fmt-errors.rs index 7dd9856442..3fcaefaa63 100644 --- a/src/test/ui/write-fmt-errors.rs +++ b/src/test/ui/write-fmt-errors.rs @@ -1,5 +1,7 @@ // run-pass +#![feature(io_error_uncategorized)] + use std::fmt; use std::io::{self, Error, Write, sink}; @@ -13,7 +15,7 @@ impl fmt::Display for ErrorDisplay { struct ErrorWriter; -const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Other; +const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Uncategorized; const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected; impl Write for ErrorWriter { diff --git a/src/test/ui/xc-private-method.stderr b/src/test/ui/xc-private-method.stderr index 8b7e43ccc0..69b414cc8f 100644 --- a/src/test/ui/xc-private-method.stderr +++ b/src/test/ui/xc-private-method.stderr @@ -3,12 +3,22 @@ error[E0624]: associated function `static_meth_struct` is private | LL | let _ = xc_private_method_lib::Struct::static_meth_struct(); | ^^^^^^^^^^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:8:5 + | +LL | fn static_meth_struct() -> Struct { + | --------------------------------- private associated function defined here error[E0624]: associated function `static_meth_enum` is private --> $DIR/xc-private-method.rs:9:42 | LL | let _ = xc_private_method_lib::Enum::static_meth_enum(); | ^^^^^^^^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:23:5 + | +LL | fn static_meth_enum() -> Enum { + | ----------------------------- private associated function defined here error: aborting due to 2 previous errors diff --git a/src/test/ui/xc-private-method2.stderr b/src/test/ui/xc-private-method2.stderr index 0ebdb0a06d..685ce0e0a1 100644 --- a/src/test/ui/xc-private-method2.stderr +++ b/src/test/ui/xc-private-method2.stderr @@ -3,12 +3,22 @@ error[E0624]: associated function `meth_struct` is private | LL | let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct(); | ^^^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:12:5 + | +LL | fn meth_struct(&self) -> isize { + | ------------------------------ private associated function defined here error[E0624]: associated function `meth_enum` is private --> $DIR/xc-private-method2.rs:9:55 | LL | let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum(); | ^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:27:5 + | +LL | fn meth_enum(&self) -> isize { + | ---------------------------- private associated function defined here error: aborting due to 2 previous errors diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml index 32103f59d8..d856c55a41 100644 --- a/src/tools/clippy/.github/workflows/clippy.yml +++ b/src/tools/clippy/.github/workflows/clippy.yml @@ -71,7 +71,7 @@ jobs: working-directory: clippy_workspace_tests - name: Test cargo-clippy --fix - run: ../target/debug/cargo-clippy clippy --fix -Zunstable-options + run: ../target/debug/cargo-clippy clippy --fix working-directory: clippy_workspace_tests - name: Test clippy-driver diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml index f27fee87dc..146b6fccd0 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_bors.yml @@ -90,11 +90,6 @@ jobs: - name: Checkout uses: actions/checkout@v2.3.3 - # FIXME: should not be necessary once 1.24.2 is the default version on the windows runner - - name: Update rustup - run: rustup self update - if: runner.os == 'Windows' - - name: Install toolchain run: rustup show active-toolchain @@ -139,7 +134,7 @@ jobs: working-directory: clippy_workspace_tests - name: Test cargo-clippy --fix - run: ../target/debug/cargo-clippy clippy --fix -Zunstable-options + run: ../target/debug/cargo-clippy clippy --fix working-directory: clippy_workspace_tests - name: Test clippy-driver diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml index 4f25a86b2e..77efdec1e5 100644 --- a/src/tools/clippy/.github/workflows/remark.yml +++ b/src/tools/clippy/.github/workflows/remark.yml @@ -22,7 +22,7 @@ jobs: uses: actions/setup-node@v1.4.4 - name: Install remark - run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended + run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm # Run - name: Check *.md files diff --git a/src/tools/clippy/.remarkrc b/src/tools/clippy/.remarkrc index 0ede7ac75c..04b82b8cc5 100644 --- a/src/tools/clippy/.remarkrc +++ b/src/tools/clippy/.remarkrc @@ -1,6 +1,7 @@ { "plugins": [ "remark-preset-lint-recommended", + "remark-gfm", ["remark-lint-list-item-indent", false], ["remark-lint-no-literal-urls", false], ["remark-lint-no-shortcut-reference-link", false], diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 41af8e190d..acbefc8064 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,139 @@ document. ## Unreleased / In Rust Nightly -[7c7683c...master](https://github.com/rust-lang/rust-clippy/compare/7c7683c...master) +[3ae8faf...master](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...master) + +## Rust 1.54 + +Current beta, release 2021-07-29 + +[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf) + +### New Lints + +- [`ref_binding_to_reference`] + [#7105](https://github.com/rust-lang/rust-clippy/pull/7105) +- [`needless_bitwise_bool`] + [#7133](https://github.com/rust-lang/rust-clippy/pull/7133) +- [`unused_async`] [#7225](https://github.com/rust-lang/rust-clippy/pull/7225) +- [`manual_str_repeat`] + [#7265](https://github.com/rust-lang/rust-clippy/pull/7265) +- [`suspicious_splitn`] + [#7292](https://github.com/rust-lang/rust-clippy/pull/7292) + +### Moves and Deprecations + +- Deprecate `pub_enum_variant_names` and `wrong_pub_self_convention` in favor of + the new `avoid_breaking_exported_api` config option (see + [Enhancements](#1-54-enhancements)) + [#7187](https://github.com/rust-lang/rust-clippy/pull/7187) +- Move [`inconsistent_struct_constructor`] to `pedantic` + [#7193](https://github.com/rust-lang/rust-clippy/pull/7193) +- Move [`needless_borrow`] to `style` (now warn-by-default) + [#7254](https://github.com/rust-lang/rust-clippy/pull/7254) +- Move [`suspicious_operation_groupings`] to `nursery` + [#7266](https://github.com/rust-lang/rust-clippy/pull/7266) +- Move [`semicolon_if_nothing_returned`] to `pedantic` + [#7268](https://github.com/rust-lang/rust-clippy/pull/7268) + +### Enhancements + +- [`while_let_on_iterator`]: Now also lints in nested loops + [#6966](https://github.com/rust-lang/rust-clippy/pull/6966) +- [`single_char_pattern`]: Now also lints on `strip_prefix` and `strip_suffix` + [#7156](https://github.com/rust-lang/rust-clippy/pull/7156) +- [`needless_collect`]: Now also lints on assignments with type annotations + [#7163](https://github.com/rust-lang/rust-clippy/pull/7163) +- [`if_then_some_else_none`]: Now works with the MSRV config + [#7177](https://github.com/rust-lang/rust-clippy/pull/7177) +- Add `avoid_breaking_exported_api` config option for the lints + [`enum_variant_names`], [`large_types_passed_by_value`], + [`trivially_copy_pass_by_ref`], [`unnecessary_wraps`], + [`upper_case_acronyms`], and [`wrong_self_convention`]. We recommend to set + this configuration option to `false` before a major release (1.0/2.0/...) to + clean up the API [#7187](https://github.com/rust-lang/rust-clippy/pull/7187) +- [`needless_collect`]: Now lints on even more data structures + [#7188](https://github.com/rust-lang/rust-clippy/pull/7188) +- [`missing_docs_in_private_items`]: No longer sees `#[ = ""]` like + attributes as sufficient documentation + [#7281](https://github.com/rust-lang/rust-clippy/pull/7281) +- [`needless_collect`], [`short_circuit_statement`], [`unnecessary_operation`]: + Now work as expected when used with `allow` + [#7282](https://github.com/rust-lang/rust-clippy/pull/7282) + +### False Positive Fixes + +- [`implicit_return`]: Now takes all diverging functions in account to avoid + false positives [#6951](https://github.com/rust-lang/rust-clippy/pull/6951) +- [`while_let_on_iterator`]: No longer lints when the iterator is a struct field + and the struct is used in the loop + [#6966](https://github.com/rust-lang/rust-clippy/pull/6966) +- [`multiple_inherent_impl`]: No longer lints with generic arguments + [#7089](https://github.com/rust-lang/rust-clippy/pull/7089) +- [`comparison_chain`]: No longer lints in a `const` context + [#7118](https://github.com/rust-lang/rust-clippy/pull/7118) +- [`while_immutable_condition`]: Fix false positive where mutation in the loop + variable wasn't picked up + [#7144](https://github.com/rust-lang/rust-clippy/pull/7144) +- [`default_trait_access`]: No longer lints in macros + [#7150](https://github.com/rust-lang/rust-clippy/pull/7150) +- [`needless_question_mark`]: No longer lints when the inner value is implicitly + dereferenced [#7165](https://github.com/rust-lang/rust-clippy/pull/7165) +- [`unused_unit`]: No longer lints when multiple macro contexts are involved + [#7167](https://github.com/rust-lang/rust-clippy/pull/7167) +- [`eval_order_dependence`]: Fix false positive in async context + [#7174](https://github.com/rust-lang/rust-clippy/pull/7174) +- [`unnecessary_filter_map`]: No longer lints if the `filter_map` changes the + type [#7175](https://github.com/rust-lang/rust-clippy/pull/7175) +- [`wrong_self_convention`]: No longer lints in trait implementations of + non-`Copy` types [#7182](https://github.com/rust-lang/rust-clippy/pull/7182) +- [`suboptimal_flops`]: No longer lints on `powi(2)` + [#7201](https://github.com/rust-lang/rust-clippy/pull/7201) +- [`wrong_self_convention`]: No longer lints if there is no implicit `self` + [#7215](https://github.com/rust-lang/rust-clippy/pull/7215) +- [`option_if_let_else`]: No longer lints on `else if let` pattern + [#7216](https://github.com/rust-lang/rust-clippy/pull/7216) +- [`use_self`], [`useless_conversion`]: Fix false positives when generic + arguments are involved + [#7223](https://github.com/rust-lang/rust-clippy/pull/7223) +- [`manual_unwrap_or`]: Fix false positive with deref coercion + [#7233](https://github.com/rust-lang/rust-clippy/pull/7233) +- [`similar_names`]: No longer lints on `wparam`/`lparam` + [#7255](https://github.com/rust-lang/rust-clippy/pull/7255) +- [`redundant_closure`]: No longer lints on using the `vec![]` macro in a + closure [#7263](https://github.com/rust-lang/rust-clippy/pull/7263) + +### Suggestion Fixes/Improvements + +- [`implicit_return`] + [#6951](https://github.com/rust-lang/rust-clippy/pull/6951) + - Fix suggestion for async functions + - Improve suggestion with macros + - Suggest to change `break` to `return` when appropriate +- [`while_let_on_iterator`]: Now suggests `&mut iter` when necessary + [#6966](https://github.com/rust-lang/rust-clippy/pull/6966) +- [`match_single_binding`]: Improve suggestion when match scrutinee has side + effects [#7095](https://github.com/rust-lang/rust-clippy/pull/7095) +- [`needless_borrow`]: Now suggests to also change usage sites as needed + [#7105](https://github.com/rust-lang/rust-clippy/pull/7105) +- [`write_with_newline`]: Improve suggestion when only `\n` is written to the + buffer [#7183](https://github.com/rust-lang/rust-clippy/pull/7183) +- [`from_iter_instead_of_collect`]: The suggestion is now auto applicable also + when a `<_ as Trait>::_` is involved + [#7264](https://github.com/rust-lang/rust-clippy/pull/7264) +- [`not_unsafe_ptr_arg_deref`]: Improved error message + [#7294](https://github.com/rust-lang/rust-clippy/pull/7294) + +### ICE Fixes + +- Fix ICE when running Clippy on `libstd` + [#7140](https://github.com/rust-lang/rust-clippy/pull/7140) +- [`implicit_return`] + [#7242](https://github.com/rust-lang/rust-clippy/pull/7242) ## Rust 1.53 -Current beta, release 2021-06-17 +Current stable, released 2021-06-17 [6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c) @@ -194,7 +322,7 @@ Current beta, release 2021-06-17 ## Rust 1.52 -Current stable, released 2021-05-06 +Released 2021-05-06 [3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e) @@ -464,7 +592,7 @@ Released 2021-02-11 * Previously deprecated [`str_to_string`] and [`string_to_string`] have been un-deprecated as `restriction` lints [#6333](https://github.com/rust-lang/rust-clippy/pull/6333) -* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panic` +* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panics` [#6351](https://github.com/rust-lang/rust-clippy/pull/6351) * Move [`map_err_ignore`] to `restriction` [#6416](https://github.com/rust-lang/rust-clippy/pull/6416) @@ -2358,6 +2486,8 @@ 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 [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method +[`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents +[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons @@ -2391,6 +2521,7 @@ Released 2018-09-13 [`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop [`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write [`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice +[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain [`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes [`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from [`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default @@ -2527,6 +2658,7 @@ Released 2018-09-13 [`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op [`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items +[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames [`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items [`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc @@ -2574,6 +2706,7 @@ Released 2018-09-13 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool [`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options +[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces [`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref [`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref @@ -2611,6 +2744,7 @@ Released 2018-09-13 [`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero [`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len [`rc_buffer`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer +[`rc_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex [`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure @@ -2638,6 +2772,7 @@ Released 2018-09-13 [`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some [`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment +[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse @@ -2664,6 +2799,7 @@ Released 2018-09-13 [`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes [`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string +[`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools [`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index 7265d1b832..4273fda4e6 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -115,7 +115,7 @@ To work around this, you need to have a copy of the [rustc-repo][rustc_repo] ava `git clone https://github.com/rust-lang/rust/`. Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies which `IntelliJ Rust` will be able to understand. -Run `cargo dev ide_setup --repo-path ` where `` is a path to the rustc repo +Run `cargo dev setup intellij --repo-path ` where `` is a path to the rustc repo you just cloned. The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to Clippys `Cargo.toml`s and should allow `IntelliJ Rust` to understand most of the types that Clippy uses. @@ -342,7 +342,7 @@ We have prioritization labels and a sync-blocker label, which are described belo - [P-low][p-low]: Requires attention (fix/response/evaluation) by a team member but isn't urgent. - [P-medium][p-medium]: Should be addressed by a team member until the next sync. - [P-high][p-high]: Should be immediately addressed and will require an out-of-cycle sync or a backport. -- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync. +- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync. Or rather: before the sync this should be addressed, e.g. by removing a lint again, so it doesn't hit beta/stable. diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index b003b15a11..9b5d9b2adf 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.54" +version = "0.1.55" authors = ["The Rust Clippy Developers"] description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index 6c556f579c..e1c968273c 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -10,16 +10,17 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. -| Category | Description | Default level | -| --------------------- | ----------------------------------------------------------------------- | ------------- | -| `clippy::all` | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny** | -| `clippy::correctness` | code that is outright wrong or very useless | **deny** | -| `clippy::style` | code that should be written in a more idiomatic way | **warn** | -| `clippy::complexity` | code that does something simple but in a complex way | **warn** | -| `clippy::perf` | code that can be written to run faster | **warn** | -| `clippy::pedantic` | lints which are rather strict or might have false positives | allow | -| `clippy::nursery` | new lints that are still under development | allow | -| `clippy::cargo` | lints for the cargo manifest | allow | +| Category | Description | Default level | +| --------------------- | ----------------------------------------------------------------------------------- | ------------- | +| `clippy::all` | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** | +| `clippy::correctness` | code that is outright wrong or useless | **deny** | +| `clippy::suspicious` | code that is most likely wrong or useless | **warn** | +| `clippy::style` | code that should be written in a more idiomatic way | **warn** | +| `clippy::complexity` | code that does something simple but in a complex way | **warn** | +| `clippy::perf` | code that can be written to run faster | **warn** | +| `clippy::pedantic` | lints which are rather strict or might have false positives | allow | +| `clippy::nursery` | new lints that are still under development | allow | +| `clippy::cargo` | lints for the cargo manifest | allow | More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas! @@ -75,11 +76,10 @@ cargo clippy #### Automatically applying Clippy suggestions -Clippy can automatically apply some lint suggestions. -Note that this is still experimental and only supported on the nightly channel: +Clippy can automatically apply some lint suggestions, just like the compiler. ```terminal -cargo clippy --fix -Z unstable-options +cargo clippy --fix ``` #### Workspaces @@ -95,7 +95,7 @@ As with `cargo check`, this includes dependencies that are members of the worksp If you want to run Clippy **only** on the given crate, use the `--no-deps` option like this: ```terminal -cargo clippy -p example -- --no-deps +cargo clippy -p example -- --no-deps ``` ### As a rustc replacement (`clippy-driver`) diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index b1844e29b3..5c6c106e0e 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" bytecount = "0.6" clap = "2.33" itertools = "0.9" -opener = "0.4" +opener = "0.5" regex = "1" shell-escape = "0.1" walkdir = "2" diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs index 1517cdc941..c81eb40d52 100644 --- a/src/tools/clippy/clippy_dev/src/fmt.rs +++ b/src/tools/clippy/clippy_dev/src/fmt.rs @@ -60,11 +60,7 @@ pub fn run(check: bool, verbose: bool) { let entry = entry?; let path = entry.path(); - if path.extension() != Some("rs".as_ref()) - || entry.file_name() == "ice-3891.rs" - // Avoid rustfmt bug rust-lang/rustfmt#1873 - || cfg!(windows) && entry.file_name() == "implicit_hasher.rs" - { + if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" { continue; } @@ -90,7 +86,7 @@ pub fn run(check: bool, verbose: bool) { }, CliError::RaSetupActive => { eprintln!( - "error: a local rustc repo is enabled as path dependency via `cargo dev ide_setup`. + "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`. Not formatting because that would format the local repo as well! Please revert the changes to Cargo.tomls first." ); diff --git a/src/tools/clippy/clippy_dev/src/ide_setup.rs b/src/tools/clippy/clippy_dev/src/ide_setup.rs deleted file mode 100644 index defb1133e4..0000000000 --- a/src/tools/clippy/clippy_dev/src/ide_setup.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::fs; -use std::fs::File; -use std::io::prelude::*; -use std::path::{Path, PathBuf}; - -// This module takes an absolute path to a rustc repo and alters the dependencies to point towards -// the respective rustc subcrates instead of using extern crate xyz. -// This allows rust analyzer to analyze rustc internals and show proper information inside clippy -// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details - -/// # Panics -/// -/// Panics if `rustc_path` does not lead to a rustc repo or the files could not be read -pub fn run(rustc_path: Option<&str>) { - // we can unwrap here because the arg is required by clap - let rustc_path = PathBuf::from(rustc_path.unwrap()) - .canonicalize() - .expect("failed to get the absolute repo path"); - assert!(rustc_path.is_dir(), "path is not a directory"); - let rustc_source_basedir = rustc_path.join("compiler"); - assert!( - rustc_source_basedir.is_dir(), - "are you sure the path leads to a rustc repo?" - ); - - let clippy_root_manifest = fs::read_to_string("Cargo.toml").expect("failed to read ./Cargo.toml"); - let clippy_root_lib_rs = fs::read_to_string("src/driver.rs").expect("failed to read ./src/driver.rs"); - inject_deps_into_manifest( - &rustc_source_basedir, - "Cargo.toml", - &clippy_root_manifest, - &clippy_root_lib_rs, - ) - .expect("Failed to inject deps into ./Cargo.toml"); - - let clippy_lints_manifest = - fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml"); - let clippy_lints_lib_rs = - fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs"); - inject_deps_into_manifest( - &rustc_source_basedir, - "clippy_lints/Cargo.toml", - &clippy_lints_manifest, - &clippy_lints_lib_rs, - ) - .expect("Failed to inject deps into ./clippy_lints/Cargo.toml"); -} - -fn inject_deps_into_manifest( - rustc_source_dir: &Path, - manifest_path: &str, - cargo_toml: &str, - lib_rs: &str, -) -> std::io::Result<()> { - // do not inject deps if we have aleady done so - if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") { - eprintln!( - "cargo dev ide_setup: warning: deps already found inside {}, doing nothing.", - manifest_path - ); - return Ok(()); - } - - let extern_crates = lib_rs - .lines() - // get the deps - .filter(|line| line.starts_with("extern crate")) - // we have something like "extern crate foo;", we only care about the "foo" - // ↓ ↓ - // extern crate rustc_middle; - .map(|s| &s[13..(s.len() - 1)]); - - 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 a new [dependencies]-block with the new deps we need to inject - let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n"); - new_deps.for_each(|dep_line| { - all_deps.push_str(&dep_line); - }); - all_deps.push_str("\n[dependencies]\n"); - - // replace "[dependencies]" with - // [dependencies] - // dep1 = { path = ... } - // dep2 = { path = ... } - // etc - let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1); - - // println!("{}", new_manifest); - let mut file = File::create(manifest_path)?; - file.write_all(new_manifest.as_bytes())?; - - println!("Dependency paths injected: {}", manifest_path); - - Ok(()) -} diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index 69f42aca8b..72bdaf8d59 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -14,9 +14,9 @@ use walkdir::WalkDir; pub mod bless; pub mod fmt; -pub mod ide_setup; pub mod new_lint; pub mod serve; +pub mod setup; pub mod stderr_length_check; pub mod update_lints; diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 7040c257c8..ff324ff6ee 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -2,8 +2,8 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] -use clap::{App, Arg, ArgMatches, SubCommand}; -use clippy_dev::{bless, fmt, ide_setup, new_lint, serve, stderr_length_check, update_lints}; +use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; +use clippy_dev::{bless, fmt, new_lint, serve, setup, stderr_length_check, update_lints}; fn main() { let matches = get_clap_config(); @@ -36,7 +36,22 @@ fn main() { ("limit_stderr_length", _) => { stderr_length_check::check(); }, - ("ide_setup", Some(matches)) => ide_setup::run(matches.value_of("rustc-repo-path")), + ("setup", Some(sub_command)) => match sub_command.subcommand() { + ("intellij", Some(matches)) => setup::intellij::setup_rustc_src( + matches + .value_of("rustc-repo-path") + .expect("this field is mandatory and therefore always valid"), + ), + ("git-hook", Some(matches)) => setup::git_hook::install_hook(matches.is_present("force-override")), + ("vscode-tasks", Some(matches)) => setup::vscode::install_tasks(matches.is_present("force-override")), + _ => {}, + }, + ("remove", Some(sub_command)) => match sub_command.subcommand() { + ("git-hook", Some(_)) => setup::git_hook::remove_hook(), + ("intellij", Some(_)) => setup::intellij::remove_rustc_src(), + ("vscode-tasks", Some(_)) => setup::vscode::remove_tasks(), + _ => {}, + }, ("serve", Some(matches)) => { let port = matches.value_of("port").unwrap().parse().unwrap(); let lint = matches.value_of("lint"); @@ -48,6 +63,7 @@ fn main() { fn get_clap_config<'a>() -> ArgMatches<'a> { App::new("Clippy developer tooling") + .setting(AppSettings::ArgRequiredElseHelp) .subcommand( SubCommand::with_name("bless") .about("bless the test output changes") @@ -123,6 +139,7 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { .possible_values(&[ "style", "correctness", + "suspicious", "complexity", "perf", "pedantic", @@ -140,16 +157,54 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { .about("Ensures that stderr files do not grow longer than a certain amount of lines."), ) .subcommand( - SubCommand::with_name("ide_setup") - .about("Alter dependencies so Intellij Rust can find rustc internals") - .arg( - Arg::with_name("rustc-repo-path") - .long("repo-path") - .short("r") - .help("The path to a rustc repo that will be used for setting the dependencies") - .takes_value(true) - .value_name("path") - .required(true), + SubCommand::with_name("setup") + .about("Support for setting up your personal development environment") + .setting(AppSettings::ArgRequiredElseHelp) + .subcommand( + SubCommand::with_name("intellij") + .about("Alter dependencies so Intellij Rust can find rustc internals") + .arg( + Arg::with_name("rustc-repo-path") + .long("repo-path") + .short("r") + .help("The path to a rustc repo that will be used for setting the dependencies") + .takes_value(true) + .value_name("path") + .required(true), + ), + ) + .subcommand( + SubCommand::with_name("git-hook") + .about("Add a pre-commit git hook that formats your code to make it look pretty") + .arg( + Arg::with_name("force-override") + .long("force-override") + .short("f") + .help("Forces the override of an existing git pre-commit hook") + .required(false), + ), + ) + .subcommand( + SubCommand::with_name("vscode-tasks") + .about("Add several tasks to vscode for formatting, validation and testing") + .arg( + Arg::with_name("force-override") + .long("force-override") + .short("f") + .help("Forces the override of existing vscode tasks") + .required(false), + ), + ), + ) + .subcommand( + SubCommand::with_name("remove") + .about("Support for undoing changes done by the setup command") + .setting(AppSettings::ArgRequiredElseHelp) + .subcommand(SubCommand::with_name("git-hook").about("Remove any existing pre-commit git hook")) + .subcommand(SubCommand::with_name("vscode-tasks").about("Remove any existing vscode tasks")) + .subcommand( + SubCommand::with_name("intellij") + .about("Removes rustc source paths added via `cargo dev setup intellij`"), ), ) .subcommand( diff --git a/src/tools/clippy/clippy_dev/src/setup/git_hook.rs b/src/tools/clippy/clippy_dev/src/setup/git_hook.rs new file mode 100644 index 0000000000..3fbb77d592 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/git_hook.rs @@ -0,0 +1,85 @@ +use std::fs; +use std::path::Path; + +use super::verify_inside_clippy_dir; + +/// Rusts setup uses `git rev-parse --git-common-dir` to get the root directory of the repo. +/// I've decided against this for the sake of simplicity and to make sure that it doesn't install +/// the hook if `clippy_dev` would be used in the rust tree. The hook also references this tool +/// for formatting and should therefor only be used in a normal clone of clippy +const REPO_GIT_DIR: &str = ".git"; +const HOOK_SOURCE_FILE: &str = "util/etc/pre-commit.sh"; +const HOOK_TARGET_FILE: &str = ".git/hooks/pre-commit"; + +pub fn install_hook(force_override: bool) { + if !check_precondition(force_override) { + return; + } + + // So a little bit of a funny story. Git on unix requires the pre-commit file + // to have the `execute` permission to be set. The Rust functions for modifying + // these flags doesn't seem to work when executed with normal user permissions. + // + // However, there is a little hack that is also being used by Rust itself in their + // setup script. Git saves the `execute` flag when syncing files. This means + // that we can check in a file with execution permissions and the sync it to create + // a file with the flag set. We then copy this file here. The copy function will also + // include the `execute` permission. + match fs::copy(HOOK_SOURCE_FILE, HOOK_TARGET_FILE) { + Ok(_) => { + 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 + ), + } +} + +fn check_precondition(force_override: bool) -> bool { + if !verify_inside_clippy_dir() { + return false; + } + + // Make sure that we can find the git repository + let git_path = Path::new(REPO_GIT_DIR); + if !git_path.exists() || !git_path.is_dir() { + eprintln!("error: clippy_dev was unable to find the `.git` directory"); + return false; + } + + // Make sure that we don't override an existing hook by accident + let path = Path::new(HOOK_TARGET_FILE); + if path.exists() { + if force_override { + return delete_git_hook_file(path); + } + + eprintln!("error: there is already a pre-commit hook installed"); + println!("info: use the `--force-override` flag to override the existing hook"); + return false; + } + + true +} + +pub fn remove_hook() { + let path = Path::new(HOOK_TARGET_FILE); + if path.exists() { + if delete_git_hook_file(path) { + println!("git hook successfully removed"); + } + } else { + println!("no pre-commit hook was found"); + } +} + +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); + 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 new file mode 100644 index 0000000000..bf741e6d12 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/intellij.rs @@ -0,0 +1,223 @@ +use std::fs; +use std::fs::File; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; + +// This module takes an absolute path to a rustc repo and alters the dependencies to point towards +// the respective rustc subcrates instead of using extern crate xyz. +// This allows IntelliJ to analyze rustc internals and show proper information inside Clippy +// code. See https://github.com/rust-lang/rust-clippy/issues/5514 for details + +const RUSTC_PATH_SECTION: &str = "[target.'cfg(NOT_A_PLATFORM)'.dependencies]"; +const DEPENDENCIES_SECTION: &str = "[dependencies]"; + +const CLIPPY_PROJECTS: &[ClippyProjectInfo] = &[ + ClippyProjectInfo::new("root", "Cargo.toml", "src/driver.rs"), + ClippyProjectInfo::new("clippy_lints", "clippy_lints/Cargo.toml", "clippy_lints/src/lib.rs"), + ClippyProjectInfo::new("clippy_utils", "clippy_utils/Cargo.toml", "clippy_utils/src/lib.rs"), +]; + +/// Used to store clippy project information to later inject the dependency into. +struct ClippyProjectInfo { + /// Only used to display information to the user + name: &'static str, + cargo_file: &'static str, + lib_rs_file: &'static str, +} + +impl ClippyProjectInfo { + const fn new(name: &'static str, cargo_file: &'static str, lib_rs_file: &'static str) -> Self { + Self { + name, + cargo_file, + lib_rs_file, + } + } +} + +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, + }; + + for project in CLIPPY_PROJECTS { + if inject_deps_into_project(&rustc_source_dir, project).is_err() { + return; + } + } + + println!("info: the source paths can be removed again with `cargo dev remove intellij`"); +} + +fn check_and_get_rustc_dir(rustc_path: &str) -> Result { + let mut path = PathBuf::from(rustc_path); + + if path.is_relative() { + match path.canonicalize() { + Ok(absolute_path) => { + println!("info: the rustc path was resolved to: `{}`", absolute_path.display()); + path = absolute_path; + }, + Err(err) => { + eprintln!("error: unable to get the absolute path of rustc ({})", err); + return Err(()); + }, + }; + } + + let path = path.join("compiler"); + println!("info: looking for compiler sources at: {}", path.display()); + + if !path.exists() { + eprintln!("error: the given path does not exist"); + return Err(()); + } + + if !path.is_dir() { + eprintln!("error: the given path is not a directory"); + return Err(()); + } + + Ok(path) +} + +fn inject_deps_into_project(rustc_source_dir: &Path, project: &ClippyProjectInfo) -> Result<(), ()> { + let cargo_content = read_project_file(project.cargo_file)?; + let lib_content = read_project_file(project.lib_rs_file)?; + + if inject_deps_into_manifest(rustc_source_dir, project.cargo_file, &cargo_content, &lib_content).is_err() { + eprintln!( + "error: unable to inject dependencies into {} with the Cargo file {}", + project.name, project.cargo_file + ); + Err(()) + } else { + Ok(()) + } +} + +/// `clippy_dev` expects to be executed in the root directory of Clippy. This function +/// loads the given file or returns an error. Having it in this extra function ensures +/// that the error message looks nice. +fn read_project_file(file_path: &str) -> Result { + let path = Path::new(file_path); + if !path.exists() { + 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); + Err(()) + }, + } +} + +fn inject_deps_into_manifest( + rustc_source_dir: &Path, + manifest_path: &str, + cargo_toml: &str, + lib_rs: &str, +) -> 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 + ); + return Ok(()); + } + + let extern_crates = lib_rs + .lines() + // only take dependencies starting with `rustc_` + .filter(|line| line.starts_with("extern crate rustc_")) + // we have something like "extern crate foo;", we only care about the "foo" + // extern crate rustc_middle; + // ^^^^^^^^^^^^ + .map(|s| &s[13..(s.len() - 1)]); + + 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 a new [dependencies]-block with the new deps we need to inject + let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n"); + new_deps.for_each(|dep_line| { + all_deps.push_str(&dep_line); + }); + all_deps.push_str("\n[dependencies]\n"); + + // replace "[dependencies]" with + // [dependencies] + // dep1 = { path = ... } + // dep2 = { path = ... } + // etc + let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1); + + // 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); + + Ok(()) +} + +pub fn remove_rustc_src() { + for project in CLIPPY_PROJECTS { + remove_rustc_src_from_project(project); + } +} + +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 { + return false; + }; + let section_start = if let Some(section_start) = cargo_content.find(RUSTC_PATH_SECTION) { + section_start + } else { + println!( + "info: dependencies could not be found in `{}` for {}, skipping file", + project.cargo_file, project.name + ); + return true; + }; + + let end_point = if let Some(end_point) = cargo_content.find(DEPENDENCIES_SECTION) { + end_point + } else { + eprintln!( + "error: the end of the rustc dependencies section could not be found in `{}`", + project.cargo_file + ); + return false; + }; + + cargo_content.replace_range(section_start..end_point, ""); + + match File::create(project.cargo_file) { + Ok(mut file) => { + file.write_all(cargo_content.as_bytes()).unwrap(); + println!("info: successfully removed dependencies inside {}", project.cargo_file); + true + }, + Err(err) => { + eprintln!( + "error: unable to open file `{}` to remove rustc dependencies for {} ({})", + project.cargo_file, project.name, err + ); + false + }, + } +} diff --git a/src/tools/clippy/clippy_dev/src/setup/mod.rs b/src/tools/clippy/clippy_dev/src/setup/mod.rs new file mode 100644 index 0000000000..a1e4dd103b --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/mod.rs @@ -0,0 +1,23 @@ +pub mod git_hook; +pub mod intellij; +pub mod vscode; + +use std::path::Path; + +const CLIPPY_DEV_DIR: &str = "clippy_dev"; + +/// This function verifies that the tool is being executed in the clippy directory. +/// This is useful to ensure that setups only modify Clippys resources. The verification +/// is done by checking that `clippy_dev` is a sub directory of the current directory. +/// +/// It will print an error message and return `false` if the directory could not be +/// verified. +fn verify_inside_clippy_dir() -> bool { + let path = Path::new(CLIPPY_DEV_DIR); + if path.exists() && path.is_dir() { + true + } else { + eprintln!("error: unable to verify that the working directory is clippys directory"); + false + } +} diff --git a/src/tools/clippy/clippy_dev/src/setup/vscode.rs b/src/tools/clippy/clippy_dev/src/setup/vscode.rs new file mode 100644 index 0000000000..d59001b2c6 --- /dev/null +++ b/src/tools/clippy/clippy_dev/src/setup/vscode.rs @@ -0,0 +1,104 @@ +use std::fs; +use std::path::Path; + +use super::verify_inside_clippy_dir; + +const VSCODE_DIR: &str = ".vscode"; +const TASK_SOURCE_FILE: &str = "util/etc/vscode-tasks.json"; +const TASK_TARGET_FILE: &str = ".vscode/tasks.json"; + +pub fn install_tasks(force_override: bool) { + if !check_install_precondition(force_override) { + return; + } + + match fs::copy(TASK_SOURCE_FILE, TASK_TARGET_FILE) { + Ok(_) => { + 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 + ), + } +} + +fn check_install_precondition(force_override: bool) -> bool { + if !verify_inside_clippy_dir() { + return false; + } + + let vs_dir_path = Path::new(VSCODE_DIR); + if vs_dir_path.exists() { + // verify the target will be valid + if !vs_dir_path.is_dir() { + eprintln!("error: the `.vscode` path exists but seems to be a file"); + return false; + } + + // make sure that we don't override any existing tasks by accident + let path = Path::new(TASK_TARGET_FILE); + if path.exists() { + if force_override { + return delete_vs_task_file(path); + } + + eprintln!( + "error: there is already a `task.json` file inside the `{}` directory", + VSCODE_DIR + ); + 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); + }, + Err(err) => { + eprintln!( + "error: the task target directory `{}` could not be created ({})", + VSCODE_DIR, err + ); + }, + } + } + + true +} + +pub fn remove_tasks() { + let path = Path::new(TASK_TARGET_FILE); + if path.exists() { + if delete_vs_task_file(path) { + try_delete_vs_directory_if_empty(); + println!("vscode tasks successfully removed"); + } + } else { + println!("no vscode tasks were found"); + } +} + +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); + return false; + } + + true +} + +/// This function will try to delete the `.vscode` directory if it's empty. +/// It may fail silently. +fn try_delete_vs_directory_if_empty() { + let path = Path::new(VSCODE_DIR); + if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) { + // The directory is empty. We just try to delete it but allow a silence + // fail as an empty `.vscode` directory is still valid + let _silence_result = fs::remove_dir(path); + } else { + // The directory is not empty or could not be read. Either way don't take + // any further actions + } +} diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index edf6c5f57a..db467c26f1 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -92,7 +92,10 @@ pub fn run(update_mode: UpdateMode) { || { // clippy::all should only include the following lint groups: let all_group_lints = usable_lints.iter().filter(|l| { - l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf" + matches!( + &*l.group, + "correctness" | "suspicious" | "style" | "complexity" | "perf" + ) }); gen_lint_group_list(all_group_lints) diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 48f2972ec5..42cf7547f5 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.1.54" +version = "0.1.55" # end automatic update authors = ["The Rust Clippy Developers"] description = "A bunch of helpful lints to avoid common pitfalls in Rust" @@ -23,6 +23,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } toml = "0.5.3" unicode-normalization = "0.1" +unicode-script = { version = "0.5.3", default-features = false } semver = "0.11" rustc-semver = "1.1.0" # NOTE: cargo requires serde feat in its url dep diff --git a/src/tools/clippy/clippy_lints/src/assign_ops.rs b/src/tools/clippy/clippy_lints/src/assign_ops.rs index bc6eec0051..17ce3cd809 100644 --- a/src/tools/clippy/clippy_lints/src/assign_ops.rs +++ b/src/tools/clippy/clippy_lints/src/assign_ops.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; -use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method}; -use clippy_utils::{higher, paths, sugg}; +use clippy_utils::{binop_traits, sugg}; +use clippy_utils::{eq_expr_value, trait_ref_of_method}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -55,7 +55,7 @@ declare_clippy_lint! { /// a += a + b; /// ``` pub MISREFACTORED_ASSIGN_OP, - complexity, + suspicious, "having a variable on both sides of an assign op" } @@ -85,71 +85,34 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps { let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { let ty = cx.typeck_results().expr_ty(assignee); let rty = cx.typeck_results().expr_ty(rhs); - macro_rules! ops { - ($op:expr, - $cx:expr, - $ty:expr, - $rty:expr, - $($trait_name:ident),+) => { - match $op { - $(hir::BinOpKind::$trait_name => { - let [krate, module] = paths::OPS_MODULE; - let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")]; - let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) { - trait_id - } else { - return; // useless if the trait doesn't exist - }; - // check that we are not inside an `impl AssignOp` of this exact operation - let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); - if_chain! { - if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn); - if trait_ref.path.res.def_id() == trait_id; - then { return; } + 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); + 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()]); + then { + span_lint_and_then( + cx, + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation", + |diag| { + if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + { + diag.span_suggestion( + expr.span, + "replace it with", + format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), + Applicability::MachineApplicable, + ); } - implements_trait($cx, $ty, trait_id, &[$rty]) - },)* - _ => false, - } + }, + ); } } - if ops!( - op.node, - cx, - ty, - rty.into(), - Add, - Sub, - Mul, - Div, - Rem, - And, - Or, - BitAnd, - BitOr, - BitXor, - Shr, - Shl - ) { - span_lint_and_then( - cx, - ASSIGN_OP_PATTERN, - expr.span, - "manual implementation of an assign operation", - |diag| { - if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) - { - diag.span_suggestion( - expr.span, - "replace it with", - format!("{} {}= {}", snip_a, op.node.as_str(), snip_r), - Applicability::MachineApplicable, - ); - } - }, - ); - } }; let mut visitor = ExprVisitor { @@ -206,7 +169,7 @@ 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(higher::binop(op.node), a, r)); + let long = format!("{} = {}", snip_a, sugg::make_binop(op.node.into(), a, r)); diag.span_suggestion( expr.span, &format!( diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 932cd58bf6..f272ed010a 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -173,7 +173,7 @@ declare_clippy_lint! { /// #![deny(clippy::as_conversions)] /// ``` pub BLANKET_CLIPPY_RESTRICTION_LINTS, - style, + suspicious, "enabling the complete restriction group" } diff --git a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs index b26ef33e05..8eb94f3c28 100644 --- a/src/tools/clippy/clippy_lints/src/blacklisted_name.rs +++ b/src/tools/clippy/clippy_lints/src/blacklisted_name.rs @@ -1,6 +1,6 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::{diagnostics::span_lint, is_test_module_or_function}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{Pat, PatKind}; +use rustc_hir::{Item, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -25,18 +25,37 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct BlacklistedName { blacklist: FxHashSet, + test_modules_deep: u32, } impl BlacklistedName { pub fn new(blacklist: FxHashSet) -> Self { - Self { blacklist } + Self { + blacklist, + test_modules_deep: 0, + } + } + + fn in_test_module(&self) -> bool { + self.test_modules_deep != 0 } } impl_lint_pass!(BlacklistedName => [BLACKLISTED_NAME]); impl<'tcx> LateLintPass<'tcx> for BlacklistedName { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { + self.test_modules_deep = self.test_modules_deep.saturating_add(1); + } + } + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { + // Check whether we are under the `test` attribute. + if self.in_test_module() { + return; + } + if let PatKind::Binding(.., ident, _) = pat.kind { if self.blacklist.contains(&ident.name.to_string()) { span_lint( @@ -48,4 +67,10 @@ impl<'tcx> LateLintPass<'tcx> for BlacklistedName { } } } + + fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { + self.test_modules_deep = self.test_modules_deep.saturating_sub(1); + } + } } diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs index 877ae002d3..4f7ffdcdfb 100644 --- a/src/tools/clippy/clippy_lints/src/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/bytecount.rs @@ -1,15 +1,15 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::match_type; -use clippy_utils::{contains_name, get_pat_name, paths, single_segment_path}; +use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::{path_to_local_id, paths, peel_ref_operators, remove_blocks, strip_pat_refs}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, UintTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; -use rustc_span::Symbol; declare_clippy_lint! { /// **What it does:** Checks for naive byte counts @@ -38,42 +38,43 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]); impl<'tcx> LateLintPass<'tcx> for ByteCount { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(count, _, count_args, _) = expr.kind; + if let ExprKind::MethodCall(count, _, [count_recv], _) = expr.kind; if count.ident.name == sym!(count); - if count_args.len() == 1; - if let ExprKind::MethodCall(filter, _, filter_args, _) = count_args[0].kind; + if let ExprKind::MethodCall(filter, _, [filter_recv, filter_arg], _) = count_recv.kind; if filter.ident.name == sym!(filter); - if filter_args.len() == 2; - if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind; + if let ExprKind::Closure(_, _, body_id, _, _) = filter_arg.kind; let body = cx.tcx.hir().body(body_id); - if body.params.len() == 1; - if let Some(argname) = get_pat_name(body.params[0].pat); + if let [param] = body.params; + if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind; if let ExprKind::Binary(ref op, l, r) = body.value.kind; if op.node == BinOpKind::Eq; if match_type(cx, - cx.typeck_results().expr_ty(&filter_args[0]).peel_refs(), + cx.typeck_results().expr_ty(filter_recv).peel_refs(), &paths::SLICE_ITER); + let operand_is_arg = |expr| { + let expr = peel_ref_operators(cx, remove_blocks(expr)); + path_to_local_id(expr, arg_id) + }; + let needle = if operand_is_arg(l) { + r + } else if operand_is_arg(r) { + l + } else { + return; + }; + if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind(); + if !LocalUsedVisitor::new(cx, arg_id).check_expr(needle); then { - let needle = match get_path_name(l) { - Some(name) if check_arg(name, argname, r) => r, - _ => match get_path_name(r) { - Some(name) if check_arg(name, argname, l) => l, - _ => { return; } - } - }; - if ty::Uint(UintTy::U8) != *cx.typeck_results().expr_ty(needle).peel_refs().kind() { - return; - } let haystack = if let ExprKind::MethodCall(path, _, args, _) = - filter_args[0].kind { + filter_recv.kind { let p = path.ident.name; if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 { &args[0] } else { - &filter_args[0] + &filter_recv } } else { - &filter_args[0] + &filter_recv }; let mut applicability = Applicability::MaybeIncorrect; span_lint_and_sugg( @@ -91,24 +92,3 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount { }; } } - -fn check_arg(name: Symbol, arg: Symbol, needle: &Expr<'_>) -> bool { - name == arg && !contains_name(name, needle) -} - -fn get_path_name(expr: &Expr<'_>) -> Option { - match expr.kind { - ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) | ExprKind::Unary(UnOp::Deref, e) => { - get_path_name(e) - }, - ExprKind::Block(b, _) => { - if b.stmts.is_empty() { - b.expr.as_ref().and_then(|p| get_path_name(p)) - } else { - None - } - }, - ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name), - _ => None, - } -} 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 8097a1c832..21c7b2448c 100644 --- a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs @@ -2,8 +2,7 @@ use std::path::PathBuf; -use clippy_utils::diagnostics::span_lint; -use clippy_utils::run_lints; +use clippy_utils::{diagnostics::span_lint, is_lint_allowed}; use rustc_hir::{hir_id::CRATE_HIR_ID, Crate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -85,7 +84,7 @@ fn is_empty_vec(value: &[String]) -> bool { impl LateLintPass<'_> for CargoCommonMetadata { fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { - if !run_lints(cx, &[CARGO_COMMON_METADATA], CRATE_HIR_ID) { + if is_lint_allowed(cx, CARGO_COMMON_METADATA, CRATE_HIR_ID) { return; } diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs index ab22578abd..a6c3a5b0e8 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::visitors::LocalUsedVisitor; -use clippy_utils::{is_lang_ctor, path_to_local, SpanlessEq}; +use clippy_utils::{is_lang_ctor, path_to_local, peel_ref_operators, SpanlessEq}; use if_chain::if_chain; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind, UnOp}; +use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::TypeckResults; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{MultiSpan, Span}; @@ -73,7 +72,7 @@ fn check_arm<'tcx>(arm: &Arm<'tcx>, wild_outer_arm: &Arm<'tcx>, cx: &LateContext if arms_inner.iter().all(|arm| arm.guard.is_none()); // match expression must be a local binding // match { .. } - if let Some(binding_id) = path_to_local(strip_ref_operators(expr_in, cx.typeck_results())); + if let Some(binding_id) = path_to_local(peel_ref_operators(cx, expr_in)); // one of the branches must be "wild-like" if let Some(wild_inner_arm_idx) = arms_inner.iter().rposition(|arm_inner| arm_is_wild_like(cx, arm_inner)); let (wild_inner_arm, non_wild_inner_arm) = @@ -163,16 +162,3 @@ fn pat_contains_or(pat: &Pat<'_>) -> bool { }); result } - -/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is -/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed. -fn strip_ref_operators<'hir>(mut expr: &'hir Expr<'hir>, typeck_results: &TypeckResults<'_>) -> &'hir Expr<'hir> { - loop { - match expr.kind { - ExprKind::AddrOf(_, _, e) => expr = e, - ExprKind::Unary(UnOp::Deref, e) if typeck_results.expr_ty(e).is_ref() => expr = e, - _ => break, - } - } - expr -} diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index 376a14b818..9cbcde5976 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then}; use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt}; use clippy_utils::{ both, count_eq, eq_expr_value, get_enclosing_block, get_parent_expr, if_sequence, in_macro, is_else_clause, - run_lints, search_same, ContainsName, SpanlessEq, SpanlessHash, + is_lint_allowed, search_same, ContainsName, SpanlessEq, SpanlessHash, }; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; @@ -120,7 +120,10 @@ declare_clippy_lint! { /// /// **Why is this bad?** Duplicate code is less maintainable. /// - /// **Known problems:** Hopefully none. + /// **Known problems:** + /// * The lint doesn't check if the moved expressions modify values that are beeing used in + /// the if condition. The suggestion can in that case modify the behavior of the program. + /// See [rust-clippy#7452](https://github.com/rust-lang/rust-clippy/issues/7452) /// /// **Example:** /// ```ignore @@ -337,8 +340,8 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> Option< if block_expr_eq; if l_stmts.len() == r_stmts.len(); if l_stmts.len() == current_start_eq; - if run_lints(cx, &[IF_SAME_THEN_ELSE], win[0].hir_id); - if run_lints(cx, &[IF_SAME_THEN_ELSE], win[1].hir_id); + if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win[0].hir_id); + if !is_lint_allowed(cx, IF_SAME_THEN_ELSE, win[1].hir_id); then { span_lint_and_note( cx, @@ -358,8 +361,7 @@ fn scan_block_for_eq(cx: &LateContext<'tcx>, blocks: &[&Block<'tcx>]) -> Option< expr_eq &= block_expr_eq; } - let has_expr = blocks[0].expr.is_some(); - if has_expr && !expr_eq { + if !expr_eq { end_eq = 0; } diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 7a53d390bb..947479db8f 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::{Ident, Symbol}; @@ -122,7 +121,7 @@ impl LateLintPass<'_> for Default { if let StmtKind::Local(local) = stmt.kind; if let Some(expr) = local.init; if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); - if !in_external_macro(cx.tcx.sess, expr.span); + if !in_macro(expr.span); // only take bindings to identifiers if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind; // only when assigning `... = Default::default()` 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 759f7d4062..e719a1b0ab 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet; +use clippy_utils::numeric_literal; +use clippy_utils::source::snippet_opt; use if_chain::if_chain; use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; @@ -7,9 +8,10 @@ use rustc_hir::{ intravisit::{walk_expr, walk_stmt, NestedVisitorMap, Visitor}, Body, Expr, ExprKind, HirId, Lit, Stmt, StmtKind, }; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::{ hir::map::Map, + lint::in_external_macro, ty::{self, FloatTy, IntTy, PolyFnSig, Ty}, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -73,19 +75,29 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> { /// Check whether a passed literal has potential to cause fallback or not. fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>) { if_chain! { + if !in_external_macro(self.cx.sess(), lit.span); if let Some(ty_bound) = self.ty_bounds.last(); if matches!(lit.node, LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed)); - if !ty_bound.is_integral(); + if !ty_bound.is_numeric(); then { - let suffix = match lit_ty.kind() { - ty::Int(IntTy::I32) => "i32", - ty::Float(FloatTy::F64) => "f64", + let (suffix, is_float) = match lit_ty.kind() { + ty::Int(IntTy::I32) => ("i32", false), + ty::Float(FloatTy::F64) => ("f64", true), // Default numeric fallback never results in other types. _ => return, }; - let sugg = format!("{}_{}", snippet(self.cx, lit.span, ""), suffix); + let src = if let Some(src) = snippet_opt(self.cx, lit.span) { + src + } else { + match lit.node { + LitKind::Int(src, _) => format!("{}", src), + LitKind::Float(src, _) => format!("{}", src), + _ => return, + } + }; + let sugg = numeric_literal::format(&src, Some(suffix), is_float); span_lint_and_sugg( self.cx, DEFAULT_NUMERIC_FALLBACK, @@ -217,10 +229,10 @@ enum TyBound<'tcx> { } impl<'tcx> TyBound<'tcx> { - fn is_integral(self) -> bool { + fn is_numeric(self) -> bool { match self { TyBound::Any => true, - TyBound::Ty(t) => t.is_integral(), + TyBound::Ty(t) => t.is_numeric(), TyBound::Nothing => false, } } diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 04f3d77464..2933fbc934 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -149,7 +149,7 @@ declare_deprecated_lint! { /// enables the `enum_variant_names` lint for public items. /// ``` pub PUB_ENUM_VARIANT_NAMES, - "set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items" + "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items" } declare_deprecated_lint! { @@ -158,5 +158,5 @@ declare_deprecated_lint! { /// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which /// enables the `wrong_self_conversion` lint for public items. pub WRONG_PUB_SELF_CONVENTION, - "set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items" + "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items" } diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 1415f8e235..682003f9c2 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::peel_mid_ty_refs; -use clippy_utils::{get_parent_node, in_macro, is_allowed}; +use clippy_utils::{get_parent_node, in_macro, is_lint_allowed}; use rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp}; @@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { match kind { RefOp::Method(target_mut) - if !is_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id) + if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id) && is_linted_explicit_deref_position(parent, expr.hir_id, expr.span) => { self.state = Some(( diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 840c1eba79..7aafaf7138 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_then}; use clippy_utils::paths; use clippy_utils::ty::{implements_trait, is_copy}; -use clippy_utils::{get_trait_def_id, is_allowed, is_automatically_derived, match_def_path}; +use clippy_utils::{get_trait_def_id, is_automatically_derived, is_lint_allowed, match_def_path}; use if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor}; @@ -362,7 +362,7 @@ fn check_unsafe_derive_deserialize<'tcx>( if let ty::Adt(def, _) = ty.kind(); if let Some(local_def_id) = def.did.as_local(); let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id); - if !is_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id); + if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id); if cx.tcx.inherent_impls(def.did) .iter() .map(|imp_did| item_from_def_id(cx, *imp_did)) @@ -410,13 +410,8 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } if let ExprKind::Block(block, _) = expr.kind { - match block.rules { - BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) - | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided) - | BlockCheckMode::PopUnsafeBlock(UnsafeSource::UserProvided) => { - self.has_unsafe = true; - }, - _ => {}, + if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules { + self.has_unsafe = true; } } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_method.rs b/src/tools/clippy/clippy_lints/src/disallowed_method.rs index ded0a0fff5..aa1a609afe 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_method.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_method.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::fn_def_id; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::Expr; +use rustc_hir::{def::Res, def_id::DefId, Crate, Expr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Symbol; @@ -13,21 +13,14 @@ declare_clippy_lint! { /// **Why is this bad?** Some methods are undesirable in certain contexts, /// and it's beneficial to lint for them as needed. /// - /// **Known problems:** Currently, you must write each function as a - /// fully-qualified path. This lint doesn't support aliases or reexported - /// names; be aware that many types in `std` are actually reexports. - /// - /// For example, if you want to disallow `Duration::as_secs`, your clippy.toml - /// configuration would look like - /// `disallowed-methods = ["core::time::Duration::as_secs"]` and not - /// `disallowed-methods = ["std::time::Duration::as_secs"]` as you might expect. + /// **Known problems:** None. /// /// **Example:** /// /// An example clippy.toml configuration: /// ```toml /// # clippy.toml - /// disallowed-methods = ["alloc::vec::Vec::leak", "std::time::Instant::now"] + /// disallowed-methods = ["std::vec::Vec::leak", "std::time::Instant::now"] /// ``` /// /// ```rust,ignore @@ -52,6 +45,7 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct DisallowedMethod { disallowed: FxHashSet>, + def_ids: FxHashSet<(DefId, Vec)>, } impl DisallowedMethod { @@ -61,6 +55,7 @@ impl DisallowedMethod { .iter() .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::>()) .collect(), + def_ids: FxHashSet::default(), } } } @@ -68,10 +63,20 @@ impl DisallowedMethod { impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]); impl<'tcx> LateLintPass<'tcx> for DisallowedMethod { + fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + for path in &self.disallowed { + let segs = path.iter().map(ToString::to_string).collect::>(); + if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::>()) + { + self.def_ids.insert((id, path.clone())); + } + } + } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let Some(def_id) = fn_def_id(cx, expr) { - let func_path = cx.get_def_path(def_id); - if self.disallowed.contains(&func_path) { + if self.def_ids.iter().any(|(id, _)| def_id == *id) { + let func_path = cx.get_def_path(def_id); let func_path_string = func_path .into_iter() .map(Symbol::to_ident_string) diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs new file mode 100644 index 0000000000..12c525634c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -0,0 +1,112 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_ast::ast; +use rustc_data_structures::fx::FxHashSet; +use rustc_lint::{EarlyContext, EarlyLintPass, Level}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use unicode_script::{Script, UnicodeScript}; + +declare_clippy_lint! { + /// **What it does:** Checks for usage of unicode scripts other than those explicitly allowed + /// by the lint config. + /// + /// This lint doesn't take into account non-text scripts such as `Unknown` and `Linear_A`. + /// It also ignores the `Common` script type. + /// While configuring, be sure to use official script name [aliases] from + /// [the list of supported scripts][supported_scripts]. + /// + /// See also: [`non_ascii_idents`]. + /// + /// [aliases]: http://www.unicode.org/reports/tr24/tr24-31.html#Script_Value_Aliases + /// [supported_scripts]: https://www.unicode.org/iso15924/iso15924-codes.html + /// + /// **Why is this bad?** It may be not desired to have many different scripts for + /// identifiers in the codebase. + /// + /// Note that if you only want to allow plain English, you might want to use + /// built-in [`non_ascii_idents`] lint instead. + /// + /// [`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// // Assuming that `clippy.toml` contains the following line: + /// // allowed-locales = ["Latin", "Cyrillic"] + /// let counter = 10; // OK, latin is allowed. + /// let счётчик = 10; // OK, cyrillic is allowed. + /// let zähler = 10; // OK, it's still latin. + /// let カウンタ = 10; // Will spawn the lint. + /// ``` + pub DISALLOWED_SCRIPT_IDENTS, + restriction, + "usage of non-allowed Unicode scripts" +} + +#[derive(Clone, Debug)] +pub struct DisallowedScriptIdents { + whitelist: FxHashSet