]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #94515 - estebank:tweak-move-error, r=davidtwco
authorbors <bors@rust-lang.org>
Wed, 9 Mar 2022 08:58:47 +0000 (08:58 +0000)
committerbors <bors@rust-lang.org>
Wed, 9 Mar 2022 08:58:47 +0000 (08:58 +0000)
Tweak move error

Point at method definition that causes type to be consumed.

Fix #94056.

751 files changed:
Cargo.lock
RELEASES.md
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_passes/Cargo.toml
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_pretty/src/pprust/state/item.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_borrowck/Cargo.toml
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_codegen_cranelift/src/abi/comments.rs
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
compiler/rustc_codegen_gcc/src/builder.rs
compiler/rustc_codegen_gcc/src/common.rs
compiler/rustc_codegen_gcc/src/consts.rs
compiler/rustc_codegen_gcc/src/context.rs
compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_codegen_llvm/src/back/lto.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/common.rs
compiler/rustc_codegen_llvm/src/consts.rs
compiler/rustc_codegen_llvm/src/context.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/llvm/mod.rs
compiler/rustc_codegen_llvm/src/llvm_util.rs
compiler/rustc_codegen_ssa/Cargo.toml
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_codegen_ssa/src/traits/consts.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/machine.rs
compiler/rustc_const_eval/src/const_eval/mod.rs
compiler/rustc_const_eval/src/interpret/cast.rs
compiler/rustc_const_eval/src/interpret/intern.rs
compiler/rustc_const_eval/src/interpret/intrinsics.rs
compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
compiler/rustc_const_eval/src/interpret/machine.rs
compiler/rustc_const_eval/src/interpret/memory.rs
compiler/rustc_const_eval/src/interpret/operand.rs
compiler/rustc_const_eval/src/interpret/operator.rs
compiler/rustc_const_eval/src/interpret/terminator.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/check_consts/ops.rs
compiler/rustc_data_structures/Cargo.toml
compiler/rustc_data_structures/src/intern.rs
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_data_structures/src/small_c_str.rs
compiler/rustc_data_structures/src/small_str.rs [new file with mode: 0644]
compiler/rustc_data_structures/src/small_str/tests.rs [new file with mode: 0644]
compiler/rustc_data_structures/src/sorted_map/index_map.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_driver/src/pretty.rs
compiler/rustc_error_codes/src/error_codes/E0772.md
compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/diagnostic_builder.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/config.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/mbe/macro_parser.rs
compiler/rustc_expand/src/mbe/transcribe.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_feature/src/accepted.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_incremental/src/persist/load.rs
compiler/rustc_index/src/bit_set.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
compiler/rustc_infer/src/infer/glb.rs
compiler/rustc_infer/src/infer/lattice.rs
compiler/rustc_infer/src/infer/lub.rs
compiler/rustc_interface/src/interface.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/early.rs
compiler/rustc_lint/src/expect.rs [new file with mode: 0644]
compiler/rustc_lint/src/late.rs
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint_defs/Cargo.toml
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_lint_defs/src/lib.rs
compiler/rustc_llvm/Cargo.toml
compiler/rustc_llvm/build.rs
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_macros/src/newtype.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/arena.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/middle/stability.rs
compiler/rustc_middle/src/mir/interpret/allocation.rs
compiler/rustc_middle/src/mir/interpret/mod.rs
compiler/rustc_middle/src/mir/interpret/queries.rs
compiler/rustc_middle/src/mir/interpret/value.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/pretty.rs
compiler/rustc_middle/src/thir.rs
compiler/rustc_middle/src/thir/visit.rs
compiler/rustc_middle/src/ty/codec.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/fast_reject.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/trait_def.rs
compiler/rustc_mir_build/src/build/expr/as_constant.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/check_match.rs
compiler/rustc_mir_transform/Cargo.toml
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/nonterminal.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/entry.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_resolve/src/imports.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_session/Cargo.toml
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_target/src/abi/mod.rs
compiler/rustc_target/src/asm/arm.rs
compiler/rustc_target/src/lib.rs
compiler/rustc_target/src/spec/aarch64_linux_android.rs
compiler/rustc_target/src/spec/arm_linux_androideabi.rs
compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
compiler/rustc_target/src/spec/i686_linux_android.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/x86_64_linux_android.rs
compiler/rustc_trait_selection/src/traits/coherence.rs
compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
library/alloc/src/collections/btree/map/entry.rs
library/alloc/src/collections/btree/node.rs
library/alloc/src/lib.rs
library/core/src/cmp.rs
library/core/src/hint.rs
library/core/src/iter/adapters/map.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/pin.rs
library/core/src/result.rs
library/core/src/slice/mod.rs
library/core/src/sync/atomic.rs
library/core/tests/simd.rs
library/core/tests/slice.rs
library/proc_macro/src/lib.rs
library/std/src/io/mod.rs
library/std/src/io/stdio.rs
library/std/src/io/stdio/tests.rs
library/std/src/lib.rs
library/std/src/net/mod.rs
library/std/src/net/tcp/tests.rs
library/std/src/os/windows/fs.rs
library/std/src/os/windows/io/handle.rs
library/std/src/path/tests.rs
library/std/src/sync/once.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/path.rs
library/std/src/sys/unix/rwlock.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/windows/c.rs
library/std/src/sys/windows/fs.rs
library/std/src/sys/windows/handle.rs
library/std/src/sys/windows/mod.rs
library/std/src/sys/windows/thread.rs
library/std/src/thread/local.rs
library/std/src/thread/mod.rs
library/std/src/thread/scoped.rs
library/std/src/thread/tests.rs
library/unwind/src/libunwind.rs
src/bootstrap/Cargo.toml
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/builder/tests.rs
src/bootstrap/cc_detect.rs
src/bootstrap/channel.rs
src/bootstrap/clean.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/format.rs
src/bootstrap/install.rs
src/bootstrap/lib.rs
src/bootstrap/metadata.rs
src/bootstrap/native.rs
src/bootstrap/run.rs
src/bootstrap/sanity.rs
src/bootstrap/setup.rs
src/bootstrap/tarball.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/bootstrap/toolstate.rs
src/bootstrap/util.rs
src/build_helper/Cargo.toml [deleted file]
src/build_helper/lib.rs [deleted file]
src/doc/favicon.inc
src/doc/redirect.inc
src/doc/rustc/src/platform-support.md
src/doc/rustdoc/src/the-doc-attribute.md
src/doc/unstable-book/src/language-features/c-variadic.md
src/librustdoc/Cargo.toml
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/simplify.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/fold.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/js/source-script.js
src/librustdoc/html/templates/page.html
src/librustdoc/json/conversions.rs
src/librustdoc/lib.rs
src/librustdoc/passes/check_doc_test_visibility.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/visit.rs
src/rustdoc-json-types/lib.rs
src/test/codegen/arg-return-value-in-reg.rs [deleted file]
src/test/codegen/array-equality.rs
src/test/codegen/autovectorize-f32x4.rs [new file with mode: 0644]
src/test/codegen/loads.rs
src/test/codegen/target-feature-overrides.rs
src/test/codegen/union-abi.rs
src/test/rustdoc-gui/source-anchor-scroll.goml [new file with mode: 0644]
src/test/rustdoc-gui/source-code-page.goml
src/test/rustdoc-gui/src/link_to_definition/lib.rs
src/test/rustdoc-json/generic-associated-types/gats.rs [new file with mode: 0644]
src/test/rustdoc/const-generics/generic_const_exprs.rs
src/test/rustdoc/generic-associated-types/gats.rs [new file with mode: 0644]
src/test/rustdoc/generic-associated-types/issue-94683.rs [new file with mode: 0644]
src/test/rustdoc/intra-doc/associated-items.rs
src/test/rustdoc/macro-higher-kinded-function.rs [new file with mode: 0644]
src/test/rustdoc/rfc-2632-const-trait-impl.rs [new file with mode: 0644]
src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.rs
src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.rs
src/test/ui/alloc-error/alloc-error-handler-bad-signature-3.rs
src/test/ui/asm/naked-functions.rs
src/test/ui/asm/naked-functions.stderr
src/test/ui/associated-consts/associated-const-in-trait.rs
src/test/ui/associated-consts/associated-const-in-trait.stderr
src/test/ui/associated-types/issue-59324.rs
src/test/ui/associated-types/issue-59324.stderr
src/test/ui/async-await/async-fn-nonsend.rs
src/test/ui/async-await/drop-and-assign.rs [new file with mode: 0644]
src/test/ui/async-await/edition-deny-async-fns-2015.stderr
src/test/ui/async-await/suggest-switching-edition-on-await-cargo.rs [new file with mode: 0644]
src/test/ui/async-await/suggest-switching-edition-on-await-cargo.stderr [new file with mode: 0644]
src/test/ui/async-await/suggest-switching-edition-on-await.rs
src/test/ui/async-await/suggest-switching-edition-on-await.stderr
src/test/ui/async-await/try-on-option-in-async.rs
src/test/ui/async-await/unresolved_type_param.rs
src/test/ui/async-await/unresolved_type_param.stderr
src/test/ui/attributes/const-stability-on-macro.rs
src/test/ui/attributes/const-stability-on-macro.stderr
src/test/ui/attributes/extented-attribute-macro-error.rs
src/test/ui/attributes/extented-attribute-macro-error.stderr
src/test/ui/attributes/issue-90873.rs
src/test/ui/attributes/issue-90873.stderr
src/test/ui/borrowck/copy-suggestion-region-vid.rs [new file with mode: 0644]
src/test/ui/borrowck/copy-suggestion-region-vid.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-88434-minimal-example.rs
src/test/ui/borrowck/issue-88434-minimal-example.stderr
src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
src/test/ui/check-cfg/empty-values.rs
src/test/ui/check-cfg/empty-values.stderr
src/test/ui/check-cfg/no-values.rs
src/test/ui/check-cfg/no-values.stderr
src/test/ui/check-cfg/stmt-no-ice.rs [new file with mode: 0644]
src/test/ui/check-cfg/stmt-no-ice.stderr [new file with mode: 0644]
src/test/ui/check-cfg/well-known-values.rs [new file with mode: 0644]
src/test/ui/check-cfg/well-known-values.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr
src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr
src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
src/test/ui/const-generics/generic_const_exprs/issue-85848.rs
src/test/ui/const-generics/issues/issue-79674.rs
src/test/ui/const-generics/issues/issue-82956.rs
src/test/ui/consts/auxiliary/const_fn_lib.rs
src/test/ui/consts/const-array-oob-arith.rs
src/test/ui/consts/const-array-oob-arith.stderr
src/test/ui/consts/const-array-oob.rs
src/test/ui/consts/const-array-oob.stderr
src/test/ui/consts/const-block-const-bound.rs
src/test/ui/consts/const-eval/const_fn_ptr.stderr
src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
src/test/ui/consts/const-eval/issue-49296.rs
src/test/ui/consts/const-eval/issue-49296.stderr
src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs
src/test/ui/consts/const-eval/transmute-const-promotion.rs
src/test/ui/consts/const-eval/transmute-const-promotion.stderr
src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs
src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr
src/test/ui/consts/const-fn.rs
src/test/ui/consts/const_fn_trait_bound.gated.stderr [deleted file]
src/test/ui/consts/const_fn_trait_bound.rs [deleted file]
src/test/ui/consts/const_fn_trait_bound.stock.stderr [deleted file]
src/test/ui/consts/issue-37550-1.rs
src/test/ui/consts/issue-37550-1.stderr [deleted file]
src/test/ui/consts/issue-37550.rs
src/test/ui/consts/issue-46553.rs
src/test/ui/consts/issue-56164.rs
src/test/ui/consts/issue-56164.stderr
src/test/ui/consts/issue-87046.rs
src/test/ui/consts/issue-87046.stderr
src/test/ui/consts/issue-88071.rs
src/test/ui/consts/issue-94675.rs [new file with mode: 0644]
src/test/ui/consts/issue-94675.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs [deleted file]
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr [deleted file]
src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs
src/test/ui/consts/min_const_fn/cast_errors.rs [deleted file]
src/test/ui/consts/min_const_fn/cast_errors.stderr [deleted file]
src/test/ui/consts/min_const_fn/cast_fn.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
src/test/ui/consts/min_const_fn/min_const_fn.rs
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs
src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr [deleted file]
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs [deleted file]
src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr [deleted file]
src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs [deleted file]
src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr [deleted file]
src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
src/test/ui/consts/transmute-size-mismatch-before-typeck.rs
src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr
src/test/ui/consts/unstable-const-fn-in-libcore.rs
src/test/ui/consts/unstable-const-fn-in-libcore.stderr
src/test/ui/continue-after-missing-main.nll.stderr
src/test/ui/continue-after-missing-main.rs
src/test/ui/continue-after-missing-main.stderr
src/test/ui/deprecation/deprecation-in-staged-api.stderr
src/test/ui/editions/async-block-2015.rs
src/test/ui/editions/async-block-2015.stderr
src/test/ui/elided-test.stderr
src/test/ui/empty/empty-attributes.rs
src/test/ui/empty/empty-attributes.stderr
src/test/ui/empty/empty-never-array.stderr
src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
src/test/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
src/test/ui/entry-point/imported_main_const_forbidden.rs
src/test/ui/entry-point/imported_main_const_forbidden.stderr
src/test/ui/error-codes/E0004-2.stderr
src/test/ui/error-codes/E0004.stderr
src/test/ui/error-codes/E0005.stderr
src/test/ui/error-codes/E0297.stderr
src/test/ui/explore-issue-38412.rs
src/test/ui/explore-issue-38412.stderr
src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
src/test/ui/feature-gates/feature-gate-staged_api.stderr
src/test/ui/feature-gates/gated-bad-feature.rs
src/test/ui/feature-gates/gated-bad-feature.stderr
src/test/ui/feature-gates/issue-43106-gating-of-rustc_deprecated.rs
src/test/ui/feature-gates/issue-43106-gating-of-rustc_deprecated.stderr
src/test/ui/feature-gates/issue-43106-gating-of-stable.rs
src/test/ui/feature-gates/issue-43106-gating-of-stable.stderr
src/test/ui/feature-gates/issue-43106-gating-of-unstable.rs
src/test/ui/feature-gates/issue-43106-gating-of-unstable.stderr
src/test/ui/generator/drop-control-flow.rs
src/test/ui/generator/dropck.rs
src/test/ui/generator/issue-57478.rs
src/test/ui/generator/partial-drop.rs
src/test/ui/generator/partial-drop.stderr
src/test/ui/generic-associated-types/bugs/issue-87735.rs
src/test/ui/generic-associated-types/bugs/issue-87748.rs
src/test/ui/generic-associated-types/collections-project-default.rs
src/test/ui/generic-associated-types/collections.rs
src/test/ui/generic-associated-types/construct_with_other_type.rs
src/test/ui/generic-associated-types/gat-in-trait-path.rs
src/test/ui/generic-associated-types/generic-associated-types-where.rs
src/test/ui/generic-associated-types/generic-associated-types-where.stderr
src/test/ui/generic-associated-types/impl_bounds.rs
src/test/ui/generic-associated-types/impl_bounds.stderr
src/test/ui/generic-associated-types/impl_bounds_ok.rs
src/test/ui/generic-associated-types/issue-47206-where-clause.rs
src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
src/test/ui/generic-associated-types/issue-76826.rs
src/test/ui/generic-associated-types/issue-79422.rs
src/test/ui/generic-associated-types/issue-84931.stderr
src/test/ui/generic-associated-types/issue-86787.rs
src/test/ui/generic-associated-types/issue-88287.rs
src/test/ui/generic-associated-types/issue-90014.stderr
src/test/ui/generic-associated-types/issue-90729.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-91139.migrate.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-91139.rs
src/test/ui/generic-associated-types/issue-92033.stderr
src/test/ui/generic-associated-types/issue-92280.rs
src/test/ui/generic-associated-types/issue-93341.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-93342.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/iterable.rs
src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs
src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr
src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs
src/test/ui/generic-associated-types/projection-bound-cycle.rs
src/test/ui/generic-associated-types/streaming_iterator.rs
src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr [deleted file]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.nll.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
src/test/ui/impl-trait/issues/issue-79099.stderr
src/test/ui/impl-trait/issues/universal-issue-48703.rs
src/test/ui/impl-trait/issues/universal-issue-48703.stderr
src/test/ui/inference/question-mark-type-infer.rs
src/test/ui/inference/question-mark-type-infer.stderr
src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs
src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr
src/test/ui/issues/issue-16538.mir.stderr
src/test/ui/issues/issue-16538.rs
src/test/ui/issues/issue-16538.thir.stderr
src/test/ui/issues/issue-27078.rs
src/test/ui/issues/issue-27078.stderr
src/test/ui/issues/issue-39211.rs
src/test/ui/issues/issue-39211.stderr
src/test/ui/issues/issue-46101.rs
src/test/ui/issues/issue-46101.stderr
src/test/ui/issues/issue-47511.rs
src/test/ui/issues/issue-47511.stderr
src/test/ui/issues/issue-6596-2.rs
src/test/ui/issues/issue-6596-2.stderr
src/test/ui/issues/issue-75777.nll.stderr
src/test/ui/issues/issue-75777.rs
src/test/ui/issues/issue-75777.stderr
src/test/ui/issues/issue-78957.rs
src/test/ui/issues/issue-78957.stderr
src/test/ui/issues/issue-87707.rs [new file with mode: 0644]
src/test/ui/issues/issue-87707.run.stderr [new file with mode: 0644]
src/test/ui/lint/issue-87308.rs [deleted file]
src/test/ui/lint/issue-87308.stdout [deleted file]
src/test/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs [new file with mode: 0644]
src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr [new file with mode: 0644]
src/test/ui/lto/lto-duplicate-symbols.stderr
src/test/ui/macros/macro-non-lifetime.rs
src/test/ui/macros/macro-non-lifetime.stderr
src/test/ui/macros/macro-path-prelude-fail-1.rs
src/test/ui/macros/macro-path-prelude-fail-1.stderr
src/test/ui/macros/macro-path-prelude-shadowing.rs
src/test/ui/macros/macro-stability.rs
src/test/ui/macros/macro-stability.stderr
src/test/ui/main-wrong-location.rs
src/test/ui/main-wrong-location.stderr
src/test/ui/match/match_non_exhaustive.stderr
src/test/ui/mismatched_types/overloaded-calls-bad.rs
src/test/ui/mismatched_types/overloaded-calls-bad.stderr
src/test/ui/missing/missing-alloc_error_handler.rs
src/test/ui/missing/missing-allocator.rs
src/test/ui/missing/missing-main.stderr
src/test/ui/nll/issue-55825-const-fn.rs
src/test/ui/nll/issue-55825-const-fn.stderr [deleted file]
src/test/ui/nll/lint-no-err.rs [new file with mode: 0644]
src/test/ui/nll/lint-no-err.stderr [new file with mode: 0644]
src/test/ui/not-panic/not-panic-safe.rs
src/test/ui/not-panic/not-panic-safe.stderr
src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr
src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs
src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr
src/test/ui/on-unimplemented/impl-substs.rs [new file with mode: 0644]
src/test/ui/on-unimplemented/impl-substs.stderr [new file with mode: 0644]
src/test/ui/once-cant-call-twice-on-heap.rs
src/test/ui/once-cant-call-twice-on-heap.stderr
src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
src/test/ui/or-patterns/nested-undelimited-precedence.rs
src/test/ui/or-patterns/nested-undelimited-precedence.stderr
src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.rs
src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr
src/test/ui/parser/attr-with-a-semicolon.rs [new file with mode: 0644]
src/test/ui/parser/attr-with-a-semicolon.stderr [new file with mode: 0644]
src/test/ui/parser/bounds-lifetime-where.rs
src/test/ui/parser/bounds-lifetime-where.stderr
src/test/ui/parser/issues/issue-49040.stderr
src/test/ui/parser/removed-syntax-ptr-lifetime.rs
src/test/ui/parser/removed-syntax-ptr-lifetime.stderr
src/test/ui/parser/trailing-question-in-macro-type.rs [new file with mode: 0644]
src/test/ui/parser/trailing-question-in-macro-type.stderr [new file with mode: 0644]
src/test/ui/parser/type-alias-where-fixable.fixed [new file with mode: 0644]
src/test/ui/parser/type-alias-where-fixable.rs [new file with mode: 0644]
src/test/ui/parser/type-alias-where-fixable.stderr [new file with mode: 0644]
src/test/ui/parser/type-alias-where.rs
src/test/ui/parser/type-alias-where.stderr
src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
src/test/ui/pattern/usefulness/empty-match.normal.stderr
src/test/ui/pattern/usefulness/floats.stderr
src/test/ui/pattern/usefulness/guards.stderr
src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr
src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
src/test/ui/pattern/usefulness/issue-15129.stderr
src/test/ui/pattern/usefulness/issue-2111.stderr
src/test/ui/pattern/usefulness/issue-30240.stderr
src/test/ui/pattern/usefulness/issue-3096-1.stderr
src/test/ui/pattern/usefulness/issue-3096-2.stderr
src/test/ui/pattern/usefulness/issue-31561.stderr
src/test/ui/pattern/usefulness/issue-35609.stderr
src/test/ui/pattern/usefulness/issue-3601.stderr
src/test/ui/pattern/usefulness/issue-39362.stderr
src/test/ui/pattern/usefulness/issue-40221.stderr
src/test/ui/pattern/usefulness/issue-4321.stderr
src/test/ui/pattern/usefulness/issue-50900.stderr
src/test/ui/pattern/usefulness/issue-56379.stderr
src/test/ui/pattern/usefulness/issue-72377.stderr
src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs
src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr
src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
src/test/ui/pattern/usefulness/match-non-exhaustive.stderr
src/test/ui/pattern/usefulness/match-privately-empty.stderr
src/test/ui/pattern/usefulness/match-slice-patterns.stderr
src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs
src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
src/test/ui/pattern/usefulness/stable-gated-patterns.stderr
src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr
src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr
src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr
src/test/ui/pub/pub-restricted-error.rs
src/test/ui/pub/pub-restricted-error.stderr
src/test/ui/pub/pub-restricted.rs
src/test/ui/pub/pub-restricted.stderr
src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
src/test/ui/repr/issue-83921-pretty.normal.stderr [deleted file]
src/test/ui/repr/issue-83921-pretty.pretty.stdout [deleted file]
src/test/ui/repr/issue-83921-pretty.rs [deleted file]
src/test/ui/repr/repr-transparent-other-reprs.rs
src/test/ui/repr/repr-transparent-other-reprs.stderr
src/test/ui/rfc-2005-default-binding-mode/slice.stderr
src/test/ui/rfc-2008-non-exhaustive/enum.stderr
src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr
src/test/ui/rfc-2093-infer-outlives/explicit-dyn.rs
src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr
src/test/ui/rfc-2093-infer-outlives/self-dyn.rs
src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr
src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs
src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr
src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr
src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs
src/test/ui/rfc-2632-const-trait-impl/const-closures.rs
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs
src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs
src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs
src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr
src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs
src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs
src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr
src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs
src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
src/test/ui/rfc-2632-const-trait-impl/stability.rs
src/test/ui/rfc-2632-const-trait-impl/stability.stderr
src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
src/test/ui/rust-2018/uniform-paths/issue-56596.rs
src/test/ui/rust-2018/uniform-paths/issue-56596.stderr
src/test/ui/rust-2018/unresolved-asterisk-imports.rs [new file with mode: 0644]
src/test/ui/rust-2018/unresolved-asterisk-imports.stderr [new file with mode: 0644]
src/test/ui/span/issue-23827.rs
src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs
src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr
src/test/ui/stability-attribute/stability-attribute-non-staged.rs
src/test/ui/stability-attribute/stability-attribute-non-staged.stderr
src/test/ui/stability-attribute/stability-attribute-sanity-4.rs
src/test/ui/stability-attribute/stability-attribute-sanity-4.stderr
src/test/ui/stability-attribute/stability-attribute-sanity.rs
src/test/ui/stability-attribute/stability-attribute-sanity.stderr
src/test/ui/suggestions/missing-lifetime-specifier.rs
src/test/ui/suggestions/missing-lifetime-specifier.stderr
src/test/ui/target-feature/invalid-attribute.rs
src/test/ui/target-feature/invalid-attribute.stderr
src/test/ui/test-attrs/test-on-not-fn.rs
src/test/ui/test-attrs/test-on-not-fn.stderr
src/test/ui/threads-sendsync/issue-43733.mir.stderr
src/test/ui/threads-sendsync/issue-43733.rs
src/test/ui/threads-sendsync/issue-43733.thir.stderr
src/test/ui/try-trait/try-on-option-diagnostics.rs
src/test/ui/try-trait/try-on-option.rs
src/test/ui/try-trait/try-on-option.stderr
src/test/ui/tuple/wrong_argument_ice-3.rs [new file with mode: 0644]
src/test/ui/tuple/wrong_argument_ice-3.stderr [new file with mode: 0644]
src/test/ui/tuple/wrong_argument_ice-4.rs [new file with mode: 0644]
src/test/ui/tuple/wrong_argument_ice-4.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
src/test/ui/type-alias-impl-trait/issue-53096.rs
src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
src/test/ui/type-alias-impl-trait/issue-63355.rs
src/test/ui/type-alias-impl-trait/issue-63355.stderr
src/test/ui/type-alias-impl-trait/issue-65384.rs
src/test/ui/type-alias-impl-trait/issue-65384.stderr
src/test/ui/type-alias-impl-trait/issue-89686.rs
src/test/ui/type-alias-impl-trait/issue-89686.stderr
src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
src/test/ui/type-alias-impl-trait/structural-match-no-leak.stderr
src/test/ui/type-alias-impl-trait/structural-match.rs
src/test/ui/type-alias-impl-trait/structural-match.stderr
src/test/ui/type/type-parameter-defaults-referencing-Self.rs
src/test/ui/type/type-parameter-defaults-referencing-Self.stderr
src/test/ui/unboxed-closures/issue-53448.rs
src/test/ui/unboxed-closures/issue-53448.stderr [deleted file]
src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs
src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs
src/test/ui/uninhabited/uninhabited-irrefutable.stderr
src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
src/test/ui/unresolved/unresolved-asterisk-imports.rs [new file with mode: 0644]
src/test/ui/unresolved/unresolved-asterisk-imports.stderr [new file with mode: 0644]
src/tools/build-manifest/Cargo.toml
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clippy/Cargo.toml
src/tools/clippy/clippy_dev/Cargo.toml
src/tools/clippy/clippy_lints/Cargo.toml
src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
src/tools/clippy/clippy_utils/src/ast_utils.rs
src/tools/clippy/clippy_utils/src/consts.rs
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
src/tools/clippy/tests/ui/crashes/ice-6250.stderr
src/tools/clippy/tests/ui/crashes/ice-6251.stderr
src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/header/tests.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/rust-analyzer
src/tools/rustfmt/Cargo.toml
src/tools/rustfmt/src/items.rs
triagebot.toml

index f0c6e371c38be197f77023de408fbc9422962a69..4d7b62e9c559fb65ed536d392a425c67becddbd9 100644 (file)
@@ -161,9 +161,9 @@ dependencies = [
 
 [[package]]
 name = "autocfg"
-version = "1.0.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "bitflags"
@@ -214,14 +214,12 @@ dependencies = [
 name = "bootstrap"
 version = "0.0.0"
 dependencies = [
- "build_helper",
  "cc",
  "cmake",
  "filetime",
  "getopts",
  "ignore",
  "libc",
- "num_cpus",
  "once_cell",
  "opener",
  "pretty_assertions",
@@ -249,7 +247,6 @@ dependencies = [
  "anyhow",
  "flate2",
  "hex 0.4.2",
- "num_cpus",
  "rayon",
  "serde",
  "serde_json",
@@ -258,10 +255,6 @@ dependencies = [
  "toml",
 ]
 
-[[package]]
-name = "build_helper"
-version = "0.1.0"
-
 [[package]]
 name = "bump-stage0"
 version = "0.1.0"
@@ -344,7 +337,7 @@ dependencies = [
  "humantime 2.0.1",
  "ignore",
  "im-rc",
- "itertools 0.10.1",
+ "itertools",
  "jobserver",
  "lazy_static",
  "lazycell",
@@ -352,7 +345,6 @@ dependencies = [
  "libgit2-sys",
  "log",
  "memchr",
- "num_cpus",
  "opener",
  "openssl",
  "os_info",
@@ -449,7 +441,7 @@ dependencies = [
  "flate2",
  "git2",
  "glob",
- "itertools 0.10.1",
+ "itertools",
  "lazy_static",
  "remove_dir_all",
  "serde_json",
@@ -567,7 +559,7 @@ dependencies = [
  "chalk-ir",
  "ena",
  "indexmap",
- "itertools 0.10.1",
+ "itertools",
  "petgraph",
  "rustc-hash",
  "tracing",
@@ -631,7 +623,7 @@ dependencies = [
  "filetime",
  "futures 0.3.19",
  "if_chain",
- "itertools 0.10.1",
+ "itertools",
  "num_cpus",
  "parking_lot",
  "quote",
@@ -654,7 +646,7 @@ dependencies = [
  "cargo_metadata",
  "clap 2.34.0",
  "indoc",
- "itertools 0.10.1",
+ "itertools",
  "opener",
  "regex",
  "shell-escape",
@@ -668,7 +660,7 @@ dependencies = [
  "cargo_metadata",
  "clippy_utils",
  "if_chain",
- "itertools 0.10.1",
+ "itertools",
  "pulldown-cmark",
  "quine-mc_cluskey",
  "regex-syntax",
@@ -1510,9 +1502,9 @@ dependencies = [
 
 [[package]]
 name = "git2"
-version = "0.13.23"
+version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700"
+checksum = "6e7d3b96ec1fcaa8431cf04a4f1ef5caafe58d5cf7bcc31f09c1626adddb0ffe"
 dependencies = [
  "bitflags",
  "libc",
@@ -1525,9 +1517,9 @@ dependencies = [
 
 [[package]]
 name = "git2-curl"
-version = "0.14.1"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "883539cb0ea94bab3f8371a98cd8e937bbe9ee7c044499184aa4c17deb643a50"
+checksum = "1ee51709364c341fbb6fe2a385a290fb9196753bdde2fc45447d27cd31b11b13"
 dependencies = [
  "curl",
  "git2",
@@ -1790,15 +1782,6 @@ dependencies = [
  "cfg-if 1.0.0",
 ]
 
-[[package]]
-name = "itertools"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
-dependencies = [
- "either",
-]
-
 [[package]]
 name = "itertools"
 version = "0.10.1"
@@ -1991,9 +1974,9 @@ dependencies = [
 
 [[package]]
 name = "libgit2-sys"
-version = "0.12.24+1.3.0"
+version = "0.13.1+1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c"
+checksum = "43e598aa7a4faedf1ea1b4608f582b06f0f40211eec551b7ef36019ae3f62def"
 dependencies = [
  "cc",
  "libc",
@@ -2289,9 +2272,9 @@ dependencies = [
 
 [[package]]
 name = "minifier"
-version = "0.0.42"
+version = "0.0.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55a1388517eda8a68875243b650c26997e055a33d82571b5a0349129faef7d99"
+checksum = "d81352bda6f4d04af1720afaa762054f66e16caffd93c1f86461a1c0ac4e695e"
 dependencies = [
  "macro-utils",
 ]
@@ -3145,7 +3128,7 @@ dependencies = [
  "futures 0.3.19",
  "heck",
  "home",
- "itertools 0.10.1",
+ "itertools",
  "jsonrpc-core",
  "lazy_static",
  "log",
@@ -3187,7 +3170,7 @@ dependencies = [
  "derive-new",
  "env_logger 0.9.0",
  "fst",
- "itertools 0.10.1",
+ "itertools",
  "json",
  "lazy_static",
  "log",
@@ -3418,7 +3401,7 @@ dependencies = [
 name = "rustc_ast_passes"
 version = "0.0.0"
 dependencies = [
- "itertools 0.10.1",
+ "itertools",
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_attr",
@@ -3461,7 +3444,7 @@ name = "rustc_borrowck"
 version = "0.0.0"
 dependencies = [
  "either",
- "itertools 0.10.1",
+ "itertools",
  "polonius-engine",
  "rustc_const_eval",
  "rustc_data_structures",
@@ -3543,7 +3526,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags",
  "cc",
- "itertools 0.10.1",
+ "itertools",
  "jobserver",
  "libc",
  "object 0.28.1",
@@ -3882,6 +3865,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_ast",
  "rustc_data_structures",
+ "rustc_hir",
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
@@ -3892,7 +3876,6 @@ dependencies = [
 name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
- "build_helper",
  "cc",
  "libc",
 ]
@@ -4026,7 +4009,7 @@ name = "rustc_mir_transform"
 version = "0.0.0"
 dependencies = [
  "coverage_test_macros",
- "itertools 0.10.1",
+ "itertools",
  "rustc_ast",
  "rustc_attr",
  "rustc_const_eval",
@@ -4241,7 +4224,6 @@ name = "rustc_session"
 version = "0.0.0"
 dependencies = [
  "getopts",
- "num_cpus",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
@@ -4427,7 +4409,7 @@ dependencies = [
  "askama",
  "atty",
  "expect-test",
- "itertools 0.10.1",
+ "itertools",
  "minifier",
  "pulldown-cmark",
  "rayon",
@@ -4509,7 +4491,7 @@ dependencies = [
  "env_logger 0.8.4",
  "getopts",
  "ignore",
- "itertools 0.9.0",
+ "itertools",
  "lazy_static",
  "log",
  "regex",
@@ -5189,7 +5171,7 @@ checksum = "744e9ed5b352340aa47ce033716991b5589e23781acb97cad37d4ea70560f55b"
 dependencies = [
  "combine",
  "indexmap",
- "itertools 0.10.1",
+ "itertools",
  "kstring",
  "serde",
 ]
index 971a63b240f3e06e4bd1cfe96e7288e25ae982f4..08040f481583643dfdc6edd03229d7f690af9d84 100644 (file)
@@ -1060,7 +1060,7 @@ Version 1.52.1 (2021-05-10)
 This release disables incremental compilation, unless the user has explicitly
 opted in via the newly added RUSTC_FORCE_INCREMENTAL=1 environment variable.
 
-This is due to the widespread, and frequently occuring, breakage encountered by
+This is due to the widespread, and frequently occurring, breakage encountered by
 Rust users due to newly enabled incremental verification in 1.52.0. Notably,
 Rust users **should** upgrade to 1.52.0 or 1.52.1: the bugs that are detected by
 newly added incremental verification are still present in past stable versions,
index 725499e5c78ca0243e58a9e36b344f6dc6393e9d..ed5a282ec0635d81ec7e144d2d942ae9625569b9 100644 (file)
@@ -2662,10 +2662,37 @@ pub struct Trait {
     pub items: Vec<P<AssocItem>>,
 }
 
+/// The location of a where clause on a `TyAlias` (`Span`) and whether there was
+/// a `where` keyword (`bool`). This is split out from `WhereClause`, since there
+/// are two locations for where clause on type aliases, but their predicates
+/// are concatenated together.
+///
+/// Take this example:
+/// ```ignore (only-for-syntax-highlight)
+/// trait Foo {
+///   type Assoc<'a, 'b> where Self: 'a, Self: 'b;
+/// }
+/// impl Foo for () {
+///   type Assoc<'a, 'b> where Self: 'a = () where Self: 'b;
+///   //                 ^^^^^^^^^^^^^^ first where clause
+///   //                                     ^^^^^^^^^^^^^^ second where clause
+/// }
+/// ```
+///
+/// If there is no where clause, then this is `false` with `DUMMY_SP`.
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
+pub struct TyAliasWhereClause(pub bool, pub Span);
+
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct TyAlias {
     pub defaultness: Defaultness,
     pub generics: Generics,
+    /// The span information for the two where clauses (before equals, after equals)
+    pub where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
+    /// The index in `generics.where_clause.predicates` that would split into
+    /// predicates from the where clause before the equals and the predicates
+    /// from the where clause after the equals
+    pub where_predicates_split: usize,
     pub bounds: GenericBounds,
     pub ty: Option<P<Ty>>,
 }
index a81a227629539a06f52f55a639378b99cff9945d..c60c77e6987a6991b116e245d2dcbd8c9f635b7b 100644 (file)
@@ -1018,9 +1018,13 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         }
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
         ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
-        ItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+        ItemKind::TyAlias(box TyAlias {
+            defaultness, generics, where_clauses, bounds, ty, ..
+        }) => {
             visit_defaultness(defaultness, vis);
             vis.visit_generics(generics);
+            vis.visit_span(&mut where_clauses.0.1);
+            vis.visit_span(&mut where_clauses.1.1);
             visit_bounds(bounds, vis);
             visit_opt(ty, |ty| vis.visit_ty(ty));
         }
@@ -1087,9 +1091,18 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        AssocItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+        AssocItemKind::TyAlias(box TyAlias {
+            defaultness,
+            generics,
+            where_clauses,
+            bounds,
+            ty,
+            ..
+        }) => {
             visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
+            visitor.visit_span(&mut where_clauses.0.1);
+            visitor.visit_span(&mut where_clauses.1.1);
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
@@ -1152,9 +1165,18 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+        ForeignItemKind::TyAlias(box TyAlias {
+            defaultness,
+            generics,
+            where_clauses,
+            bounds,
+            ty,
+            ..
+        }) => {
             visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
+            visitor.visit_span(&mut where_clauses.0.1);
+            visitor.visit_span(&mut where_clauses.1.1);
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
index 73e9297549cd4877de19f41d92d5cb5711a84bfb..ed16c25d921e4872b7f02f528847e07d72f9b604 100644 (file)
@@ -303,7 +303,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
-        ItemKind::TyAlias(box TyAlias { defaultness: _, ref generics, ref bounds, ref ty }) => {
+        ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
@@ -559,7 +559,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
             let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
-        ForeignItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
+        ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
@@ -665,7 +665,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
             let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
-        AssocItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
+        AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
index e8fca6f04ba5b4bfd88afb289186f368d60ffcf5..b452290dff460bf3fdf571cc5789f84a2d582870 100644 (file)
@@ -25,6 +25,26 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
     pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>,
 }
 
+/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
+/// to the where clause that is prefered, if it exists. Otherwise, it sets the span to the other where
+/// clause if it exists.
+fn add_ty_alias_where_clause(
+    generics: &mut ast::Generics,
+    mut where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
+    prefer_first: bool,
+) {
+    if !prefer_first {
+        where_clauses = (where_clauses.1, where_clauses.0);
+    }
+    if where_clauses.0.0 || !where_clauses.1.0 {
+        generics.where_clause.has_where_token = where_clauses.0.0;
+        generics.where_clause.span = where_clauses.0.1;
+    } else {
+        generics.where_clause.has_where_token = where_clauses.1.0;
+        generics.where_clause.span = where_clauses.1.1;
+    }
+}
+
 impl ItemLowerer<'_, '_, '_> {
     fn with_trait_impl_ref<T>(
         &mut self,
@@ -277,7 +297,12 @@ fn lower_item_kind(
             ItemKind::GlobalAsm(ref asm) => {
                 hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
             }
-            ItemKind::TyAlias(box TyAlias { ref generics, ty: Some(ref ty), .. }) => {
+            ItemKind::TyAlias(box TyAlias {
+                ref generics,
+                where_clauses,
+                ty: Some(ref ty),
+                ..
+            }) => {
                 // We lower
                 //
                 // type Foo = impl Trait
@@ -292,16 +317,22 @@ fn lower_item_kind(
                         capturable_lifetimes: &mut FxHashSet::default(),
                     },
                 );
+                let mut generics = generics.clone();
+                add_ty_alias_where_clause(&mut generics, where_clauses, true);
                 let generics = self.lower_generics(
-                    generics,
+                    &generics,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                 );
                 hir::ItemKind::TyAlias(ty, generics)
             }
-            ItemKind::TyAlias(box TyAlias { ref generics, ty: None, .. }) => {
+            ItemKind::TyAlias(box TyAlias {
+                ref generics, ref where_clauses, ty: None, ..
+            }) => {
                 let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
+                let mut generics = generics.clone();
+                add_ty_alias_where_clause(&mut generics, *where_clauses, true);
                 let generics = self.lower_generics(
-                    generics,
+                    &generics,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                 );
                 hir::ItemKind::TyAlias(ty, generics)
@@ -832,18 +863,26 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
-            AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
+            AssocItemKind::TyAlias(box TyAlias {
+                ref generics,
+                where_clauses,
+                ref bounds,
+                ref ty,
+                ..
+            }) => {
                 let ty = ty.as_ref().map(|x| {
                     self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
                 });
+                let mut generics = generics.clone();
+                add_ty_alias_where_clause(&mut generics, where_clauses, false);
                 let generics = self.lower_generics(
-                    generics,
+                    &generics,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                 );
                 let kind = hir::TraitItemKind::Type(
                     self.lower_param_bounds(
                         bounds,
-                        ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+                        ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     ),
                     ty,
                 );
@@ -917,9 +956,11 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
             }
-            AssocItemKind::TyAlias(box TyAlias { generics, ty, .. }) => {
+            AssocItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
+                let mut generics = generics.clone();
+                add_ty_alias_where_clause(&mut generics, *where_clauses, false);
                 let generics = self.lower_generics(
-                    generics,
+                    &generics,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                 );
                 let kind = match ty {
index 940887280b9c18437f28152aeaa1ad9930eece8c..7a272308fb051af3e51861a78d23e8ff22369900 100644 (file)
@@ -2064,17 +2064,13 @@ fn lower_poly_trait_ref(
                 )),
                 _ => None,
             });
-            if let ImplTraitContext::TypeAliasesOpaqueTy { 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::TypeAliasesOpaqueTy { ref mut capturable_lifetimes, .. } =
-                itctx
-            {
+            if let ImplTraitContext::TypeAliasesOpaqueTy { ref mut capturable_lifetimes } = itctx {
                 for param in lt_def_names {
                     capturable_lifetimes.remove(&param);
                 }
index 45b70420338ddd98a77d14b17dc5393d466be8fe..22742b2adbd4fc3448c10c69f4ad7aa0b45b1908 100644 (file)
@@ -4,7 +4,7 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-itertools = "0.10"
+itertools = "0.10.1"
 tracing = "0.1"
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
index 20caed1b230d56a707f90a744d05fc9ad6270e31..0cf73178d679d09dd3c0c3cac4a89ab1069ced04 100644 (file)
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::walk_list;
 use rustc_ast::*;
-use rustc_ast_pretty::pprust;
+use rustc_ast_pretty::pprust::{self, State};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
 use rustc_parse::validate_attr;
-use rustc_session::lint::builtin::{MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY};
+use rustc_session::lint::builtin::{
+    DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
+};
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
@@ -122,6 +124,42 @@ fn ban_let_expr(&self, expr: &'a Expr) {
         }
     }
 
+    fn check_gat_where(
+        &mut self,
+        id: NodeId,
+        before_predicates: &[WherePredicate],
+        where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
+    ) {
+        if !before_predicates.is_empty() {
+            let mut state = State::new();
+            if !where_clauses.1.0 {
+                state.space();
+                state.word_space("where");
+            } else {
+                state.word_space(",");
+            }
+            let mut first = true;
+            for p in before_predicates.iter() {
+                if !first {
+                    state.word_space(",");
+                }
+                first = false;
+                state.print_where_predicate(p);
+            }
+            let suggestion = state.s.eof();
+            self.lint_buffer.buffer_lint_with_diagnostic(
+                DEPRECATED_WHERE_CLAUSE_LOCATION,
+                id,
+                where_clauses.0.1,
+                "where clause not allowed here",
+                BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
+                    where_clauses.1.1.shrink_to_hi(),
+                    suggestion,
+                ),
+            );
+        }
+    }
+
     fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
         f(self);
@@ -454,7 +492,7 @@ fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
             .emit();
     }
 
-    fn check_foreign_ty_genericless(&self, generics: &Generics) {
+    fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) {
         let cannot_have = |span, descr, remove_descr| {
             self.err_handler()
                 .struct_span_err(
@@ -477,7 +515,7 @@ fn check_foreign_ty_genericless(&self, generics: &Generics) {
         }
 
         if !generics.where_clause.predicates.is_empty() {
-            cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
+            cannot_have(where_span, "`where` clauses", "`where` clause");
         }
     }
 
@@ -1223,13 +1261,29 @@ fn visit_item(&mut self, item: &'a Item) {
                 let msg = "free static item without body";
                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
             }
-            ItemKind::TyAlias(box TyAlias { defaultness, ref bounds, ref ty, .. }) => {
+            ItemKind::TyAlias(box TyAlias {
+                defaultness,
+                where_clauses,
+                ref bounds,
+                ref ty,
+                ..
+            }) => {
                 self.check_defaultness(item.span, defaultness);
                 if ty.is_none() {
                     let msg = "free type alias without body";
                     self.error_item_without_body(item.span, "type", msg, " = <type>;");
                 }
                 self.check_type_no_bounds(bounds, "this context");
+                if where_clauses.1.0 {
+                    let mut err = self.err_handler().struct_span_err(
+                        where_clauses.1.1,
+                        "where clauses are not allowed after the type for type aliases",
+                    );
+                    err.note(
+                        "see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information",
+                    );
+                    err.emit();
+                }
             }
             _ => {}
         }
@@ -1245,11 +1299,18 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
                 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
                 self.check_foreign_item_ascii_only(fi.ident);
             }
-            ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty, .. }) => {
+            ForeignItemKind::TyAlias(box TyAlias {
+                defaultness,
+                generics,
+                where_clauses,
+                bounds,
+                ty,
+                ..
+            }) => {
                 self.check_defaultness(fi.span, *defaultness);
                 self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
                 self.check_type_no_bounds(bounds, "`extern` blocks");
-                self.check_foreign_ty_genericless(generics);
+                self.check_foreign_ty_genericless(generics, where_clauses.0.1);
                 self.check_foreign_item_ascii_only(fi.ident);
             }
             ForeignItemKind::Static(_, _, body) => {
@@ -1503,9 +1564,23 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                 AssocItemKind::Fn(box Fn { body, .. }) => {
                     self.check_impl_item_provided(item.span, body, "function", " { <body> }");
                 }
-                AssocItemKind::TyAlias(box TyAlias { bounds, ty, .. }) => {
+                AssocItemKind::TyAlias(box TyAlias {
+                    generics,
+                    where_clauses,
+                    where_predicates_split,
+                    bounds,
+                    ty,
+                    ..
+                }) => {
                     self.check_impl_item_provided(item.span, ty, "type", " = <type>;");
                     self.check_type_no_bounds(bounds, "`impl`s");
+                    if ty.is_some() {
+                        self.check_gat_where(
+                            item.id,
+                            generics.where_clause.predicates.split_at(*where_predicates_split).0,
+                            *where_clauses,
+                        );
+                    }
                 }
                 _ => {}
             }
index 6c44fb0df236377baef7a736a6425b12f87f4eef..570ec45557dea7ad1c1e599427978e6e5471fb28 100644 (file)
@@ -420,6 +420,31 @@ macro_rules! gate_modifier { ($($name:literal => $feature:ident)*) => {
                 }
             }
         }
+
+        // Emit errors for non-staged-api crates.
+        if !self.features.staged_api {
+            if attr.has_name(sym::rustc_deprecated)
+                || attr.has_name(sym::unstable)
+                || attr.has_name(sym::stable)
+                || attr.has_name(sym::rustc_const_unstable)
+                || attr.has_name(sym::rustc_const_stable)
+            {
+                struct_span_err!(
+                    self.sess,
+                    attr.span,
+                    E0734,
+                    "stability attributes may not be used outside of the standard library",
+                )
+                .emit();
+            }
+        } else {
+            if attr.has_name(sym::deprecated) {
+                self.sess
+                    .struct_span_err(attr.span, "`#[deprecated]` cannot be used in staged API")
+                    .span_label(attr.span, "use `#[rustc_deprecated]` instead")
+                    .emit();
+            }
+        }
     }
 
     fn visit_item(&mut self, i: &'a ast::Item) {
index d7e9ef0e50dd864e92700acdaa9d6a1809f0fa77..2a35dd1006e7e659ac6d86131c47482f298b10c9 100644 (file)
@@ -36,12 +36,16 @@ fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
             ast::ForeignItemKind::TyAlias(box ast::TyAlias {
                 defaultness,
                 generics,
+                where_clauses,
+                where_predicates_split,
                 bounds,
                 ty,
             }) => {
                 self.print_associated_type(
                     ident,
                     generics,
+                    *where_clauses,
+                    *where_predicates_split,
                     bounds,
                     ty.as_deref(),
                     vis,
@@ -95,11 +99,15 @@ fn print_associated_type(
         &mut self,
         ident: Ident,
         generics: &ast::Generics,
+        where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
+        where_predicates_split: usize,
         bounds: &ast::GenericBounds,
         ty: Option<&ast::Ty>,
         vis: &ast::Visibility,
         defaultness: ast::Defaultness,
     ) {
+        let (before_predicates, after_predicates) =
+            generics.where_clause.predicates.split_at(where_predicates_split);
         self.head("");
         self.print_visibility(vis);
         self.print_defaultness(defaultness);
@@ -107,12 +115,13 @@ fn print_associated_type(
         self.print_ident(ident);
         self.print_generic_params(&generics.params);
         self.print_type_bounds(":", bounds);
-        self.print_where_clause(&generics.where_clause);
+        self.print_where_clause_parts(where_clauses.0.0, before_predicates);
         if let Some(ty) = ty {
             self.space();
             self.word_space("=");
             self.print_type(ty);
         }
+        self.print_where_clause_parts(where_clauses.1.0, after_predicates);
         self.word(";");
         self.end(); // end inner head-block
         self.end(); // end outer head-block
@@ -211,6 +220,8 @@ fn print_associated_type(
             ast::ItemKind::TyAlias(box ast::TyAlias {
                 defaultness,
                 ref generics,
+                where_clauses,
+                where_predicates_split,
                 ref bounds,
                 ref ty,
             }) => {
@@ -218,6 +229,8 @@ fn print_associated_type(
                 self.print_associated_type(
                     item.ident,
                     generics,
+                    where_clauses,
+                    where_predicates_split,
                     bounds,
                     ty,
                     &item.vis,
@@ -496,10 +509,19 @@ fn print_assoc_item(&mut self, item: &ast::AssocItem) {
             ast::AssocItemKind::Const(def, ty, body) => {
                 self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
             }
-            ast::AssocItemKind::TyAlias(box ast::TyAlias { defaultness, generics, bounds, ty }) => {
+            ast::AssocItemKind::TyAlias(box ast::TyAlias {
+                defaultness,
+                generics,
+                where_clauses,
+                where_predicates_split,
+                bounds,
+                ty,
+            }) => {
                 self.print_associated_type(
                     ident,
                     generics,
+                    *where_clauses,
+                    *where_predicates_split,
                     bounds,
                     ty.as_deref(),
                     vis,
@@ -566,14 +588,22 @@ fn print_fn_full(
     }
 
     fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
-        if where_clause.predicates.is_empty() && !where_clause.has_where_token {
+        self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates);
+    }
+
+    crate fn print_where_clause_parts(
+        &mut self,
+        has_where_token: bool,
+        predicates: &[ast::WherePredicate],
+    ) {
+        if predicates.is_empty() && !has_where_token {
             return;
         }
 
         self.space();
         self.word_space("where");
 
-        for (i, predicate) in where_clause.predicates.iter().enumerate() {
+        for (i, predicate) in predicates.iter().enumerate() {
             if i != 0 {
                 self.word_space(",");
             }
index 846abce9d6a6e23bd1429b90f290703c5e23dd6b..061fee7f569af40f85962dd0823394ea3058c703 100644 (file)
@@ -476,7 +476,7 @@ pub fn cfg_matches(
                             cfg.span,
                             lint_node_id,
                             "unexpected `cfg` condition name",
-                            BuiltinLintDiagnostics::UnexpectedCfg(ident.span, name, None),
+                            BuiltinLintDiagnostics::UnexpectedCfg((name, ident.span), None),
                         );
                     }
                 }
@@ -489,9 +489,8 @@ pub fn cfg_matches(
                                 lint_node_id,
                                 "unexpected `cfg` condition value",
                                 BuiltinLintDiagnostics::UnexpectedCfg(
-                                    cfg.name_value_literal_span().unwrap(),
-                                    name,
-                                    Some(value),
+                                    (name, ident.span),
+                                    Some((value, cfg.name_value_literal_span().unwrap())),
                                 ),
                             );
                         }
index eb2fdbd07967d029f83f5ea2bbfdfef2a9141cb7..0b531623ba6f5e3f08683e14949caedecf6b7d3f 100644 (file)
@@ -8,7 +8,7 @@ doctest = false
 
 [dependencies]
 either = "1.5.0"
-itertools = "0.10"
+itertools = "0.10.1"
 tracing = "0.1"
 polonius-engine = "0.13.0"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
index 3eef907d9ed3d65d10b2d62ac9310510e28d6c72..1cbca58ca2590f3ed28ae1d1088efb0984533f4c 100644 (file)
@@ -323,8 +323,16 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
                                 self.mir_hir_id(),
                                 rustc_infer::traits::ObligationCauseCode::MiscObligation,
                             );
-                            fulfill_cx.register_bound(&infcx, self.param_env, ty, copy_did, cause);
-                            let errors = fulfill_cx.select_where_possible(&infcx);
+                            fulfill_cx.register_bound(
+                                &infcx,
+                                self.param_env,
+                                // Erase any region vids from the type, which may not be resolved
+                                infcx.tcx.erase_regions(ty),
+                                copy_did,
+                                cause,
+                            );
+                            // Select all, including ambiguous predicates
+                            let errors = fulfill_cx.select_all_or_error(&infcx);
 
                             // Only emit suggestion if all required predicates are on generic
                             errors
index 985c45e2253880d02a9f8910f688e6526f6a1721..f87f4726d1c6967a05a047067ad3f450eb1f6c12 100644 (file)
@@ -560,6 +560,11 @@ fn create_derived_impl(
                 kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
                     defaultness: ast::Defaultness::Final,
                     generics: Generics::default(),
+                    where_clauses: (
+                        ast::TyAliasWhereClause::default(),
+                        ast::TyAliasWhereClause::default(),
+                    ),
+                    where_predicates_split: 0,
                     bounds: Vec::new(),
                     ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
                 })),
index e658631d09038ee22ec243927e53074810f4c970..0c2d20b8f2dc89eea86804cd2c56ed77d1d4ed11 100644 (file)
@@ -105,14 +105,18 @@ pub fn expand_test_or_bench(
 
     // Note: non-associated fn items are already handled by `expand_test_or_bench`
     if !matches!(item.kind, ast::ItemKind::Fn(_)) {
-        cx.sess
-            .parse_sess
-            .span_diagnostic
-            .struct_span_err(
-                attr_sp,
-                "the `#[test]` attribute may only be used on a non-associated function",
-            )
-            .note("the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions")
+        let diag = &cx.sess.parse_sess.span_diagnostic;
+        let msg = "the `#[test]` attribute may only be used on a non-associated function";
+        let mut err = match item.kind {
+            // These were a warning before #92959 and need to continue being that to avoid breaking
+            // stable user code (#94508).
+            ast::ItemKind::MacCall(_) => diag.struct_span_warn(attr_sp, msg),
+            // `.forget_guarantee()` needed to get these two arms to match types. Because of how
+            // locally close the `.emit()` call is I'm comfortable with it, but if it can be
+            // reworked in the future to not need it, it'd be nice.
+            _ => diag.struct_span_err(attr_sp, msg).forget_guarantee(),
+        };
+        err.span_label(attr_sp, "the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions")
             .span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
             .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", String::from("#[cfg(test)]"), Applicability::MaybeIncorrect)
             .emit();
index 5fbaed7283a6781400a2ca0628cc731ae49edb8e..37d2679c10d70af2f21316bf404ecbd29eecf4a8 100644 (file)
@@ -82,8 +82,14 @@ pub(super) fn add_local_place_comments<'tcx>(
         return;
     }
     let TyAndLayout { ty, layout } = place.layout();
-    let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } =
-        layout;
+    let rustc_target::abi::LayoutS {
+        size,
+        align,
+        abi: _,
+        variants: _,
+        fields: _,
+        largest_niche: _,
+    } = layout.0.0;
 
     let (kind, extra) = match *place.inner() {
         CPlaceInner::Var(place_local, var) => {
index 66adc1a2ce96db56d7f00affe884d53db3ddf1af..aff3603303a98ff8f90120303d3804bbac681487 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{
-    read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
+    read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
 };
 use rustc_middle::ty::ConstKind;
 use rustc_span::DUMMY_SP;
@@ -202,7 +202,7 @@ pub(crate) fn codegen_const_value<'tcx>(
                             &mut fx.constants_cx,
                             fx.module,
                             alloc_id,
-                            alloc.mutability,
+                            alloc.inner().mutability,
                         );
                         let local_data_id =
                             fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
@@ -257,11 +257,15 @@ pub(crate) fn codegen_const_value<'tcx>(
 
 pub(crate) fn pointer_for_allocation<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
-    alloc: &'tcx Allocation,
+    alloc: ConstAllocation<'tcx>,
 ) -> crate::pointer::Pointer {
     let alloc_id = fx.tcx.create_memory_alloc(alloc);
-    let data_id =
-        data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, alloc.mutability);
+    let data_id = data_id_for_alloc_id(
+        &mut fx.constants_cx,
+        &mut *fx.module,
+        alloc_id,
+        alloc.inner().mutability,
+    );
 
     let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
     if fx.clif_comments.enabled() {
@@ -361,7 +365,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                 let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
                     module
                         .declare_anonymous_data(
-                            alloc.mutability == rustc_hir::Mutability::Mut,
+                            alloc.inner().mutability == rustc_hir::Mutability::Mut,
                             false,
                         )
                         .unwrap()
@@ -386,6 +390,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
         }
 
         let mut data_ctx = DataContext::new();
+        let alloc = alloc.inner();
         data_ctx.set_align(alloc.align.bytes());
 
         if let Some(section_name) = section_name {
@@ -429,7 +434,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                     continue;
                 }
                 GlobalAlloc::Memory(target_alloc) => {
-                    data_id_for_alloc_id(cx, module, alloc_id, target_alloc.mutability)
+                    data_id_for_alloc_id(cx, module, alloc_id, target_alloc.inner().mutability)
                 }
                 GlobalAlloc::Static(def_id) => {
                     if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
index 4dfb13476c287f7bbe06692b3025f9547097db60..6489b96be4b2d037e212ba7b650c7adfab7bd02f 100644 (file)
@@ -1070,7 +1070,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
         };
 
         raw_eq, (v lhs_ref, v rhs_ref) {
-            let size = fx.layout_of(substs.type_at(0)).layout.size;
+            let size = fx.layout_of(substs.type_at(0)).layout.size();
             // FIXME add and use emit_small_memcmp
             let is_eq_value =
                 if size == Size::ZERO {
index 4153bc08e8ad4f3c9f40845f3098b0ebd8e9f622..49022ebd3e26fd19dfd4ec31b914b123ce1303fb 100644 (file)
@@ -159,7 +159,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 let idx_bytes = match idx_const {
                     ConstValue::ByRef { alloc, offset } => {
                         let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */);
-                        alloc.get_bytes(fx, alloc_range(offset, size)).unwrap()
+                        alloc.inner().get_bytes(fx, alloc_range(offset, size)).unwrap()
                     }
                     _ => unreachable!("{:?}", idx_const),
                 };
index 974e59b65ec91c2565d4b53b9ef4b8ccdd8cd483..be3f6a12706f84c16ddafbb580c74a6ac87e0e6a 100644 (file)
@@ -1064,7 +1064,7 @@ fn pointercast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'g
         let val_type = value.get_type();
         match (type_is_pointer(val_type), type_is_pointer(dest_ty)) {
             (false, true) => {
-                // NOTE: Projecting a field of a pointer type will attemp a cast from a signed char to
+                // NOTE: Projecting a field of a pointer type will attempt a cast from a signed char to
                 // a pointer, which is not supported by gccjit.
                 return self.cx.context.new_cast(None, self.inttoptr(value, val_type.make_pointer()), dest_ty);
             },
index 5851826147dfac9fd5cedacf1d9120f406be702b..d1ff15367c3c183025a8fb92fe9d50f07f083a87 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::ScalarInt;
 use rustc_middle::ty::layout::{TyAndLayout, LayoutOf};
-use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar};
+use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
 use rustc_span::Symbol;
 use rustc_target::abi::{self, HasDataLayout, Pointer, Size};
 
@@ -26,18 +26,6 @@ pub fn const_bytes(&self, bytes: &[u8]) -> RValue<'gcc> {
         bytes_in_context(self, bytes)
     }
 
-    fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> LValue<'gcc> {
-        // TODO(antoyo): handle null_terminated.
-        if let Some(&value) = self.const_cstr_cache.borrow().get(&symbol) {
-            return value;
-        }
-
-        let global = self.global_string(symbol.as_str());
-
-        self.const_cstr_cache.borrow_mut().insert(symbol, global);
-        global
-    }
-
     fn global_string(&self, string: &str) -> LValue<'gcc> {
         // TODO(antoyo): handle non-null-terminated strings.
         let string = self.context.new_string_literal(&*string);
@@ -171,8 +159,12 @@ fn const_real(&self, _t: Type<'gcc>, _val: f64) -> RValue<'gcc> {
     }
 
     fn const_str(&self, s: Symbol) -> (RValue<'gcc>, RValue<'gcc>) {
-        let len = s.as_str().len();
-        let cs = self.const_ptrcast(self.const_cstr(s, false).get_address(None),
+        let s_str = s.as_str();
+        let str_global = *self.const_str_cache.borrow_mut().entry(s).or_insert_with(|| {
+            self.global_string(s_str)
+        });
+        let len = s_str.len();
+        let cs = self.const_ptrcast(str_global.get_address(None),
             self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self, true)),
         );
         (cs, self.const_usize(len as u64))
@@ -230,6 +222,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) ->
                     match self.tcx.global_alloc(alloc_id) {
                         GlobalAlloc::Memory(alloc) => {
                             let init = const_alloc_to_gcc(self, alloc);
+                            let alloc = alloc.inner();
                             let value =
                                 match alloc.mutability {
                                     Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
@@ -262,21 +255,21 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) ->
         }
     }
 
-    fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value {
+    fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
         const_alloc_to_gcc(self, alloc)
     }
 
-    fn from_const_alloc(&self, layout: TyAndLayout<'tcx>, alloc: &Allocation, offset: Size) -> PlaceRef<'tcx, RValue<'gcc>> {
-        assert_eq!(alloc.align, layout.align.abi);
+    fn from_const_alloc(&self, layout: TyAndLayout<'tcx>, alloc: ConstAllocation<'tcx>, offset: Size) -> PlaceRef<'tcx, RValue<'gcc>> {
+        assert_eq!(alloc.inner().align, layout.align.abi);
         let ty = self.type_ptr_to(layout.gcc_type(self, true));
         let value =
             if layout.size == Size::ZERO {
-                let value = self.const_usize(alloc.align.bytes());
+                let value = self.const_usize(alloc.inner().align.bytes());
                 self.context.new_cast(None, value, ty)
             }
             else {
                 let init = const_alloc_to_gcc(self, alloc);
-                let base_addr = self.static_addr_of(init, alloc.align, None);
+                let base_addr = self.static_addr_of(init, alloc.inner().align, None);
 
                 let array = self.const_bitcast(base_addr, self.type_i8p());
                 let value = self.context.new_array_access(None, array, self.const_usize(offset.bytes())).get_address(None);
index ddc2b88191bd0e8e032d05e1220579ec09071fe7..d53b15159fa44d3d135a56e3fdcff90c576b7a53 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::mir::interpret::{self, Allocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
+use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
 use rustc_span::Span;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
@@ -284,7 +284,8 @@ pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
     }
 }
 
-pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: &Allocation) -> RValue<'gcc> {
+pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAllocation<'tcx>) -> RValue<'gcc> {
+    let alloc = alloc.inner();
     let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
     let dl = cx.data_layout();
     let pointer_size = dl.pointer_size.bytes() as usize;
@@ -338,7 +339,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: &Alloca
     cx.const_struct(&llvals, true)
 }
 
-pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId) -> Result<(RValue<'gcc>, &'tcx Allocation), ErrorHandled> {
+pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId) -> Result<(RValue<'gcc>, ConstAllocation<'tcx>), ErrorHandled> {
     let alloc = cx.tcx.eval_static_initializer(def_id)?;
     Ok((const_alloc_to_gcc(cx, alloc), alloc))
 }
index dfcd1b6231216cb49acc361bdb83e054a43e058d..6c1dce969f0f5eed9ec997d4f5af26629c0b33f7 100644 (file)
@@ -85,7 +85,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
     pub const_globals: RefCell<FxHashMap<RValue<'gcc>, RValue<'gcc>>>,
 
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<Symbol, LValue<'gcc>>>,
+    pub const_str_cache: RefCell<FxHashMap<Symbol, LValue<'gcc>>>,
 
     /// Cache of globals.
     pub globals: RefCell<FxHashMap<String, RValue<'gcc>>>,
@@ -195,7 +195,7 @@ pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>,
             function_instances: Default::default(),
             vtables: Default::default(),
             const_globals: Default::default(),
-            const_cstr_cache: Default::default(),
+            const_str_cache: Default::default(),
             globals: Default::default(),
             scalar_types: Default::default(),
             types: Default::default(),
index 572ac559d09dfb89fb5842cab86c7903d900dae7..ef213f5636907811ad4c0354e1e99153f5dfe287 100644 (file)
@@ -272,20 +272,20 @@ fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'t
                     use rustc_target::abi::Abi::*;
                     let tp_ty = substs.type_at(0);
                     let layout = self.layout_of(tp_ty).layout;
-                    let _use_integer_compare = match layout.abi {
+                    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
+                            layout.size() <= self.data_layout().pointer_size * 2
                         }
                     };
 
                     let a = args[0].immediate();
                     let b = args[1].immediate();
-                    if layout.size.bytes() == 0 {
+                    if layout.size().bytes() == 0 {
                         self.const_bool(true)
                     }
                     /*else if use_integer_compare {
@@ -301,7 +301,7 @@ fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'t
                         let void_ptr_type = self.context.new_type::<*const ()>();
                         let a_ptr = self.bitcast(a, void_ptr_type);
                         let b_ptr = self.bitcast(b, void_ptr_type);
-                        let n = self.context.new_cast(None, self.const_usize(layout.size.bytes()), self.sizet_type);
+                        let n = self.context.new_cast(None, self.const_usize(layout.size().bytes()), self.sizet_type);
                         let builtin = self.context.get_builtin_function("memcmp");
                         let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]);
                         self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
index f8f6956c47e4d298327f22f3c61e75ffac512b77..b14a4f28c756ca5b2a85cb411e1fe36f1192f027 100644 (file)
@@ -561,8 +561,7 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll V
         if self.conv == Conv::CCmseNonSecureCall {
             // This will probably get ignored on all targets but those supporting the TrustZone-M
             // extension (thumbv8m targets).
-            let cmse_nonsecure_call =
-                llvm::CreateAttrString(bx.cx.llcx, cstr::cstr!("cmse_nonsecure_call"));
+            let cmse_nonsecure_call = llvm::CreateAttrString(bx.cx.llcx, "cmse_nonsecure_call");
             attributes::apply_to_callsite(
                 callsite,
                 llvm::AttributePlace::Function,
index e382af8880b8d81bd8acbbcdec958309ab752447..101da0012cb4b0d8fe33d2401db69cf8ef03082a 100644 (file)
@@ -1,10 +1,7 @@
 //! Set and unset common attributes on LLVM values.
 
-use std::ffi::CString;
-
-use cstr::cstr;
 use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_data_structures::small_str::SmallStr;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::{self, TyCtxt};
@@ -103,11 +100,11 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr
         fp = FramePointer::Always;
     }
     let attr_value = match fp {
-        FramePointer::Always => cstr!("all"),
-        FramePointer::NonLeaf => cstr!("non-leaf"),
+        FramePointer::Always => "all",
+        FramePointer::NonLeaf => "non-leaf",
         FramePointer::MayOmit => return None,
     };
-    Some(llvm::CreateAttrStringValue(cx.llcx, cstr!("frame-pointer"), attr_value))
+    Some(llvm::CreateAttrStringValue(cx.llcx, "frame-pointer", attr_value))
 }
 
 /// Tell LLVM what instrument function to insert.
@@ -119,11 +116,11 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribu
 
         // The function name varies on platforms.
         // See test/CodeGen/mcount.c in clang.
-        let mcount_name = CString::new(cx.sess().target.mcount.as_str().as_bytes()).unwrap();
+        let mcount_name = cx.sess().target.mcount.as_str();
 
         Some(llvm::CreateAttrStringValue(
             cx.llcx,
-            cstr!("instrument-function-entry-inlined"),
+            "instrument-function-entry-inlined",
             &mcount_name,
         ))
     } else {
@@ -159,20 +156,20 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
         StackProbeType::None => return None,
         // Request LLVM to generate the probes inline. If the given LLVM version does not support
         // this, no probe is generated at all (even if the attribute is specified).
-        StackProbeType::Inline => cstr!("inline-asm"),
+        StackProbeType::Inline => "inline-asm",
         // Flag our internal `__rust_probestack` function as the stack probe symbol.
         // This is defined in the `compiler-builtins` crate for each architecture.
-        StackProbeType::Call => cstr!("__rust_probestack"),
+        StackProbeType::Call => "__rust_probestack",
         // Pick from the two above based on the LLVM version.
         StackProbeType::InlineOrCall { min_llvm_version_for_inline } => {
             if llvm_util::get_version() < min_llvm_version_for_inline {
-                cstr!("__rust_probestack")
+                "__rust_probestack"
             } else {
-                cstr!("inline-asm")
+                "inline-asm"
             }
         }
     };
-    Some(llvm::CreateAttrStringValue(cx.llcx, cstr!("probe-stack"), attr_value))
+    Some(llvm::CreateAttrStringValue(cx.llcx, "probe-stack", attr_value))
 }
 
 fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
@@ -187,15 +184,13 @@ fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
 }
 
 pub fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute {
-    let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess));
-    llvm::CreateAttrStringValue(cx.llcx, cstr!("target-cpu"), target_cpu.as_c_str())
+    let target_cpu = llvm_util::target_cpu(cx.tcx.sess);
+    llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu)
 }
 
 pub fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
-    llvm_util::tune_cpu(cx.tcx.sess).map(|tune| {
-        let tune_cpu = SmallCStr::new(tune);
-        llvm::CreateAttrStringValue(cx.llcx, cstr!("tune-cpu"), tune_cpu.as_c_str())
-    })
+    llvm_util::tune_cpu(cx.tcx.sess)
+        .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu))
 }
 
 /// Get the `NonLazyBind` LLVM attribute,
@@ -280,7 +275,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
     }
 
     if cx.sess().opts.debugging_opts.profile_sample_use.is_some() {
-        to_add.push(llvm::CreateAttrString(cx.llcx, cstr!("use-sample-profile")));
+        to_add.push(llvm::CreateAttrString(cx.llcx, "use-sample-profile"));
     }
 
     // FIXME: none of these three functions interact with source level attributes.
@@ -310,7 +305,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
         attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
     }
     if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
-        to_add.push(llvm::CreateAttrString(cx.llcx, cstr!("cmse_nonsecure_entry")));
+        to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));
     }
     if let Some(align) = codegen_fn_attrs.alignment {
         llvm::set_alignment(llfn, align as usize);
@@ -363,12 +358,12 @@ pub fn from_fn_attrs<'ll, 'tcx>(
         // If this function is an import from the environment but the wasm
         // import has a specific module/name, apply them here.
         if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) {
-            to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("wasm-import-module"), &module));
+            to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-module", &module));
 
             let name =
                 codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id()));
-            let name = CString::new(name.as_str()).unwrap();
-            to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("wasm-import-name"), &name));
+            let name = name.as_str();
+            to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-name", name));
         }
 
         // The `"wasm"` abi on wasm targets automatically enables the
@@ -383,18 +378,17 @@ pub fn from_fn_attrs<'ll, 'tcx>(
         }
     }
 
-    if !function_features.is_empty() {
-        let global_features = cx.tcx.global_backend_features(()).iter().map(|s| &s[..]);
-        let val = global_features
-            .chain(function_features.iter().map(|s| &s[..]))
-            .intersperse(",")
-            .collect::<SmallCStr>();
-        to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("target-features"), &val));
+    let global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str());
+    let function_features = function_features.iter().map(|s| s.as_str());
+    let target_features =
+        global_features.chain(function_features).intersperse(",").collect::<SmallStr<1024>>();
+    if !target_features.is_empty() {
+        to_add.push(llvm::CreateAttrStringValue(cx.llcx, "target-features", &target_features));
     }
 
     attributes::apply_to_llfn(llfn, Function, &to_add);
 }
 
-fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option<CString> {
-    tcx.wasm_import_module_map(id.krate).get(&id).map(|s| CString::new(&s[..]).unwrap())
+fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option<&String> {
+    tcx.wasm_import_module_map(id.krate).get(&id)
 }
index 6afa649b6de325a19b40e8df10619b1002f371fd..0f5b1c08ec2dc707920b85ec45c08aac2bde8193 100644 (file)
@@ -317,7 +317,7 @@ fn fat_lto(
             info!("linking {:?}", name);
             let data = bc_decoded.data();
             linker.add(data).map_err(|()| {
-                let msg = format!("failed to load bc of {:?}", name);
+                let msg = format!("failed to load bitcode of module {:?}", name);
                 write::llvm_err(diag_handler, &msg)
             })?;
             serialized_bitcode.push(bc_decoded);
index 6c1d4ce8f3c2b78d03ebb4db6b046e76cce329fb..c4eb593d2976a6f0c015b2f70f59784be9135a13 100644 (file)
@@ -477,6 +477,8 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
             bx: &mut Builder<'a, 'll, 'tcx>,
             load: &'ll Value,
             scalar: abi::Scalar,
+            layout: TyAndLayout<'tcx>,
+            offset: Size,
         ) {
             if !scalar.is_always_valid(bx) {
                 bx.noundef_metadata(load);
@@ -488,10 +490,18 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
                         bx.range_metadata(load, scalar.valid_range);
                     }
                 }
-                abi::Pointer if !scalar.valid_range.contains(0) => {
-                    bx.nonnull_metadata(load);
+                abi::Pointer => {
+                    if !scalar.valid_range.contains(0) {
+                        bx.nonnull_metadata(load);
+                    }
+
+                    if let Some(pointee) = layout.pointee_info_at(bx, offset) {
+                        if let Some(_) = pointee.safe {
+                            bx.align_metadata(load, pointee.align);
+                        }
+                    }
                 }
-                _ => {}
+                abi::F32 | abi::F64 => {}
             }
         }
 
@@ -509,7 +519,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
             let llval = const_llval.unwrap_or_else(|| {
                 let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
                 if let abi::Abi::Scalar(scalar) = place.layout.abi {
-                    scalar_load_metadata(self, load, scalar);
+                    scalar_load_metadata(self, load, scalar, place.layout, Size::ZERO);
                 }
                 load
             });
@@ -518,17 +528,17 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
             let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
             let pair_ty = place.layout.llvm_type(self);
 
-            let mut load = |i, scalar: abi::Scalar, align| {
+            let mut load = |i, scalar: abi::Scalar, layout, align, offset| {
                 let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
                 let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
                 let load = self.load(llty, llptr, align);
-                scalar_load_metadata(self, load, scalar);
+                scalar_load_metadata(self, load, scalar, layout, offset);
                 self.to_immediate_scalar(load, scalar)
             };
 
             OperandValue::Pair(
-                load(0, a, place.align),
-                load(1, b, place.align.restrict_for_offset(b_offset)),
+                load(0, a, place.layout, place.align, Size::ZERO),
+                load(1, b, place.layout, place.align.restrict_for_offset(b_offset), b_offset),
             )
         } else {
             OperandValue::Ref(place.llval, None, place.align)
@@ -1208,6 +1218,18 @@ fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
         }
     }
 
+    fn align_metadata(&mut self, load: &'ll Value, align: Align) {
+        unsafe {
+            let v = [self.cx.const_u64(align.bytes())];
+
+            llvm::LLVMSetMetadata(
+                load,
+                llvm::MD_align as c_uint,
+                llvm::LLVMMDNodeInContext(self.cx.llcx, v.as_ptr(), v.len() as c_uint),
+            );
+        }
+    }
+
     fn noundef_metadata(&mut self, load: &'ll Value) {
         unsafe {
             llvm::LLVMSetMetadata(
index 9d34734f4e59ac83845cb0f947c5789f656e4071..b10e74625dadc81edc4c04bb18f4213a387553e8 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
-use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar};
+use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::ScalarInt;
 use rustc_span::symbol::Symbol;
@@ -106,32 +106,6 @@ pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
         bytes_in_context(self.llcx, bytes)
     }
 
-    fn const_cstr(&self, s: Symbol, null_terminated: bool) -> &'ll Value {
-        unsafe {
-            if let Some(&llval) = self.const_cstr_cache.borrow().get(&s) {
-                return llval;
-            }
-
-            let s_str = s.as_str();
-            let sc = llvm::LLVMConstStringInContext(
-                self.llcx,
-                s_str.as_ptr() as *const c_char,
-                s_str.len() as c_uint,
-                !null_terminated as Bool,
-            );
-            let sym = self.generate_local_symbol_name("str");
-            let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
-                bug!("symbol `{}` is already defined", sym);
-            });
-            llvm::LLVMSetInitializer(g, sc);
-            llvm::LLVMSetGlobalConstant(g, True);
-            llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
-
-            self.const_cstr_cache.borrow_mut().insert(s, g);
-            g
-        }
-    }
-
     pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
         unsafe {
             assert_eq!(idx as c_uint as u64, idx);
@@ -204,9 +178,23 @@ fn const_real(&self, t: &'ll Type, val: f64) -> &'ll Value {
     }
 
     fn const_str(&self, s: Symbol) -> (&'ll Value, &'ll Value) {
-        let len = s.as_str().len();
+        let s_str = s.as_str();
+        let str_global = *self.const_str_cache.borrow_mut().entry(s).or_insert_with(|| {
+            let sc = self.const_bytes(s_str.as_bytes());
+            let sym = self.generate_local_symbol_name("str");
+            let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
+                bug!("symbol `{}` is already defined", sym);
+            });
+            unsafe {
+                llvm::LLVMSetInitializer(g, sc);
+                llvm::LLVMSetGlobalConstant(g, True);
+                llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
+            }
+            g
+        });
+        let len = s_str.len();
         let cs = consts::ptrcast(
-            self.const_cstr(s, false),
+            str_global,
             self.type_ptr_to(self.layout_of(self.tcx.types.str_).llvm_type(self)),
         );
         (cs, self.const_usize(len as u64))
@@ -249,6 +237,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) ->
                 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 alloc = alloc.inner();
                         let value = match alloc.mutability {
                             Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
                             _ => self.static_addr_of(init, alloc.align, None),
@@ -285,24 +274,25 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) ->
         }
     }
 
-    fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value {
+    fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
         const_alloc_to_llvm(self, alloc)
     }
 
     fn from_const_alloc(
         &self,
         layout: TyAndLayout<'tcx>,
-        alloc: &Allocation,
+        alloc: ConstAllocation<'tcx>,
         offset: Size,
     ) -> PlaceRef<'tcx, &'ll Value> {
-        assert_eq!(alloc.align, layout.align.abi);
+        let alloc_align = alloc.inner().align;
+        assert_eq!(alloc_align, layout.align.abi);
         let llty = self.type_ptr_to(layout.llvm_type(self));
         let llval = if layout.size == Size::ZERO {
-            let llval = self.const_usize(alloc.align.bytes());
+            let llval = self.const_usize(alloc_align.bytes());
             unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
         } else {
             let init = const_alloc_to_llvm(self, alloc);
-            let base_addr = self.static_addr_of(init, alloc.align, None);
+            let base_addr = self.static_addr_of(init, alloc_align, None);
 
             let llval = unsafe {
                 llvm::LLVMRustConstInBoundsGEP2(
index c98720944c9769c32b03460d94d1e29238914377..7d3fe43eeab17d3f0bff7ca7ea88952a8b02d2f1 100644 (file)
@@ -12,7 +12,7 @@
 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, InitChunk, Pointer,
+    read_target_uint, Allocation, ConstAllocation, ErrorHandled, GlobalAlloc, InitChunk, Pointer,
     Scalar as InterpScalar,
 };
 use rustc_middle::mir::mono::MonoItem;
@@ -25,7 +25,8 @@
 use std::ops::Range;
 use tracing::debug;
 
-pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
+pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>) -> &'ll Value {
+    let alloc = alloc.inner();
     let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
     let dl = cx.data_layout();
     let pointer_size = dl.pointer_size.bytes() as usize;
@@ -127,7 +128,7 @@ fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>(
 pub fn codegen_static_initializer<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     def_id: DefId,
-) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
+) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> {
     let alloc = cx.tcx.eval_static_initializer(def_id)?;
     Ok((const_alloc_to_llvm(cx, alloc), alloc))
 }
@@ -370,6 +371,7 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
                 // Error has already been reported
                 return;
             };
+            let alloc = alloc.inner();
 
             let g = self.get_static(def_id);
 
index f102becf2bdba125ef1c0496fc8836ea5066aec5..52e03e0ad3d6b963d02e331a4216dac6fb986543 100644 (file)
@@ -55,7 +55,7 @@ pub struct CodegenCx<'ll, 'tcx> {
     pub vtables:
         RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<Symbol, &'ll Value>>,
+    pub const_str_cache: RefCell<FxHashMap<Symbol, &'ll Value>>,
 
     /// Reverse-direction for const ptrs cast from globals.
     ///
@@ -415,7 +415,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             codegen_unit,
             instances: Default::default(),
             vtables: Default::default(),
-            const_cstr_cache: Default::default(),
+            const_str_cache: Default::default(),
             const_unsized: Default::default(),
             const_globals: Default::default(),
             statics_to_rauw: RefCell::new(Vec::new()),
index e7c13e793d92e3150cca00f3d9b8f33243d73989..7f804ab5e6347aad8a5e9a4809420c65990b77c5 100644 (file)
@@ -300,34 +300,34 @@ fn codegen_intrinsic_call(
                 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 {
+                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
+                        layout.size() <= self.data_layout().pointer_size * 2
                     }
                 };
 
                 let a = args[0].immediate();
                 let b = args[1].immediate();
-                if layout.size.bytes() == 0 {
+                if layout.size().bytes() == 0 {
                     self.const_bool(true)
                 } else if use_integer_compare {
-                    let integer_ty = self.type_ix(layout.size.bits());
+                    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 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);
+                    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 n = self.const_usize(layout.size().bytes());
                     let cmp = self.call_intrinsic("memcmp", &[a_ptr, b_ptr, n]);
                     self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
                 }
index 6e9e0332faf604c7ba033cb1a0bf26de8d5ddafb..375b9927c867219579c4cf15d9ad6cf19a7ec792 100644 (file)
@@ -441,6 +441,7 @@ pub enum MetadataType {
     MD_nontemporal = 9,
     MD_mem_parallel_loop_access = 10,
     MD_nonnull = 11,
+    MD_align = 17,
     MD_type = 19,
     MD_noundef = 29,
 }
@@ -1175,11 +1176,12 @@ pub fn LLVMRustGetNamedValue(
 
     // Operations on attributes
     pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute;
-    pub fn LLVMRustCreateAttrString(C: &Context, Name: *const c_char) -> &Attribute;
-    pub fn LLVMRustCreateAttrStringValue(
+    pub fn LLVMCreateStringAttribute(
         C: &Context,
         Name: *const c_char,
+        NameLen: c_uint,
         Value: *const c_char,
+        ValueLen: c_uint,
     ) -> &Attribute;
     pub fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute;
     pub fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute;
index 4892b8d4a84c696e620d52a0934e5a21bde868b7..48fbc1de8ee4407adbf323e87430a66ad98ff3c2 100644 (file)
@@ -47,12 +47,28 @@ pub fn AddCallSiteAttributes<'ll>(
     }
 }
 
-pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &CStr, value: &CStr) -> &'ll Attribute {
-    unsafe { LLVMRustCreateAttrStringValue(llcx, attr.as_ptr(), value.as_ptr()) }
+pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -> &'ll Attribute {
+    unsafe {
+        LLVMCreateStringAttribute(
+            llcx,
+            attr.as_ptr().cast(),
+            attr.len().try_into().unwrap(),
+            value.as_ptr().cast(),
+            value.len().try_into().unwrap(),
+        )
+    }
 }
 
-pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &CStr) -> &'ll Attribute {
-    unsafe { LLVMRustCreateAttrStringValue(llcx, attr.as_ptr(), std::ptr::null()) }
+pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute {
+    unsafe {
+        LLVMCreateStringAttribute(
+            llcx,
+            attr.as_ptr().cast(),
+            attr.len().try_into().unwrap(),
+            std::ptr::null(),
+            0,
+        )
+    }
 }
 
 pub fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute {
index 3b06587061d9d5b4821f95c2bcac16ea73afa5bc..e9d13a4ebaf8cb775162de4b198f660d5c8214f3 100644 (file)
@@ -369,12 +369,12 @@ pub fn target_cpu(sess: &Session) -> &str {
 /// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
 /// `--target` and similar).
 pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<String> {
-    // Features that come earlier are overriden by conflicting features later in the string.
+    // Features that come earlier are overridden by conflicting features later in the string.
     // Typically we'll want more explicit settings to override the implicit ones, so:
     //
-    // * Features from -Ctarget-cpu=*; are overriden by [^1]
-    // * Features implied by --target; are overriden by
-    // * Features from -Ctarget-feature; are overriden by
+    // * Features from -Ctarget-cpu=*; are overridden by [^1]
+    // * Features implied by --target; are overridden by
+    // * Features from -Ctarget-feature; are overridden by
     // * function specific features.
     //
     // [^1]: target-cpu=native is handled here, other target-cpu values are handled implicitly
@@ -383,7 +383,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
     // FIXME(nagisa): it isn't clear what's the best interaction between features implied by
     // `-Ctarget-cpu` and `--target` are. On one hand, you'd expect CLI arguments to always
     // override anything that's implicit, so e.g. when there's no `--target` flag, features implied
-    // the host target are overriden by `-Ctarget-cpu=*`. On the other hand, what about when both
+    // the host target are overridden by `-Ctarget-cpu=*`. On the other hand, what about when both
     // `--target` and `-Ctarget-cpu=*` are specified? Both then imply some target features and both
     // flags are specified by the user on the CLI. It isn't as clear-cut which order of precedence
     // should be taken in cases like these.
index 8bbf25ce030f8f14a95f9a50cda465c83caa836b..87d0680bf6f308fa8427b7919e61872f87a76676 100644 (file)
@@ -9,7 +9,7 @@ test = false
 [dependencies]
 bitflags = "1.2.1"
 cc = "1.0.69"
-itertools = "0.10"
+itertools = "0.10.1"
 tracing = "0.1"
 libc = "0.2.50"
 jobserver = "0.1.22"
index 1561277b7049f1b9b3f50b2d9848938ff49f884f..62a297937d40c66c2856fa5746f67f6123e64cb2 100644 (file)
@@ -1,6 +1,6 @@
 // Type Names for Debug Info.
 
-// Notes on targetting MSVC:
+// Notes on targeting 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:
@@ -427,7 +427,7 @@ fn msvc_enum_fallback<'tcx>(
 
             // calculate the range of values for the dataful variant
             let dataful_discriminant_range =
-                dataful_variant_layout.largest_niche.unwrap().scalar.valid_range;
+                dataful_variant_layout.largest_niche().unwrap().scalar.valid_range;
 
             let min = dataful_discriminant_range.start;
             let min = tag.value.size(&tcx).truncate(min);
index fd4adfea8082c745eeead9a6c47108dd215f841a..df011d6ca5fab6e4989d63b3e19eb7c5190b6fca 100644 (file)
@@ -39,6 +39,7 @@
     // #[target_feature].
     ("thumb-mode", Some(sym::arm_target_feature)),
     ("thumb2", Some(sym::arm_target_feature)),
+    ("d32", Some(sym::arm_target_feature)),
 ];
 
 const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
index 5260b7cc33120e0e36c05d3d79eb0ad537b7d317..918f36841695a194a5af533997f87e52cb2c2532 100644 (file)
@@ -1,6 +1,6 @@
 use super::BackendTypes;
 use crate::mir::place::PlaceRef;
-use rustc_middle::mir::interpret::{Allocation, Scalar};
+use rustc_middle::mir::interpret::{ConstAllocation, Scalar};
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_span::Symbol;
 use rustc_target::abi::{self, Size};
@@ -26,13 +26,13 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64>;
     fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128>;
 
-    fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value;
+    fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value;
 
     fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value;
     fn from_const_alloc(
         &self,
         layout: TyAndLayout<'tcx>,
-        alloc: &Allocation,
+        alloc: ConstAllocation<'tcx>,
         offset: Size,
     ) -> PlaceRef<'tcx, Self::Value>;
 
index dad572741049b1aac840648f1865fb5418a068ff..df809e8270195862ffd27ceb39b81fa4f20011c5 100644 (file)
@@ -367,7 +367,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                             "the raw bytes of the constant ({}",
                             display_allocation(
                                 *ecx.tcx,
-                                ecx.tcx.global_alloc(alloc_id).unwrap_memory()
+                                ecx.tcx.global_alloc(alloc_id).unwrap_memory().inner()
                             )
                         ));
                     },
index ac25cfd057c17ed1bc7b77d265fe4a08104d084b..92f4d3a6772444d79638249261ddcbc8fd7aa48c 100644 (file)
@@ -18,8 +18,8 @@
 use rustc_target::spec::abi::Abi;
 
 use crate::interpret::{
-    self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, OpTy,
-    PlaceTy, Scalar, StackPopUnwind,
+    self, compile_time_machine, AllocId, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
+    OpTy, PlaceTy, Scalar, StackPopUnwind,
 };
 
 use super::error::*;
@@ -475,13 +475,14 @@ fn stack_mut<'a>(
     fn before_access_global(
         memory_extra: &MemoryExtra,
         alloc_id: AllocId,
-        allocation: &Allocation,
+        alloc: ConstAllocation<'tcx>,
         static_def_id: Option<DefId>,
         is_write: bool,
     ) -> InterpResult<'tcx> {
+        let alloc = alloc.inner();
         if is_write {
             // Write access. These are never allowed, but we give a targeted error message.
-            if allocation.mutability == Mutability::Not {
+            if alloc.mutability == Mutability::Not {
                 Err(err_ub!(WriteToReadOnly(alloc_id)).into())
             } else {
                 Err(ConstEvalErrKind::ModifiedGlobal.into())
@@ -504,7 +505,7 @@ fn before_access_global(
                 // But make sure we never accept a read from something mutable, that would be
                 // unsound. The reason is that as the content of this allocation may be different
                 // now and at run-time, so if we permit reading now we might return the wrong value.
-                assert_eq!(allocation.mutability, Mutability::Not);
+                assert_eq!(alloc.mutability, Mutability::Not);
                 Ok(())
             }
         }
index 724f92243d07ee73116b46cfd0c5c6ffa18fe68a..c49c5ecac267607290081dee62f6264761fcba78 100644 (file)
@@ -183,7 +183,7 @@ pub(crate) fn deref_const<'tcx>(
     let mplace = ecx.deref_operand(&op).unwrap();
     if let Some(alloc_id) = mplace.ptr.provenance {
         assert_eq!(
-            tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().mutability,
+            tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().inner().mutability,
             Mutability::Not,
             "deref_const cannot be used with mutable allocations as \
             that could allow pattern matching to observe mutable statics",
index e2c4eb1dadc83facbfe202c929681901e4ad2ced..5be0a183cf6b40300685b951120cf339abee7cca 100644 (file)
@@ -97,7 +97,7 @@ pub fn cast(
         Ok(())
     }
 
-    fn misc_cast(
+    pub fn misc_cast(
         &self,
         src: &ImmTy<'tcx, M::PointerTag>,
         cast_ty: Ty<'tcx>,
@@ -139,7 +139,7 @@ fn misc_cast(
                 if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) {
                     assert!(src.layout.is_zst());
                     let discr_layout = self.layout_of(discr.ty)?;
-                    return Ok(self.cast_from_scalar(discr.val, discr_layout, cast_ty).into());
+                    return Ok(self.cast_from_int_like(discr.val, discr_layout, cast_ty).into());
                 }
             }
             Variants::Multiple { .. } => {}
@@ -169,17 +169,17 @@ fn misc_cast(
             }
         }
 
-        // # The remaining source values are scalar.
+        // # The remaining source values are scalar and "int-like".
 
         // For all remaining casts, we either
         // (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 = src.to_scalar()?.to_bits(src.layout.size)?;
-        Ok(self.cast_from_scalar(bits, src.layout, cast_ty).into())
+        Ok(self.cast_from_int_like(bits, src.layout, cast_ty).into())
     }
 
-    pub(super) fn cast_from_scalar(
+    fn cast_from_int_like(
         &self,
         v: u128, // raw bits (there is no ScalarTy so we separate data+layout)
         src_layout: TyAndLayout<'tcx>,
index 2096addb9f78629103a074503f4a9e5362f6de3d..bacb3f6ea7fec8471131ba42d3bc81c8d1d1be0b 100644 (file)
 
 use rustc_ast::Mutability;
 
-use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, ValueVisitor};
+use super::{
+    AllocId, Allocation, ConstAllocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy,
+    ValueVisitor,
+};
 use crate::const_eval;
 
 pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
@@ -131,8 +134,8 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
         alloc.mutability = Mutability::Not;
     };
     // link the alloc id to the actual allocation
-    let alloc = tcx.intern_const_alloc(alloc);
     leftover_allocations.extend(alloc.relocations().iter().map(|&(_, alloc_id)| alloc_id));
+    let alloc = tcx.intern_const_alloc(alloc);
     tcx.set_alloc_id_memory(alloc_id, alloc);
     None
 }
@@ -393,7 +396,7 @@ pub fn intern_const_alloc_recursive<
             }
             let alloc = tcx.intern_const_alloc(alloc);
             tcx.set_alloc_id_memory(alloc_id, alloc);
-            for &(_, alloc_id) in alloc.relocations().iter() {
+            for &(_, alloc_id) in alloc.inner().relocations().iter() {
                 if leftover_allocations.insert(alloc_id) {
                     todo.push(alloc_id);
                 }
@@ -425,7 +428,7 @@ pub fn intern_with_temp_alloc(
             &mut InterpCx<'mir, 'tcx, M>,
             &PlaceTy<'tcx, M::PointerTag>,
         ) -> InterpResult<'tcx, ()>,
-    ) -> InterpResult<'tcx, &'tcx Allocation> {
+    ) -> InterpResult<'tcx, ConstAllocation<'tcx>> {
         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;
index bf7e811c76f8edc4dfa228d5f8a26de4d08a2f73..715b174491bcbc524921d082b028a17b3b1cb487 100644 (file)
@@ -56,7 +56,7 @@ fn numeric_intrinsic<Tag>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<T
         sym::type_name => {
             ensure_monomorphic_enough(tcx, tp_ty)?;
             let alloc = type_name::alloc_type_name(tcx, tp_ty);
-            ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
+            ConstValue::Slice { data: alloc, start: 0, end: alloc.inner().len() }
         }
         sym::needs_drop => {
             ensure_monomorphic_enough(tcx, tp_ty)?;
@@ -219,48 +219,11 @@ pub fn emulate_intrinsic(
             sym::saturating_add | sym::saturating_sub => {
                 let l = self.read_immediate(&args[0])?;
                 let r = self.read_immediate(&args[1])?;
-                let is_add = intrinsic_name == sym::saturating_add;
-                let (val, overflowed, _ty) = self.overflowing_binary_op(
-                    if is_add { BinOp::Add } else { BinOp::Sub },
+                let val = self.saturating_arith(
+                    if intrinsic_name == sym::saturating_add { BinOp::Add } else { BinOp::Sub },
                     &l,
                     &r,
                 )?;
-                let val = if overflowed {
-                    let size = l.layout.size;
-                    let num_bits = size.bits();
-                    if l.layout.abi.is_signed() {
-                        // For signed ints the saturated value depends on the sign of the first
-                        // term since the sign of the second term can be inferred from this and
-                        // the fact that the operation has overflowed (if either is 0 no
-                        // overflow can occur)
-                        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
-                            // can only increase an (in range) negative term for addition
-                            // or corresponding negated positive term for subtraction
-                            Scalar::from_uint(
-                                (1u128 << (num_bits - 1)) - 1, // max positive
-                                Size::from_bits(num_bits),
-                            )
-                        } else {
-                            // Positive overflow not possible for similar reason
-                            // max negative
-                            Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
-                        }
-                    } else {
-                        // unsigned
-                        if is_add {
-                            // max unsigned
-                            Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
-                        } else {
-                            // underflow to 0
-                            Scalar::from_uint(0u128, Size::from_bits(num_bits))
-                        }
-                    }
-                } else {
-                    val
-                };
                 self.write_scalar(val, dest)?;
             }
             sym::discriminant_value => {
@@ -508,6 +471,49 @@ pub fn exact_div(
         self.binop_ignore_overflow(BinOp::Div, &a, &b, dest)
     }
 
+    pub fn saturating_arith(
+        &self,
+        mir_op: BinOp,
+        l: &ImmTy<'tcx, M::PointerTag>,
+        r: &ImmTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
+        assert!(matches!(mir_op, BinOp::Add | BinOp::Sub));
+        let (val, overflowed, _ty) = self.overflowing_binary_op(mir_op, l, r)?;
+        Ok(if overflowed {
+            let size = l.layout.size;
+            let num_bits = size.bits();
+            if l.layout.abi.is_signed() {
+                // For signed ints the saturated value depends on the sign of the first
+                // term since the sign of the second term can be inferred from this and
+                // the fact that the operation has overflowed (if either is 0 no
+                // overflow can occur)
+                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
+                    // can only increase an (in range) negative term for addition
+                    // or corresponding negated positive term for subtraction
+                    Scalar::from_int(size.signed_int_max(), size)
+                } else {
+                    // Positive overflow not possible for similar reason
+                    // max negative
+                    Scalar::from_int(size.signed_int_min(), size)
+                }
+            } else {
+                // unsigned
+                if matches!(mir_op, BinOp::Add) {
+                    // max unsigned
+                    Scalar::from_uint(size.unsigned_int_max(), size)
+                } else {
+                    // underflow to 0
+                    Scalar::from_uint(0u128, size)
+                }
+            }
+        } else {
+            val
+        })
+    }
+
     /// Offsets a pointer by some multiple of its type, returning an error if the pointer leaves its
     /// allocation. For integer pointers, we consider each of them their own tiny allocation of size
     /// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value.
index aa84b16b502817cf0e28d4b20837f329861ae1fc..dfc1a6e4d38e12828791fd4c39c8b7b51cf69537 100644 (file)
@@ -1,6 +1,6 @@
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::DisambiguatedDefPathData;
-use rustc_middle::mir::interpret::Allocation;
+use rustc_middle::mir::interpret::{Allocation, ConstAllocation};
 use rustc_middle::ty::{
     self,
     print::{PrettyPrinter, Print, Printer},
@@ -188,7 +188,7 @@ fn write_str(&mut self, s: &str) -> std::fmt::Result {
 }
 
 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
-crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
+crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
     let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
     let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
     tcx.intern_const_alloc(alloc)
index 23ec3875cbc1a51a38d4cbec791f9d0044389166..7d75c84d108357d35b993301f7da2816c7076cb4 100644 (file)
@@ -13,8 +13,9 @@
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    AllocId, AllocRange, Allocation, Frame, ImmTy, InterpCx, InterpResult, LocalValue, MemPlace,
-    Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
+    AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
+    LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
+    StackPopUnwind,
 };
 
 /// Data returned by Machine::stack_pop,
@@ -252,7 +253,7 @@ fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx
     fn before_access_global(
         _memory_extra: &Self::MemoryExtra,
         _alloc_id: AllocId,
-        _allocation: &Allocation,
+        _allocation: ConstAllocation<'tcx>,
         _static_def_id: Option<DefId>,
         _is_write: bool,
     ) -> InterpResult<'tcx> {
index 04a6209990ccf72795e45716ae4f89f30db87675..e100ebc4ccb2814fe8450608985e9a825fa48d65 100644 (file)
@@ -525,12 +525,11 @@ fn get_global_alloc(
             }
         };
         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 = M::init_allocation_extra(
             self,
             id, // always use the ID we got as input, not the "hidden" one.
-            alloc,
+            Cow::Borrowed(alloc.inner()),
             M::GLOBAL_KIND.map(MemoryKind::Machine),
         );
         Ok(alloc)
@@ -711,6 +710,7 @@ pub fn get_size_and_align(
             Some(GlobalAlloc::Memory(alloc)) => {
                 // Need to duplicate the logic here, because the global allocations have
                 // different associated types than the interpreter-local ones.
+                let alloc = alloc.inner();
                 Ok((alloc.size(), alloc.align))
             }
             Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
@@ -867,7 +867,7 @@ fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>(
                                 &mut *fmt,
                                 self.mem.tcx,
                                 &mut allocs_to_print,
-                                alloc,
+                                alloc.inner(),
                             )?;
                         }
                         Some(GlobalAlloc::Function(func)) => {
index 716c01ba78ceb6a337076efb45f214d74df816a0..fb4fe41bdbc4c31981b3007ab59cd9faf8c7a02d 100644 (file)
@@ -535,7 +535,7 @@ pub fn eval_operand(
                 let val =
                     self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?;
                 // This can still fail:
-                // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
+                // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
                 //   checked yet.
                 // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
 
@@ -681,18 +681,22 @@ pub fn read_discriminant(
         let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
         assert_eq!(tag_layout.size, tag_val.layout.size);
         assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
-        let tag_val = tag_val.to_scalar()?;
-        trace!("tag value: {:?}", tag_val);
+        trace!("tag value: {}", tag_val);
 
         // Figure out which discriminant and variant this corresponds to.
         Ok(match *tag_encoding {
             TagEncoding::Direct => {
+                // Generate a specific error if `tag_val` is not an integer.
+                // (`tag_bits` itself is only used for error messages below.)
                 let tag_bits = tag_val
+                    .to_scalar()?
                     .try_to_int()
                     .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
                     .assert_bits(tag_layout.size);
                 // Cast bits from tag layout to discriminant layout.
-                let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
+                // After the checks we did above, this cannot fail.
+                let discr_val =
+                    self.misc_cast(&tag_val, discr_layout.ty).unwrap().to_scalar().unwrap();
                 let discr_bits = discr_val.assert_bits(discr_layout.size);
                 // Convert discriminant to variant index, and catch invalid discriminants.
                 let index = match *op.layout.ty.kind() {
@@ -712,6 +716,7 @@ pub fn read_discriminant(
                 (discr_val, index.0)
             }
             TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
+                let tag_val = tag_val.to_scalar()?;
                 // Compute the variant this niche value/"tag" corresponds to. With niche layout,
                 // discriminant (encoded in niche/tag) and variant index are the same.
                 let variants_start = niche_variants.start().as_u32();
index 079ce9f07b8e10f5e322ec4c03add05fc224dfec..6dae9dc72b7b4668df706aa5dc605f0e2c3a7ea4 100644 (file)
@@ -127,17 +127,29 @@ fn binary_int_op(
 
         // Shift ops can have an RHS with a different numeric type.
         if bin_op == Shl || bin_op == Shr {
-            let signed = left_layout.abi.is_signed();
             let size = u128::from(left_layout.size.bits());
+            // Even if `r` is signed, we treat it as if it was unsigned (i.e., we use its
+            // zero-extended form). This matches the codegen backend:
+            // <https://github.com/rust-lang/rust/blob/c274e4969f058b1c644243181ece9f829efa7594/compiler/rustc_codegen_ssa/src/base.rs#L315-L317>.
+            // The overflow check is also ignorant to the sign:
+            // <https://github.com/rust-lang/rust/blob/c274e4969f058b1c644243181ece9f829efa7594/compiler/rustc_codegen_ssa/src/mir/rvalue.rs#L728>.
+            // This would behave rather strangely if we had integer types of size 256: a shift by
+            // -1i8 would actually shift by 255, but that would *not* be considered overflowing. A
+            // shift by -1i16 though would be considered overflowing. If we had integers of size
+            // 512, then a shift by -1i8 would even produce a different result than one by -1i16:
+            // the first shifts by 255, the latter by u16::MAX % 512 = 511. Lucky enough, our
+            // integers are maximally 128bits wide, so negative shifts *always* overflow and we have
+            // consistent results for the same value represented at different bit widths.
+            assert!(size <= 128);
             let overflow = r >= size;
             // The shift offset is implicitly masked to the type size, to make sure this operation
             // is always defined. This is the one MIR operator that does *not* directly map to a
             // single LLVM operation. See
-            // <https://github.com/rust-lang/rust/blob/a3b9405ae7bb6ab4e8103b414e75c44598a10fd2/compiler/rustc_codegen_ssa/src/common.rs#L131-L158>
+            // <https://github.com/rust-lang/rust/blob/c274e4969f058b1c644243181ece9f829efa7594/compiler/rustc_codegen_ssa/src/common.rs#L131-L158>
             // for the corresponding truncation in our codegen backends.
             let r = r % size;
             let r = u32::try_from(r).unwrap(); // we masked so this will always fit
-            let result = if signed {
+            let result = if left_layout.abi.is_signed() {
                 let l = self.sign_extend(l, left_layout) as i128;
                 let result = match bin_op {
                     Shl => l.checked_shl(r).unwrap(),
index 8094bf0cf2e2f7361ec1819a40ce85e74dc09641..d2fbd6a9654f90d66c20ab41cd0d6e047b687acc 100644 (file)
@@ -39,7 +39,8 @@ pub(super) fn eval_terminator(
                 let mut target_block = targets.otherwise();
 
                 for (const_int, target) in targets.iter() {
-                    // Compare using binary_op, to also support pointer values
+                    // Compare using MIR BinOp::Eq, to also support pointer values.
+                    // (Avoiding `self.binary_op` as that does some redundant layout computation.)
                     let res = self
                         .overflowing_binary_op(
                             mir::BinOp::Eq,
index b78924490cae83da5b373081f91e0ec5fc13e660..7dc279cc840fba930b174c3e11b720e82c91d9d8 100644 (file)
@@ -230,8 +230,6 @@ pub fn check_body(&mut self) {
                 }
             }
 
-            self.check_item_predicates();
-
             for (idx, local) in body.local_decls.iter_enumerated() {
                 // Handle the return place below.
                 if idx == RETURN_PLACE || local.internal {
@@ -358,83 +356,11 @@ fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
 
             match *ty.kind() {
                 ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)),
-                ty::Opaque(..) => self.check_op(ops::ty::ImplTrait),
-                ty::FnPtr(..) => self.check_op(ops::ty::FnPtr(kind)),
-
-                ty::Dynamic(preds, _) => {
-                    for pred in preds.iter() {
-                        match pred.skip_binder() {
-                            ty::ExistentialPredicate::AutoTrait(_)
-                            | ty::ExistentialPredicate::Projection(_) => {
-                                self.check_op(ops::ty::DynTrait(kind))
-                            }
-                            ty::ExistentialPredicate::Trait(trait_ref) => {
-                                if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() {
-                                    self.check_op(ops::ty::DynTrait(kind))
-                                }
-                            }
-                        }
-                    }
-                }
                 _ => {}
             }
         }
     }
 
-    fn check_item_predicates(&mut self) {
-        let ConstCx { tcx, .. } = *self.ccx;
-
-        let mut current = self.def_id().to_def_id();
-        loop {
-            let predicates = tcx.predicates_of(current);
-            for (predicate, _) in predicates.predicates {
-                match predicate.kind().skip_binder() {
-                    ty::PredicateKind::RegionOutlives(_)
-                    | ty::PredicateKind::TypeOutlives(_)
-                    | ty::PredicateKind::WellFormed(_)
-                    | ty::PredicateKind::Projection(_)
-                    | ty::PredicateKind::ConstEvaluatable(..)
-                    | ty::PredicateKind::ConstEquate(..)
-                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
-                    ty::PredicateKind::ObjectSafe(_) => {
-                        bug!("object safe predicate on function: {:#?}", predicate)
-                    }
-                    ty::PredicateKind::ClosureKind(..) => {
-                        bug!("closure kind predicate on function: {:#?}", predicate)
-                    }
-                    ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) => {
-                        bug!("subtype/coerce predicate on function: {:#?}", predicate)
-                    }
-                    ty::PredicateKind::Trait(pred) => {
-                        if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
-                            continue;
-                        }
-                        match pred.self_ty().kind() {
-                            ty::Param(p) => {
-                                let generics = tcx.generics_of(current);
-                                let def = generics.type_param(p, tcx);
-                                let span = tcx.def_span(def.def_id);
-
-                                // These are part of the function signature, so treat them like
-                                // arguments when determining importance.
-                                let kind = LocalKind::Arg;
-
-                                self.check_op_spanned(ops::ty::TraitBound(kind), span);
-                            }
-                            // other kinds of bounds are either tautologies
-                            // or cause errors in other passes
-                            _ => continue,
-                        }
-                    }
-                }
-            }
-            match predicates.parent {
-                Some(parent) => current = parent,
-                None => break,
-            }
-        }
-    }
-
     fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {
         match self.const_kind() {
             // In a const fn all borrows are transient or point to the places given via
@@ -613,7 +539,9 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                 ),
                 _,
                 _,
-            ) => self.check_op(ops::FnPtrCast),
+            ) => {
+                // Nothing to do here. Function pointer casts are allowed now.
+            }
 
             Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
                 // Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
index f6b92df92c04434ebfba7ca175c4e88cdc691394..ba248a3b6cbe59e286d9b84a1e21770f6c962c41 100644 (file)
@@ -355,31 +355,6 @@ fn build_error(
     }
 }
 
-#[derive(Debug)]
-pub struct FnPtrCast;
-impl<'tcx> NonConstOp<'tcx> for FnPtrCast {
-    fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
-        if ccx.const_kind() != hir::ConstContext::ConstFn {
-            Status::Allowed
-        } else {
-            Status::Unstable(sym::const_fn_fn_ptr_basics)
-        }
-    }
-
-    fn build_error(
-        &self,
-        ccx: &ConstCx<'_, 'tcx>,
-        span: Span,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        feature_err(
-            &ccx.tcx.sess.parse_sess,
-            sym::const_fn_fn_ptr_basics,
-            span,
-            &format!("function pointer casts are not allowed in {}s", ccx.const_kind()),
-        )
-    }
-}
-
 #[derive(Debug)]
 pub struct Generator(pub hir::GeneratorKind);
 impl<'tcx> NonConstOp<'tcx> for Generator {
@@ -820,167 +795,4 @@ fn build_error(
             )
         }
     }
-
-    #[derive(Debug)]
-    pub struct FnPtr(pub mir::LocalKind);
-    impl<'tcx> NonConstOp<'tcx> for FnPtr {
-        fn importance(&self) -> DiagnosticImportance {
-            match self.0 {
-                mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
-                mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
-                    DiagnosticImportance::Primary
-                }
-            }
-        }
-
-        fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
-            if ccx.const_kind() != hir::ConstContext::ConstFn {
-                Status::Allowed
-            } else {
-                Status::Unstable(sym::const_fn_fn_ptr_basics)
-            }
-        }
-
-        fn build_error(
-            &self,
-            ccx: &ConstCx<'_, 'tcx>,
-            span: Span,
-        ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-            feature_err(
-                &ccx.tcx.sess.parse_sess,
-                sym::const_fn_fn_ptr_basics,
-                span,
-                &format!("function pointers cannot appear in {}s", ccx.const_kind()),
-            )
-        }
-    }
-
-    #[derive(Debug)]
-    pub struct ImplTrait;
-    impl<'tcx> NonConstOp<'tcx> for ImplTrait {
-        fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
-            Status::Unstable(sym::const_impl_trait)
-        }
-
-        fn build_error(
-            &self,
-            ccx: &ConstCx<'_, 'tcx>,
-            span: Span,
-        ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-            feature_err(
-                &ccx.tcx.sess.parse_sess,
-                sym::const_impl_trait,
-                span,
-                &format!("`impl Trait` is not allowed in {}s", ccx.const_kind()),
-            )
-        }
-    }
-
-    #[derive(Debug)]
-    pub struct TraitBound(pub mir::LocalKind);
-    impl<'tcx> NonConstOp<'tcx> for TraitBound {
-        fn importance(&self) -> DiagnosticImportance {
-            match self.0 {
-                mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
-                mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
-                    DiagnosticImportance::Primary
-                }
-            }
-        }
-
-        fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
-            if ccx.const_kind() != hir::ConstContext::ConstFn {
-                Status::Allowed
-            } else {
-                Status::Unstable(sym::const_fn_trait_bound)
-            }
-        }
-
-        fn build_error(
-            &self,
-            ccx: &ConstCx<'_, 'tcx>,
-            span: Span,
-        ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-            let mut err = feature_err(
-                &ccx.tcx.sess.parse_sess,
-                sym::const_fn_trait_bound,
-                span,
-                "trait bounds other than `Sized` on const fn parameters are unstable",
-            );
-
-            match ccx.fn_sig() {
-                Some(fn_sig) if !fn_sig.span.contains(span) => {
-                    err.span_label(fn_sig.span, "function declared as const here");
-                }
-                _ => {}
-            }
-
-            err
-        }
-    }
-
-    #[derive(Debug)]
-    pub struct DynTrait(pub mir::LocalKind);
-    impl<'tcx> NonConstOp<'tcx> for DynTrait {
-        fn importance(&self) -> DiagnosticImportance {
-            match self.0 {
-                mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
-                mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
-                    DiagnosticImportance::Primary
-                }
-            }
-        }
-
-        fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
-            if ccx.const_kind() != hir::ConstContext::ConstFn {
-                Status::Allowed
-            } else {
-                Status::Unstable(sym::const_fn_trait_bound)
-            }
-        }
-
-        fn build_error(
-            &self,
-            ccx: &ConstCx<'_, 'tcx>,
-            span: Span,
-        ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-            let mut err = feature_err(
-                &ccx.tcx.sess.parse_sess,
-                sym::const_fn_trait_bound,
-                span,
-                "trait objects in const fn are unstable",
-            );
-
-            match ccx.fn_sig() {
-                Some(fn_sig) if !fn_sig.span.contains(span) => {
-                    err.span_label(fn_sig.span, "function declared as const here");
-                }
-                _ => {}
-            }
-
-            err
-        }
-    }
-
-    /// A trait bound with the `?const Trait` opt-out
-    #[derive(Debug)]
-    pub struct TraitBoundNotConst;
-    impl<'tcx> NonConstOp<'tcx> for TraitBoundNotConst {
-        fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
-            Status::Unstable(sym::const_trait_bound_opt_out)
-        }
-
-        fn build_error(
-            &self,
-            ccx: &ConstCx<'_, 'tcx>,
-            span: Span,
-        ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-            feature_err(
-                &ccx.tcx.sess.parse_sess,
-                sym::const_trait_bound_opt_out,
-                span,
-                "`?const Trait` syntax is unstable",
-            )
-        }
-    }
 }
index ad296c97659d209e1978816e7788a7e362bc9f66..b82e97172614b0df6e0e29ad160973c73b07722f 100644 (file)
@@ -20,7 +20,7 @@ stable_deref_trait = "1.0.0"
 rayon = { version = "0.3.2", package = "rustc-rayon" }
 rayon-core = { version = "0.3.2", package = "rustc-rayon-core" }
 rustc-hash = "1.1.0"
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.6.1", features = ["const_generics", "union", "may_dangle"] }
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
 measureme = "10.0.0"
index 46054fe7bcbb97234dff1580361a490e4a2a0cd7..7a320b10b60300460fc3efe19811798742efb599 100644 (file)
@@ -1,3 +1,4 @@
+use crate::stable_hasher::{HashStable, StableHasher};
 use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
 use std::ops::Deref;
@@ -62,13 +63,17 @@ fn eq(&self, other: &Self) -> bool {
 
 impl<'a, T> Eq for Interned<'a, T> {}
 
-// In practice you can't intern any `T` that doesn't implement `Eq`, because
-// that's needed for hashing. Therefore, we won't be interning any `T` that
-// implements `PartialOrd` without also implementing `Ord`. So we can have the
-// bound `T: Ord` here and avoid duplication with the `Ord` impl below.
-impl<'a, T: Ord> PartialOrd for Interned<'a, T> {
+impl<'a, T: PartialOrd> PartialOrd for Interned<'a, T> {
     fn partial_cmp(&self, other: &Interned<'a, T>) -> Option<Ordering> {
-        Some(self.cmp(other))
+        // Pointer equality implies equality, due to the uniqueness constraint,
+        // but the contents must be compared otherwise.
+        if ptr::eq(self.0, other.0) {
+            Some(Ordering::Equal)
+        } else {
+            let res = self.0.partial_cmp(&other.0);
+            debug_assert_ne!(res, Some(Ordering::Equal));
+            res
+        }
     }
 }
 
@@ -94,5 +99,14 @@ fn hash<H: Hasher>(&self, s: &mut H) {
     }
 }
 
+impl<T, CTX> HashStable<CTX> for Interned<'_, T>
+where
+    T: HashStable<CTX>,
+{
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.0.hash_stable(hcx, hasher);
+    }
+}
+
 #[cfg(test)]
 mod tests;
index b1e59d6502913621afd4c6d2b63412d84f5d0118..1a3fe652521567d839b359fdffa81ae0fd70c9b2 100644 (file)
@@ -80,6 +80,7 @@ macro_rules! unlikely {
 pub mod owning_ref;
 pub mod sip128;
 pub mod small_c_str;
+pub mod small_str;
 pub mod snapshot_map;
 pub mod stable_map;
 pub mod svh;
index cd9025245628e628c1f66b3e712eef03777e4162..3a8ab8ff9911e4a34d2b9d01027dec1d328c7b01 100644 (file)
@@ -62,6 +62,7 @@ pub fn spilled(&self) -> bool {
 impl Deref for SmallCStr {
     type Target = ffi::CStr;
 
+    #[inline]
     fn deref(&self) -> &ffi::CStr {
         self.as_c_str()
     }
diff --git a/compiler/rustc_data_structures/src/small_str.rs b/compiler/rustc_data_structures/src/small_str.rs
new file mode 100644 (file)
index 0000000..800acb1
--- /dev/null
@@ -0,0 +1,68 @@
+use smallvec::SmallVec;
+
+#[cfg(test)]
+mod tests;
+
+/// Like SmallVec but for strings.
+#[derive(Default)]
+pub struct SmallStr<const N: usize>(SmallVec<[u8; N]>);
+
+impl<const N: usize> SmallStr<N> {
+    #[inline]
+    pub fn new() -> Self {
+        SmallStr(SmallVec::default())
+    }
+
+    #[inline]
+    pub fn push_str(&mut self, s: &str) {
+        self.0.extend_from_slice(s.as_bytes());
+    }
+
+    #[inline]
+    pub fn empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    #[inline]
+    pub fn spilled(&self) -> bool {
+        self.0.spilled()
+    }
+
+    #[inline]
+    pub fn as_str(&self) -> &str {
+        unsafe { std::str::from_utf8_unchecked(self.0.as_slice()) }
+    }
+}
+
+impl<const N: usize> std::ops::Deref for SmallStr<N> {
+    type Target = str;
+
+    #[inline]
+    fn deref(&self) -> &str {
+        self.as_str()
+    }
+}
+
+impl<const N: usize, A: AsRef<str>> FromIterator<A> for SmallStr<N> {
+    #[inline]
+    fn from_iter<T>(iter: T) -> Self
+    where
+        T: IntoIterator<Item = A>,
+    {
+        let mut s = SmallStr::default();
+        s.extend(iter);
+        s
+    }
+}
+
+impl<const N: usize, A: AsRef<str>> Extend<A> for SmallStr<N> {
+    #[inline]
+    fn extend<T>(&mut self, iter: T)
+    where
+        T: IntoIterator<Item = A>,
+    {
+        for a in iter.into_iter() {
+            self.push_str(a.as_ref());
+        }
+    }
+}
diff --git a/compiler/rustc_data_structures/src/small_str/tests.rs b/compiler/rustc_data_structures/src/small_str/tests.rs
new file mode 100644 (file)
index 0000000..7635a9b
--- /dev/null
@@ -0,0 +1,20 @@
+use super::*;
+
+#[test]
+fn empty() {
+    let s = SmallStr::<1>::new();
+    assert!(s.empty());
+    assert_eq!("", s.as_str());
+    assert!(!s.spilled());
+}
+
+#[test]
+fn from_iter() {
+    let s = ["aa", "bb", "cc"].iter().collect::<SmallStr<6>>();
+    assert_eq!("aabbcc", s.as_str());
+    assert!(!s.spilled());
+
+    let s = ["aa", "bb", "cc", "dd"].iter().collect::<SmallStr<6>>();
+    assert_eq!("aabbccdd", s.as_str());
+    assert!(s.spilled());
+}
index 593316e2699fade06477c3c71367cd723dcc7977..0ec32dc43070d23fd638a23ad6114036d4d63c2b 100644 (file)
@@ -152,6 +152,3 @@ fn index(&self, idx: I) -> &Self::Output {
         &self.items[idx].1
     }
 }
-
-#[cfg(tests)]
-mod tests;
index b36ce63dda75632f6799fb07e37902b8e3b4f95c..43c9e9296b90aab2928f7ba275e1d5ef2d6eff12 100644 (file)
@@ -1228,7 +1228,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
 ///
 /// A custom rustc driver can skip calling this to set up a custom ICE hook.
 pub fn install_ice_hook() {
-    // If the user has not explicitly overriden "RUST_BACKTRACE", then produce
+    // If the user has not explicitly overridden "RUST_BACKTRACE", then produce
     // full backtraces. When a compiler ICE happens, we want to gather
     // as much information as possible to present in the issue opened
     // by the user. Compiler developers and other rustc users can
index 0c0c61309655c02fe10eb5a738ab4bac0e26007a..12bac956adb557048145a6513db63bee7bf32867 100644 (file)
@@ -42,7 +42,7 @@ fn call_with_pp_support<'tcx, A, F>(
     F: FnOnce(&dyn PrinterSupport) -> A,
 {
     match *ppmode {
-        Normal | EveryBodyLoops | Expanded => {
+        Normal | Expanded => {
             let annotation = NoAnn { sess, tcx };
             f(&annotation)
         }
index 262e52351ef01c203ad655f7c2683dc6915e8a8a..3b73abaf776c25bbda797300c44dada05266b1cc 100644 (file)
@@ -45,7 +45,7 @@ trait object's internal data to be accessed safely from any trait methods. This
 rule also goes for any lifetime any struct made into a trait object may have.
 
 In the implementation for `dyn Person`, the `'2` lifetime representing the
-internal data was ommitted, meaning that the compiler inferred the lifetime
+internal data was omitted, meaning that the compiler inferred the lifetime
 `'static`. As a result, the implementation's `is_cool` is inferred by the
 compiler to look like this:
 
index 7d7ab1ed4e5e6e26752ef3cb0f50abb10fd8b0e3..c380455012d0d430929aa6ab2671c58498d198c3 100644 (file)
@@ -75,6 +75,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType {
         // FIXME(#59346): Not sure how to map this level
         Level::FailureNote => AnnotationType::Error,
         Level::Allow => panic!("Should not call with Allow"),
+        Level::Expect(_) => panic!("Should not call with Expect"),
     }
 }
 
index 6d6ada86428db4fab448da52c7040f7e0483f6ae..39ebd57b4b296decfddd85a1874c3efe8559b399 100644 (file)
@@ -7,6 +7,7 @@
 use crate::ToolMetadata;
 use rustc_lint_defs::Applicability;
 use rustc_serialize::json::Json;
+use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use std::fmt;
 use std::hash::{Hash, Hasher};
@@ -133,7 +134,7 @@ pub fn is_error(&self) -> bool {
             | Level::Error { .. }
             | Level::FailureNote => true,
 
-            Level::Warning | Level::Note | Level::Help | Level::Allow => false,
+            Level::Warning | Level::Note | Level::Help | Level::Allow | Level::Expect(_) => false,
         }
     }
 
@@ -342,6 +343,18 @@ pub fn span_help<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self {
         self
     }
 
+    /// Help the user upgrade to the latest edition.
+    /// This is factored out to make sure it does the right thing with `Cargo.toml`.
+    pub fn help_use_latest_edition(&mut self) -> &mut Self {
+        if std::env::var_os("CARGO").is_some() {
+            self.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
+        } else {
+            self.help(&format!("pass `--edition {}` to `rustc`", LATEST_STABLE_EDITION));
+        }
+        self.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
+        self
+    }
+
     /// Disallow attaching suggestions this diagnostic.
     /// Any suggestions attached e.g. with the `span_suggestion_*` methods
     /// (before and after the call to `disable_suggestions`) will be ignored.
index 5dc71f1620096113c04ccefde7ab58c8ceda3dcd..98b8b2a569edde1bfb6f4f5e1261cb3e2e99087b 100644 (file)
@@ -409,6 +409,7 @@ pub fn span_labels(
         sp: impl Into<MultiSpan>,
         msg: &str,
     ) -> &mut Self);
+    forward!(pub fn help_use_latest_edition(&mut self,) -> &mut Self);
     forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
 
     forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
index e45a57b26587a0472a62cdc32ea1a53e1129942f..217d3ec2c247ae6edbd6dcaf26677eb6d991bde5 100644 (file)
 
 pub use emitter::ColorConfig;
 
+use rustc_lint_defs::LintExpectationId;
 use Level::*;
 
 use emitter::{is_case_difference, Emitter, EmitterWriter};
 use registry::Registry;
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{self, Lock, Lrc};
 use rustc_data_structures::AtomicRef;
@@ -450,6 +451,22 @@ struct HandlerInner {
     deduplicated_warn_count: usize,
 
     future_breakage_diagnostics: Vec<Diagnostic>,
+
+    /// Expected [`Diagnostic`]s store a [`LintExpectationId`] as part of
+    /// the lint level. [`LintExpectationId`]s created early during the compilation
+    /// (before `HirId`s have been defined) are not stable and can therefore not be
+    /// stored on disk. This buffer stores these diagnostics until the ID has been
+    /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`]s are the
+    /// submitted for storage and added to the list of fulfilled expectations.
+    unstable_expect_diagnostics: Vec<Diagnostic>,
+
+    /// expected diagnostic will have the level `Expect` which additionally
+    /// carries the [`LintExpectationId`] of the expectation that can be
+    /// marked as fulfilled. This is a collection of all [`LintExpectationId`]s
+    /// that have been marked as fulfilled this way.
+    ///
+    /// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html
+    fulfilled_expectations: FxHashSet<LintExpectationId>,
 }
 
 /// A key denoting where from a diagnostic was stashed.
@@ -570,6 +587,8 @@ pub fn with_emitter_and_flags(
                 emitted_diagnostics: Default::default(),
                 stashed_diagnostics: Default::default(),
                 future_breakage_diagnostics: Vec::new(),
+                unstable_expect_diagnostics: Vec::new(),
+                fulfilled_expectations: Default::default(),
             }),
         }
     }
@@ -677,6 +696,11 @@ pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
         DiagnosticBuilder::new(self, Level::Allow, msg)
     }
 
+    /// Construct a builder at the `Expect` level with the `msg`.
+    pub fn struct_expect(&self, msg: &str, id: LintExpectationId) -> DiagnosticBuilder<'_, ()> {
+        DiagnosticBuilder::new(self, Level::Expect(id), msg)
+    }
+
     /// Construct a builder at the `Error` level at the given `span` and with the `msg`.
     pub fn struct_span_err(
         &self,
@@ -906,6 +930,48 @@ pub fn emit_future_breakage_report(&self, diags: Vec<Diagnostic>) {
     pub fn emit_unused_externs(&self, lint_level: &str, unused_externs: &[&str]) {
         self.inner.borrow_mut().emit_unused_externs(lint_level, unused_externs)
     }
+
+    pub fn update_unstable_expectation_id(
+        &self,
+        unstable_to_stable: &FxHashMap<LintExpectationId, LintExpectationId>,
+    ) {
+        let diags = std::mem::take(&mut self.inner.borrow_mut().unstable_expect_diagnostics);
+        if diags.is_empty() {
+            return;
+        }
+
+        let mut inner = self.inner.borrow_mut();
+        for mut diag in diags.into_iter() {
+            let mut unstable_id = diag
+                .level
+                .get_expectation_id()
+                .expect("all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`");
+
+            // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index.
+            // The lint index inside the attribute is manually transferred here.
+            let lint_index = unstable_id.get_lint_index();
+            unstable_id.set_lint_index(None);
+            let mut stable_id = *unstable_to_stable
+                .get(&unstable_id)
+                .expect("each unstable `LintExpectationId` must have a matching stable id");
+
+            stable_id.set_lint_index(lint_index);
+            diag.level = Level::Expect(stable_id);
+            inner.fulfilled_expectations.insert(stable_id);
+
+            (*TRACK_DIAGNOSTICS)(&diag);
+        }
+    }
+
+    /// This methods steals all [`LintExpectationId`]s that are stored inside
+    /// [`HandlerInner`] and indicate that the linked expectation has been fulfilled.
+    pub fn steal_fulfilled_expectation_ids(&self) -> FxHashSet<LintExpectationId> {
+        assert!(
+            self.inner.borrow().unstable_expect_diagnostics.is_empty(),
+            "`HandlerInner::unstable_expect_diagnostics` should be empty at this point",
+        );
+        std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
+    }
 }
 
 impl HandlerInner {
@@ -951,9 +1017,21 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             return;
         }
 
+        // The `LintExpectationId` can be stable or unstable depending on when it was created.
+        // Diagnostics created before the definition of `HirId`s are unstable and can not yet
+        // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
+        // a stable one by the `LintLevelsBuilder`.
+        if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level {
+            self.unstable_expect_diagnostics.push(diagnostic.clone());
+            return;
+        }
+
         (*TRACK_DIAGNOSTICS)(diagnostic);
 
-        if diagnostic.level == Allow {
+        if let Level::Expect(expectation_id) = diagnostic.level {
+            self.fulfilled_expectations.insert(expectation_id);
+            return;
+        } else if diagnostic.level == Allow {
             return;
         }
 
@@ -1250,6 +1328,7 @@ pub enum Level {
     Help,
     FailureNote,
     Allow,
+    Expect(LintExpectationId),
 }
 
 impl fmt::Display for Level {
@@ -1275,7 +1354,7 @@ fn color(self) -> ColorSpec {
                 spec.set_fg(Some(Color::Cyan)).set_intense(true);
             }
             FailureNote => {}
-            Allow => unreachable!(),
+            Allow | Expect(_) => unreachable!(),
         }
         spec
     }
@@ -1289,12 +1368,20 @@ pub fn to_str(self) -> &'static str {
             Help => "help",
             FailureNote => "failure-note",
             Allow => panic!("Shouldn't call on allowed error"),
+            Expect(_) => panic!("Shouldn't call on expected error"),
         }
     }
 
     pub fn is_failure_note(&self) -> bool {
         matches!(*self, FailureNote)
     }
+
+    pub fn get_expectation_id(&self) -> Option<LintExpectationId> {
+        match self {
+            Level::Expect(id) => Some(*id),
+            _ => None,
+        }
+    }
 }
 
 // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite.
index d43c6fec7d5ad4efde6b308e3b72eab0946c92b0..762198887cf8cccb794a288c841249b385f6442b 100644 (file)
@@ -167,6 +167,7 @@ fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feat
             if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
                 let since = Some(Symbol::intern(since));
                 features.declared_lang_features.push((name, mi.span(), since));
+                features.active_features.insert(name);
                 continue;
             }
 
@@ -187,10 +188,12 @@ fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feat
             if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
                 f.set(&mut features, mi.span());
                 features.declared_lang_features.push((name, mi.span(), None));
+                features.active_features.insert(name);
                 continue;
             }
 
             features.declared_lib_features.push((name, mi.span()));
+            features.active_features.insert(name);
         }
     }
 
index 1b9761805093974a6012d674821ebb66b919c345..4af376b983c94a44ec2baca5bca2df9d3cd2c483 100644 (file)
@@ -1841,7 +1841,7 @@ fn flat_map_generic_param(
         self.flat_map_node(node)
     }
 
-    fn flat_map_stmt(&mut self, mut node: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
+    fn flat_map_stmt(&mut self, node: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
         // FIXME: invocations in semicolon-less expressions positions are expanded as expressions,
         // changing that requires some compatibility measures.
         if node.is_expr() {
@@ -1863,7 +1863,7 @@ fn flat_map_generic_param(
                     self.cx.current_expansion.is_trailing_mac = false;
                     res
                 }
-                _ => assign_id!(self, &mut node.id, || noop_flat_map_stmt(node, self)),
+                _ => noop_flat_map_stmt(node, self),
             };
         }
 
index a419612e315df2fea566a58fe2f299a007ef90e5..bb36dfd793d4a03bb3a8b96a50b281661323079f 100644 (file)
@@ -154,7 +154,7 @@ struct MatcherTtFrame<'tt> {
 /// lifetime. By separating `'tt` from `'root`, we can show that.
 #[derive(Clone)]
 struct MatcherPos<'root, 'tt> {
-    /// The token or sequence of tokens that make up the matcher
+    /// The token or sequence of tokens that make up the matcher. `elts` is short for "elements".
     top_elts: TokenTreeOrTokenTreeSlice<'tt>,
 
     /// The position of the "dot" in this matcher
@@ -184,17 +184,8 @@ struct MatcherPos<'root, 'tt> {
     /// in this matcher.
     match_hi: usize,
 
-    // The following fields are used if we are matching a repetition. If we aren't, they should be
-    // `None`.
-    /// The KleeneOp of this sequence if we are in a repetition.
-    seq_op: Option<mbe::KleeneOp>,
-
-    /// The separator if we are in a repetition.
-    sep: Option<Token>,
-
-    /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
-    /// before we enter the sequence.
-    up: Option<MatcherPosHandle<'root, 'tt>>,
+    /// This field is only used if we are matching a repetition.
+    repetition: Option<MatcherPosRepetition<'root, 'tt>>,
 
     /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
     /// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc
@@ -207,7 +198,38 @@ struct MatcherPos<'root, 'tt> {
     stack: SmallVec<[MatcherTtFrame<'tt>; 1]>,
 }
 
+// This type is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 192);
+
 impl<'root, 'tt> MatcherPos<'root, 'tt> {
+    /// Generates the top-level matcher position in which the "dot" is before the first token of
+    /// the matcher `ms`.
+    fn new(ms: &'tt [TokenTree]) -> Self {
+        let match_idx_hi = count_names(ms);
+        MatcherPos {
+            // Start with the top level matcher given to us.
+            top_elts: TtSeq(ms),
+
+            // The "dot" is before the first token of the matcher.
+            idx: 0,
+
+            // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in
+            // `top_elts`. `match_lo` for `top_elts` is 0 and `match_hi` is `match_idx_hi`.
+            // `match_cur` is 0 since we haven't actually matched anything yet.
+            matches: create_matches(match_idx_hi),
+            match_lo: 0,
+            match_cur: 0,
+            match_hi: match_idx_hi,
+
+            // Haven't descended into any delimiters, so this is empty.
+            stack: smallvec![],
+
+            // Haven't descended into any sequences, so this is `None`.
+            repetition: None,
+        }
+    }
+
     /// Adds `m` as a named match for the `idx`-th metavar.
     fn push_match(&mut self, idx: usize, m: NamedMatch) {
         let matches = Lrc::make_mut(&mut self.matches[idx]);
@@ -215,6 +237,19 @@ fn push_match(&mut self, idx: usize, m: NamedMatch) {
     }
 }
 
+#[derive(Clone)]
+struct MatcherPosRepetition<'root, 'tt> {
+    /// The KleeneOp of this sequence.
+    seq_op: mbe::KleeneOp,
+
+    /// The separator.
+    sep: Option<Token>,
+
+    /// The "parent" matcher position. That is, the matcher position just before we enter the
+    /// sequence.
+    up: MatcherPosHandle<'root, 'tt>,
+}
+
 // Lots of MatcherPos instances are created at runtime. Allocating them on the
 // heap is slow. Furthermore, using SmallVec<MatcherPos> to allocate them all
 // on the stack is also slow, because MatcherPos is quite a large type and
@@ -258,6 +293,12 @@ fn deref_mut(&mut self) -> &mut MatcherPos<'root, 'tt> {
     }
 }
 
+enum EofItems<'root, 'tt> {
+    None,
+    One(MatcherPosHandle<'root, 'tt>),
+    Multiple,
+}
+
 /// Represents the possible results of an attempted parse.
 crate enum ParseResult<T> {
     /// Parsed successfully.
@@ -300,35 +341,6 @@ fn create_matches(len: usize) -> Box<[Lrc<NamedMatchVec>]> {
     .into_boxed_slice()
 }
 
-/// Generates the top-level matcher position in which the "dot" is before the first token of the
-/// matcher `ms`.
-fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree]) -> MatcherPos<'root, 'tt> {
-    let match_idx_hi = count_names(ms);
-    let matches = create_matches(match_idx_hi);
-    MatcherPos {
-        // Start with the top level matcher given to us
-        top_elts: TtSeq(ms), // "elts" is an abbr. for "elements"
-        // The "dot" is before the first token of the matcher
-        idx: 0,
-
-        // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`.
-        // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since
-        // we haven't actually matched anything yet.
-        matches,
-        match_lo: 0,
-        match_cur: 0,
-        match_hi: match_idx_hi,
-
-        // Haven't descended into any delimiters, so empty stack
-        stack: smallvec![],
-
-        // Haven't descended into any sequences, so both of these are `None`.
-        seq_op: None,
-        sep: None,
-        up: None,
-    }
-}
-
 /// `NamedMatch` is a pattern-match result for a single `token::MATCH_NONTERMINAL`:
 /// so it is associated with a single ident in a parse, and all
 /// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type
@@ -475,10 +487,10 @@ fn inner_parse_loop<'root, 'tt>(
     sess: &ParseSess,
     cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
     next_items: &mut Vec<MatcherPosHandle<'root, 'tt>>,
-    eof_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
     bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
+    eof_items: &mut EofItems<'root, 'tt>,
     token: &Token,
-) -> ParseResult<()> {
+) -> Result<(), (rustc_span::Span, String)> {
     // Pop items from `cur_items` until it is empty.
     while let Some(mut item) = cur_items.pop() {
         // When unzipped trees end, remove them. This corresponds to backtracking out of a
@@ -504,7 +516,7 @@ fn inner_parse_loop<'root, 'tt>(
             // We are repeating iff there is a parent. If the matcher is inside of a repetition,
             // then we could be at the end of a sequence or at the beginning of the next
             // repetition.
-            if item.up.is_some() {
+            if let Some(repetition) = &item.repetition {
                 // At this point, regardless of whether there is a separator, we should add all
                 // matches from the complete repetition of the sequence to the shared, top-level
                 // `matches` list (actually, `up.matches`, which could itself not be the top-level,
@@ -515,7 +527,7 @@ fn inner_parse_loop<'root, 'tt>(
                 // NOTE: removing the condition `idx == len` allows trailing separators.
                 if idx == len {
                     // Get the `up` matcher
-                    let mut new_pos = item.up.clone().unwrap();
+                    let mut new_pos = repetition.up.clone();
 
                     // Add matches from this repetition to the `matches` of `up`
                     for idx in item.match_lo..item.match_hi {
@@ -530,32 +542,33 @@ fn inner_parse_loop<'root, 'tt>(
                 }
 
                 // Check if we need a separator.
-                if idx == len && item.sep.is_some() {
+                if idx == len && repetition.sep.is_some() {
                     // We have a separator, and it is the current token. We can advance past the
                     // separator token.
-                    if item.sep.as_ref().map_or(false, |sep| token_name_eq(token, sep)) {
+                    if repetition.sep.as_ref().map_or(false, |sep| token_name_eq(token, sep)) {
                         item.idx += 1;
                         next_items.push(item);
                     }
-                }
-                // We don't need a separator. Move the "dot" back to the beginning of the matcher
-                // and try to match again UNLESS we are only allowed to have _one_ repetition.
-                else if item.seq_op != Some(mbe::KleeneOp::ZeroOrOne) {
+                } else if repetition.seq_op != mbe::KleeneOp::ZeroOrOne {
+                    // We don't need a separator. Move the "dot" back to the beginning of the
+                    // matcher and try to match again UNLESS we are only allowed to have _one_
+                    // repetition.
                     item.match_cur = item.match_lo;
                     item.idx = 0;
                     cur_items.push(item);
                 }
+            } else {
+                // If we are not in a repetition, then being at the end of a matcher means that we
+                // have reached the potential end of the input.
+                *eof_items = match eof_items {
+                    EofItems::None => EofItems::One(item),
+                    EofItems::One(_) | EofItems::Multiple => EofItems::Multiple,
+                }
             }
-            // If we are not in a repetition, then being at the end of a matcher means that we have
-            // reached the potential end of the input.
-            else {
-                eof_items.push(item);
-            }
-        }
-        // We are in the middle of a matcher.
-        else {
-            // Look at what token in the matcher we are trying to match the current token (`token`)
-            // against. Depending on that, we may generate new items.
+        } else {
+            // We are in the middle of a matcher. Look at what token in the matcher we are trying
+            // to match the current token (`token`) against. Depending on that, we may generate new
+            // items.
             match item.top_elts.get_tt(idx) {
                 // Need to descend into a sequence
                 TokenTree::Sequence(sp, seq) => {
@@ -578,14 +591,16 @@ fn inner_parse_loop<'root, 'tt>(
                     let matches = create_matches(item.matches.len());
                     cur_items.push(MatcherPosHandle::Box(Box::new(MatcherPos {
                         stack: smallvec![],
-                        sep: seq.separator.clone(),
-                        seq_op: Some(seq.kleene.op),
                         idx: 0,
                         matches,
                         match_lo: item.match_cur,
                         match_cur: item.match_cur,
                         match_hi: item.match_cur + seq.num_captures,
-                        up: Some(item),
+                        repetition: Some(MatcherPosRepetition {
+                            up: item,
+                            sep: seq.separator.clone(),
+                            seq_op: seq.kleene.op,
+                        }),
                         top_elts: Tt(TokenTree::Sequence(sp, seq)),
                     })));
                 }
@@ -593,7 +608,7 @@ fn inner_parse_loop<'root, 'tt>(
                 // We need to match a metavar (but the identifier is invalid)... this is an error
                 TokenTree::MetaVarDecl(span, _, None) => {
                     if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
-                        return Error(span, "missing fragment specifier".to_string());
+                        return Err((span, "missing fragment specifier".to_string()));
                     }
                 }
 
@@ -641,7 +656,7 @@ fn inner_parse_loop<'root, 'tt>(
     }
 
     // Yay a successful parse (so far)!
-    Success(())
+    Ok(())
 }
 
 /// Use the given sequence of token trees (`ms`) as a matcher. Match the token
@@ -659,17 +674,18 @@ pub(super) fn parse_tt(
     //
     // This MatcherPos instance is allocated on the stack. All others -- and
     // there are frequently *no* others! -- are allocated on the heap.
-    let mut initial = initial_matcher_pos(ms);
+    let mut initial = MatcherPos::new(ms);
     let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
     let mut next_items = Vec::new();
 
     loop {
+        assert!(next_items.is_empty());
+
         // Matcher positions black-box parsed by parser.rs (`parser`)
         let mut bb_items = SmallVec::new();
 
         // Matcher positions that would be valid if the macro invocation was over now
-        let mut eof_items = SmallVec::new();
-        assert!(next_items.is_empty());
+        let mut eof_items = EofItems::None;
 
         // Process `cur_items` until either we have finished the input or we need to get some
         // parsing from the black-box parser done. The result is that `next_items` will contain a
@@ -678,37 +694,34 @@ pub(super) fn parse_tt(
             parser.sess,
             &mut cur_items,
             &mut next_items,
-            &mut eof_items,
             &mut bb_items,
+            &mut eof_items,
             &parser.token,
         ) {
-            Success(_) => {}
-            Failure(token, msg) => return Failure(token, msg),
-            Error(sp, msg) => return Error(sp, msg),
-            ErrorReported => return ErrorReported,
+            Ok(()) => {}
+            Err((sp, msg)) => return Error(sp, msg),
         }
 
         // inner parse loop handled all cur_items, so it's empty
         assert!(cur_items.is_empty());
 
-        // We need to do some post processing after the `inner_parser_loop`.
+        // We need to do some post processing after the `inner_parse_loop`.
         //
         // Error messages here could be improved with links to original rules.
 
         // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
         // either the parse is ambiguous (which should never happen) or there is a syntax error.
         if parser.token == token::Eof {
-            if eof_items.len() == 1 {
-                let matches =
-                    eof_items[0].matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
-                return nameize(parser.sess, ms, matches);
-            } else if eof_items.len() > 1 {
-                return Error(
-                    parser.token.span,
-                    "ambiguity: multiple successful parses".to_string(),
-                );
-            } else {
-                return Failure(
+            return match eof_items {
+                EofItems::One(mut eof_item) => {
+                    let matches =
+                        eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
+                    nameize(parser.sess, ms, matches)
+                }
+                EofItems::Multiple => {
+                    Error(parser.token.span, "ambiguity: multiple successful parses".to_string())
+                }
+                EofItems::None => Failure(
                     Token::new(
                         token::Eof,
                         if parser.token.span.is_dummy() {
@@ -718,12 +731,12 @@ pub(super) fn parse_tt(
                         },
                     ),
                     "missing tokens in macro arguments",
-                );
-            }
+                ),
+            };
         }
-        // Performance hack: eof_items may share matchers via Rc with other things that we want
-        // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an
-        // unnecessary implicit clone later in Rc::make_mut.
+        // Performance hack: `eof_items` may share matchers via `Rc` with other things that we want
+        // to modify. Dropping `eof_items` now may drop these refcounts to 1, preventing an
+        // unnecessary implicit clone later in `Rc::make_mut`.
         drop(eof_items);
 
         // If there are no possible next positions AND we aren't waiting for the black-box parser,
@@ -731,9 +744,10 @@ pub(super) fn parse_tt(
         if bb_items.is_empty() && next_items.is_empty() {
             return Failure(parser.token.clone(), "no rules expected this token in macro call");
         }
-        // Another possibility is that we need to call out to parse some rust nonterminal
-        // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
-        else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
+
+        if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
+            // We need to call out to parse some rust nonterminal (black-box) parser. But something
+            // is wrong, because there is not EXACTLY ONE of these.
             let nts = bb_items
                 .iter()
                 .map(|item| match item.top_elts.get_tt(item.idx) {
@@ -755,15 +769,15 @@ pub(super) fn parse_tt(
                 ),
             );
         }
-        // Dump all possible `next_items` into `cur_items` for the next iteration.
-        else if !next_items.is_empty() {
-            // Now process the next token
+
+        if !next_items.is_empty() {
+            // Dump all possible `next_items` into `cur_items` for the next iteration. Then process
+            // the next token.
             cur_items.extend(next_items.drain(..));
             parser.to_mut().bump();
-        }
-        // Finally, we have the case where we need to call the black-box parser to get some
-        // nonterminal.
-        else {
+        } else {
+            // Finally, we have the case where we need to call the black-box parser to get some
+            // nonterminal.
             assert_eq!(bb_items.len(), 1);
 
             let mut item = bb_items.pop().unwrap();
index 54000527c15b9bf240b240e8ddd87ec92bbb0911..760dea77f9c2b1ecc9f2c018342dffadab2bb2e6 100644 (file)
@@ -233,7 +233,7 @@ pub(super) fn transcribe<'a>(
                         } else {
                             // Other variables are emitted into the output stream as groups with
                             // `Delimiter::None` to maintain parsing priorities.
-                            // `Interpolated` is currenty used for such groups in rustc parser.
+                            // `Interpolated` is currently used for such groups in rustc parser.
                             marker.visit_span(&mut sp);
                             TokenTree::token(token::Interpolated(nt.clone()), sp)
                         };
index 869cada400f0fe8069b8cfffb034c3e4c104c266..0aef5982cff509ccd066b6584fb6b9b071d7a191 100644 (file)
@@ -847,7 +847,7 @@ fn source_text(&mut self, span: Self::Span) -> Option<String> {
     /// the `quote` proc-macro. This will save the span of
     /// "hello" into the metadata of `my_proc_macro`. As a result,
     /// the body of `my_proc_macro` (after expansion) will end
-    /// up containg a call that looks like this:
+    /// up containing a call that looks like this:
     /// `proc_macro::Ident::new("hello", proc_macro::Span::recover_proc_macro_span(0))`
     ///
     /// where `0` is the id returned by this function.
index d43f926d0a56a458fc3dbd97fe27ef867736ba31..fc2ac75d609678d9587289261bf6b3fa329b9e9b 100644 (file)
@@ -86,6 +86,10 @@ macro_rules! declare_features {
     (accepted, conservative_impl_trait, "1.26.0", Some(34511), None),
     /// Allows calling constructor functions in `const fn`.
     (accepted, const_constructor, "1.40.0", Some(61456), None),
+    /// Allows using and casting function pointers in a `const fn`.
+    (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563), None),
+    /// Allows trait bounds in `const fn`.
+    (accepted, const_fn_trait_bound, "1.61.0", Some(93706), None),
     /// Allows calling `transmute` in const fn
     (accepted, const_fn_transmute, "1.56.0", Some(53605), None),
     /// Allows accessing fields of unions inside `const` functions.
@@ -96,6 +100,8 @@ macro_rules! declare_features {
     (accepted, const_generics_defaults, "1.59.0", Some(44580), None),
     /// Allows the use of `if` and `match` in constants.
     (accepted, const_if_match, "1.46.0", Some(49146), None),
+    /// Allows argument and return position `impl Trait` in a `const fn`.
+    (accepted, const_impl_trait, "1.61.0", Some(77463), None),
     /// Allows indexing into constant arrays.
     (accepted, const_indexing, "1.26.0", Some(29947), None),
     /// Allows let bindings, assignments and destructuring in `const` functions and constants.
index 1d9d16e85cb21286a7510f5e24b8d3954b7a22d3..a69d28b184aed8b1ee5102286fc8ebd78ae2bff5 100644 (file)
@@ -2,6 +2,7 @@
 
 use super::{to_nonzero, Feature, State};
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
@@ -47,6 +48,8 @@ pub struct Features {
             pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
             /// `#![feature]` attrs for non-language (library) features.
             pub declared_lib_features: Vec<(Symbol, Span)>,
+            /// Features enabled for this crate.
+            pub active_features: FxHashSet<Symbol>,
             $(
                 $(#[doc = $doc])*
                 pub $feature: bool
@@ -58,6 +61,11 @@ pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) {
                 $(f(stringify!($feature), self.$feature);)+
             }
 
+            /// Is the given feature active?
+            pub fn active(&self, feature: Symbol) -> bool {
+                self.active_features.contains(&feature)
+            }
+
             /// Is the given feature enabled?
             ///
             /// Panics if the symbol doesn't correspond to a declared feature.
@@ -330,14 +338,8 @@ pub fn set(&self, features: &mut Features, span: Span) {
     (active, const_extern_fn, "1.40.0", Some(64926), None),
     /// Allows basic arithmetic on floating point types in a `const fn`.
     (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
-    /// Allows using and casting function pointers in a `const fn`.
-    (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None),
-    /// Allows trait bounds in `const fn`.
-    (active, const_fn_trait_bound, "1.53.0", Some(93706), None),
     /// Allows `for _ in _` loops in const contexts.
     (active, const_for, "1.56.0", Some(87575), None),
-    /// Allows argument and return position `impl Trait` in a `const fn`.
-    (active, const_impl_trait, "1.48.0", Some(77463), None),
     /// Allows using `&mut` in constant functions.
     (active, const_mut_refs, "1.41.0", Some(57349), None),
     /// Be more precise when looking for live drops in a const context.
index 53762eef785920257279ca4075f0cbb229cc09e7..bb51f880099a6da051c93216125f4cb7c50fc497 100644 (file)
@@ -282,6 +282,10 @@ pub struct BuiltinAttribute {
     ungated!(
         allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
     ),
+    gated!(
+        expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk,
+        lint_reasons, experimental!(expect)
+    ),
     ungated!(
         forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
     ),
@@ -602,17 +606,17 @@ pub struct BuiltinAttribute {
     rustc_attr!(
         rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing,
         "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
-        niche optimizations in libcore and will never be stable",
+        niche optimizations in libcore and libstd and will never be stable",
     ),
     rustc_attr!(
         rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing,
         "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
-        niche optimizations in libcore and will never be stable",
+        niche optimizations in libcore and libstd and will never be stable",
     ),
     rustc_attr!(
         rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
         "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \
-        niche optimizations in libcore and will never be stable",
+        niche optimizations in libcore and libstd and will never be stable",
     ),
 
     // ==========================================================================
index 870c3f8068245f3d6a988b80753eea53a242182c..908a936142475bce5cd080b53393c68516b3c292 100644 (file)
@@ -27,7 +27,7 @@ pub enum LoadResult<T> {
     },
     /// The file either didn't exist or was produced by an incompatible compiler version.
     DataOutOfDate,
-    /// An error occured.
+    /// An error occurred.
     Error {
         #[allow(missing_docs)]
         message: String,
index 12bde02949452ee607d7b2a8d60ffa8b1a9e41d8..d7e5c2b60566e636dd3992d4ac215dc38f442d17 100644 (file)
@@ -654,15 +654,19 @@ fn intersect(&mut self, _other: &ChunkedBitSet<T>) -> bool {
 
 impl<T: Idx> BitRelations<HybridBitSet<T>> for ChunkedBitSet<T> {
     fn union(&mut self, other: &HybridBitSet<T>) -> bool {
-        // FIXME: this is slow if `other` is dense, and could easily be
-        // improved, but it hasn't been a problem in practice so far.
+        // FIXME: This is slow if `other` is dense, but it hasn't been a problem
+        // in practice so far.
+        // If a a faster implementation of this operation is required, consider
+        // reopening https://github.com/rust-lang/rust/pull/94625
         assert_eq!(self.domain_size, other.domain_size());
         sequential_update(|elem| self.insert(elem), other.iter())
     }
 
     fn subtract(&mut self, other: &HybridBitSet<T>) -> bool {
-        // FIXME: this is slow if `other` is dense, and could easily be
-        // improved, but it hasn't been a problem in practice so far.
+        // FIXME: This is slow if `other` is dense, but it hasn't been a problem
+        // in practice so far.
+        // If a a faster implementation of this operation is required, consider
+        // reopening https://github.com/rust-lang/rust/pull/94625
         assert_eq!(self.domain_size, other.domain_size());
         sequential_update(|elem| self.remove(elem), other.iter())
     }
index 3bc30f0220d40f64217375936a9bcf802d7f1d32..16f7504cbbe588a8ab07ef707d3af7d7fcff4acd 100644 (file)
@@ -928,7 +928,7 @@ pub fn need_type_info_err_in_generator(
 /// performing that replacement, we'll turn all remaining infer type params to use their name from
 /// their definition, and replace all the `[type error]`s back to being infer so they display in
 /// the output as `_`. If we didn't go through `[type error]`, we would either show all type params
-/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could
+/// by their name *or* `_`, neither of which is desirable: we want to show all types that we could
 /// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations.
 struct ResolvedTypeParamEraser<'tcx> {
     tcx: TyCtxt<'tcx>,
index e0420291aa3f5cbb96970a5a9504afd2deca84b6..4710eae6189a5fc087819f915fef1f9b26636d1a 100644 (file)
@@ -58,7 +58,7 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
                 bug!("Node not an impl.");
             };
 
-            // Next, let's figure out the set of trait objects with implict static bounds
+            // Next, let's figure out the set of trait objects with implicit 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);
index 381097344ec68eec5e000f22196e5b257d862cfd..e98f33ea86eef899769407146fdff37204382b7e 100644 (file)
@@ -1,3 +1,5 @@
+//! Greatest lower bound. See [`lattice`].
+
 use super::combine::CombineFields;
 use super::lattice::{self, LatticeDir};
 use super::InferCtxt;
index c47d476963772e2adda260bca51b6a4f3e1f1c97..32affd6a14e1cf0038441feb1fffc9eccc9cdc1c 100644 (file)
@@ -1,23 +1,21 @@
-//! # Lattice Variables
+//! # Lattice variables
 //!
-//! This file contains generic code for operating on inference variables
-//! that are characterized by an upper- and lower-bound. The logic and
-//! reasoning is explained in detail in the large comment in `infer.rs`.
+//! Generic code for operating on [lattices] of inference variables
+//! that are characterized by an upper- and lower-bound.
 //!
-//! The code in here is defined quite generically so that it can be
+//! The code is defined quite generically so that it can be
 //! applied both to type variables, which represent types being inferred,
 //! and fn variables, which represent function types being inferred.
-//! It may eventually be applied to their types as well, who knows.
+//! (It may eventually be applied to their types as well.)
 //! In some cases, the functions are also generic with respect to the
 //! operation on the lattice (GLB vs LUB).
 //!
-//! Although all the functions are generic, we generally write the
-//! comments in a way that is specific to type variables and the LUB
-//! operation. It's just easier that way.
+//! ## Note
 //!
-//! In general all of the functions are defined parametrically
-//! over a `LatticeValue`, which is a value defined with respect to
-//! a lattice.
+//! Although all the functions are generic, for simplicity, comments in the source code
+//! generally refer to type variables and the LUB operation.
+//!
+//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
 
 use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use super::InferCtxt;
 use rustc_middle::ty::TyVar;
 use rustc_middle::ty::{self, Ty};
 
+/// Trait for returning data about a lattice, and for abstracting
+/// over the "direction" of the lattice operation (LUB/GLB).
+///
+/// GLB moves "down" the lattice (to smaller values); LUB moves
+/// "up" the lattice (to bigger values).
 pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
     fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
 
@@ -41,6 +44,7 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
 }
 
+/// Relates two types using a given lattice.
 pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
     this: &mut L,
     a: Ty<'tcx>,
index 57cbe2c54f7aec978ddbee9e837b0e54cae8eda9..bc85a4ac609a748bda607b6542d550f43dc899e0 100644 (file)
@@ -1,3 +1,5 @@
+//! Least upper bound. See [`lattice`].
+
 use super::combine::CombineFields;
 use super::lattice::{self, LatticeDir};
 use super::InferCtxt;
index 7f4a4ffadec148a4474a411f6430d975c92ceda0..e7563933c88ac97a19480dab3aca8b9b875f4624 100644 (file)
@@ -207,6 +207,9 @@ macro_rules! error {
                                             "`values()` first argument must be a simple identifer"
                                         );
                                     }
+                                } else if args.is_empty() {
+                                    cfg.well_known_values = true;
+                                    continue 'specs;
                                 }
                             }
                         }
index 3b51f8eb61c8e83a2397bfc794487329c132359e..1aceb4e95e6138090b2863529ae35fa2bec3383e 100644 (file)
@@ -3,7 +3,6 @@
 use crate::util;
 
 use ast::CRATE_NODE_ID;
-use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::{self as ast, visit};
 use rustc_borrowck as mir_borrowck;
 use rustc_codegen_ssa::back::link::emit_metadata;
@@ -29,7 +28,7 @@
 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::config::{CrateType, Input, OutputFilenames, OutputType};
 use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn};
 use rustc_session::lint;
 use rustc_session::output::{filename_for_input, filename_for_metadata};
@@ -384,11 +383,6 @@ pub fn configure_and_expand(
         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(resolver).visit_crate(&mut krate);
-    }
-
     let has_proc_macro_decls = sess.time("AST_validation", || {
         rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer())
     });
@@ -457,18 +451,12 @@ pub fn configure_and_expand(
     });
 
     // Add all buffered lints from the `ParseSess` to the `Session`.
-    // The ReplaceBodyWithLoop pass may have deleted some AST nodes, potentially
-    // causing a delay_span_bug later if a buffered lint refers to such a deleted
-    // AST node (issue #87308). Since everybody_loops is for pretty-printing only,
-    // anyway, we simply skip all buffered lints here.
-    if !matches!(sess.opts.pretty, Some(PpMode::Source(PpSourceMode::EveryBodyLoops))) {
-        sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
-            info!("{} parse sess buffered_lints", buffered_lints.len());
-            for early_lint in buffered_lints.drain(..) {
-                resolver.lint_buffer().add_early_lint(early_lint);
-            }
-        });
-    }
+    sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
+        info!("{} parse sess buffered_lints", buffered_lints.len());
+        for early_lint in buffered_lints.drain(..) {
+            resolver.lint_buffer().add_early_lint(early_lint);
+        }
+    });
 
     // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing.
     sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| {
@@ -933,12 +921,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                     tcx.ensure().check_mod_const_bodies(module);
                 });
             },
+            {
+                sess.time("unused_lib_feature_checking", || {
+                    rustc_passes::stability::check_unused_or_stable_features(tcx)
+                });
+            },
             {
                 // 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(());
+                tcx.ensure().stability_index(());
             }
         );
     });
@@ -1010,11 +1004,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                         tcx.hir()
                             .par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
                     },
-                    {
-                        sess.time("unused_lib_feature_checking", || {
-                            rustc_passes::stability::check_unused_or_stable_features(tcx)
-                        });
-                    },
                     {
                         sess.time("lint_checking", || {
                             rustc_lint::check_crate(tcx, || {
index 046f4f9451f58b535e27c470bd6b8f71d919e23a..592cf60e6c3bb30b3bb1fa20d8cb4915dfb035c4 100644 (file)
@@ -1,7 +1,5 @@
 use libloading::Library;
-use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
-use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Term};
+use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 #[cfg(parallel_compiler)]
@@ -13,7 +11,6 @@
 use rustc_parse::validate_attr;
 #[cfg(parallel_compiler)]
 use rustc_query_impl::QueryCtxt;
-use rustc_resolve::{self, Resolver};
 use rustc_session as session;
 use rustc_session::config::CheckCfg;
 use rustc_session::config::{self, CrateType};
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::FileLoader;
 use rustc_span::symbol::{sym, Symbol};
-use smallvec::SmallVec;
 use std::env;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::lazy::SyncOnceCell;
 use std::mem;
-use std::ops::DerefMut;
 #[cfg(not(parallel_compiler))]
 use std::panic;
 use std::path::{Path, PathBuf};
@@ -664,214 +659,6 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
     std::fs::rename(src, dst)
 }
 
-/// Replaces function bodies with `loop {}` (an infinite loop). This gets rid of
-/// all semantic errors in the body while still satisfying the return type,
-/// except in certain cases, see below for more.
-///
-/// This pass is known as `everybody_loops`. Very punny.
-///
-/// As of March 2021, `everybody_loops` is only used for the
-/// `-Z unpretty=everybody_loops` debugging option.
-///
-/// FIXME: Currently the `everybody_loops` transformation is not applied to:
-///  * `const fn`; support could be added, but hasn't. Originally `const fn`
-///    was skipped due to issue #43636 that `loop` was not supported for
-///    const evaluation.
-///  * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging.
-///    Solving this may require `!` to implement every trait, which relies on the an even more
-///    ambitious form of the closed RFC #1637. See also [#34511].
-///
-/// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
-pub struct ReplaceBodyWithLoop<'a, 'b> {
-    within_static_or_const: bool,
-    nested_blocks: Option<Vec<ast::Block>>,
-    resolver: &'a mut Resolver<'b>,
-}
-
-impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
-    pub fn new(resolver: &'a mut Resolver<'b>) -> ReplaceBodyWithLoop<'a, 'b> {
-        ReplaceBodyWithLoop { within_static_or_const: false, nested_blocks: None, resolver }
-    }
-
-    fn run<R, F: FnOnce(&mut Self) -> R>(&mut self, is_const: bool, action: F) -> R {
-        let old_const = mem::replace(&mut self.within_static_or_const, is_const);
-        let old_blocks = self.nested_blocks.take();
-        let ret = action(self);
-        self.within_static_or_const = old_const;
-        self.nested_blocks = old_blocks;
-        ret
-    }
-
-    fn should_ignore_fn(ret_ty: &ast::FnRetTy) -> bool {
-        let ast::FnRetTy::Ty(ref ty) = ret_ty else {
-            return false;
-        };
-        fn involves_impl_trait(ty: &ast::Ty) -> bool {
-            match ty.kind {
-                ast::TyKind::ImplTrait(..) => true,
-                ast::TyKind::Slice(ref subty)
-                | ast::TyKind::Array(ref subty, _)
-                | ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. })
-                | ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. })
-                | ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
-                ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
-                ast::TyKind::Path(_, ref path) => {
-                    path.segments.iter().any(|seg| match seg.args.as_deref() {
-                        None => false,
-                        Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
-                            data.args.iter().any(|arg| match arg {
-                                ast::AngleBracketedArg::Arg(arg) => match arg {
-                                    ast::GenericArg::Type(ty) => involves_impl_trait(ty),
-                                    ast::GenericArg::Lifetime(_) | ast::GenericArg::Const(_) => {
-                                        false
-                                    }
-                                },
-                                ast::AngleBracketedArg::Constraint(c) => match c.kind {
-                                    ast::AssocConstraintKind::Bound { .. } => true,
-                                    ast::AssocConstraintKind::Equality { ref term } => {
-                                        match term {
-                                            Term::Ty(ty) => involves_impl_trait(ty),
-                                            // FIXME(...): This should check if the constant
-                                            // involves a trait impl, but for now ignore.
-                                            Term::Const(_) => false,
-                                        }
-                                    }
-                                },
-                            })
-                        }
-                        Some(&ast::GenericArgs::Parenthesized(ref data)) => {
-                            any_involves_impl_trait(data.inputs.iter())
-                                || ReplaceBodyWithLoop::should_ignore_fn(&data.output)
-                        }
-                    })
-                }
-                _ => false,
-            }
-        }
-
-        fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool {
-            it.any(|subty| involves_impl_trait(subty))
-        }
-
-        involves_impl_trait(ty)
-    }
-
-    fn is_sig_const(sig: &ast::FnSig) -> bool {
-        matches!(sig.header.constness, ast::Const::Yes(_))
-            || ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output)
-    }
-}
-
-impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
-    fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
-        let is_const = match i {
-            ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
-            ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
-            _ => false,
-        };
-        self.run(is_const, |s| noop_visit_item_kind(i, s))
-    }
-
-    fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        let is_const = match i.kind {
-            ast::AssocItemKind::Const(..) => true,
-            ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
-            _ => false,
-        };
-        self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
-    }
-
-    fn flat_map_impl_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        self.flat_map_trait_item(i)
-    }
-
-    fn visit_anon_const(&mut self, c: &mut ast::AnonConst) {
-        self.run(true, |s| noop_visit_anon_const(c, s))
-    }
-
-    fn visit_block(&mut self, b: &mut P<ast::Block>) {
-        fn stmt_to_block(
-            rules: ast::BlockCheckMode,
-            s: Option<ast::Stmt>,
-            resolver: &mut Resolver<'_>,
-        ) -> ast::Block {
-            ast::Block {
-                stmts: s.into_iter().collect(),
-                rules,
-                id: resolver.next_node_id(),
-                span: rustc_span::DUMMY_SP,
-                tokens: None,
-                could_be_bare_literal: false,
-            }
-        }
-
-        fn block_to_stmt(b: ast::Block, resolver: &mut Resolver<'_>) -> ast::Stmt {
-            let expr = P(ast::Expr {
-                id: resolver.next_node_id(),
-                kind: ast::ExprKind::Block(P(b), None),
-                span: rustc_span::DUMMY_SP,
-                attrs: AttrVec::new(),
-                tokens: None,
-            });
-
-            ast::Stmt {
-                id: resolver.next_node_id(),
-                kind: ast::StmtKind::Expr(expr),
-                span: rustc_span::DUMMY_SP,
-            }
-        }
-
-        let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.resolver);
-        let loop_expr = P(ast::Expr {
-            kind: ast::ExprKind::Loop(P(empty_block), None),
-            id: self.resolver.next_node_id(),
-            span: rustc_span::DUMMY_SP,
-            attrs: AttrVec::new(),
-            tokens: None,
-        });
-
-        let loop_stmt = ast::Stmt {
-            id: self.resolver.next_node_id(),
-            span: rustc_span::DUMMY_SP,
-            kind: ast::StmtKind::Expr(loop_expr),
-        };
-
-        if self.within_static_or_const {
-            noop_visit_block(b, self)
-        } else {
-            visit_clobber(b.deref_mut(), |b| {
-                let mut stmts = vec![];
-                for s in b.stmts {
-                    let old_blocks = self.nested_blocks.replace(vec![]);
-
-                    stmts.extend(self.flat_map_stmt(s).into_iter().filter(|s| s.is_item()));
-
-                    // we put a Some in there earlier with that replace(), so this is valid
-                    let new_blocks = self.nested_blocks.take().unwrap();
-                    self.nested_blocks = old_blocks;
-                    stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, self.resolver)));
-                }
-
-                let mut new_block = ast::Block { stmts, ..b };
-
-                if let Some(old_blocks) = self.nested_blocks.as_mut() {
-                    //push our fresh block onto the cache and yield an empty block with `loop {}`
-                    if !new_block.stmts.is_empty() {
-                        old_blocks.push(new_block);
-                    }
-
-                    stmt_to_block(b.rules, Some(loop_stmt), &mut self.resolver)
-                } else {
-                    //push `loop {}` onto the end of our fresh block and yield that
-                    new_block.stmts.push(loop_stmt);
-
-                    new_block
-                }
-            })
-        }
-    }
-}
-
 /// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
 pub fn version_str() -> Option<&'static str> {
     option_env!("CFG_VERSION")
index 72b8d8bb297a6b8a486814726ddf34851b73ac31..b6b73ba45391ea1d3d19e3b999bdbf634b8855e6 100644 (file)
@@ -2861,8 +2861,8 @@ fn structurally_same_type_impl<'tcx>(
 
                 let compare_layouts = |a, b| -> Result<bool, LayoutError<'tcx>> {
                     debug!("compare_layouts({:?}, {:?})", a, b);
-                    let a_layout = &cx.layout_of(a)?.layout.abi;
-                    let b_layout = &cx.layout_of(b)?.layout.abi;
+                    let a_layout = &cx.layout_of(a)?.layout.abi();
+                    let b_layout = &cx.layout_of(b)?.layout.abi();
                     debug!(
                         "comparing layouts: {:?} == {:?} = {}",
                         a_layout,
index ad9a16fb39ae2d5fe3641ec255058e816c96a6e3..b892e520d3bdeb4194fef8342496f676752d3330 100644 (file)
@@ -109,6 +109,7 @@ struct LintGroup {
     depr: Option<LintAlias>,
 }
 
+#[derive(Debug)]
 pub enum CheckLintNameResult<'a> {
     Ok(&'a [LintId]),
     /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
@@ -377,6 +378,9 @@ pub fn check_lint_name_cmdline(
                     Level::ForceWarn => "--force-warn",
                     Level::Deny => "-D",
                     Level::Forbid => "-F",
+                    Level::Expect(_) => {
+                        unreachable!("lints with the level of `expect` should not run this code");
+                    }
                 },
                 lint_name
             );
@@ -775,39 +779,55 @@ fn lookup_with_diagnostics(
                     db.help(&help);
                     db.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information");
                 },
-                BuiltinLintDiagnostics::UnexpectedCfg(span, name, value) => {
-                    let possibilities: Vec<Symbol> = if value.is_some() {
-                        let Some(values) = &sess.parse_sess.check_config.values_valid.get(&name) else {
-                            bug!("it shouldn't be possible to have a diagnostic on a value whose name is not in values");
-                        };
-                        values.iter().map(|&s| s).collect()
-                    } else {
-                        let Some(names_valid) = &sess.parse_sess.check_config.names_valid else {
-                            bug!("it shouldn't be possible to have a diagnostic on a name if name checking is not enabled");
-                        };
-                        names_valid.iter().map(|s| *s).collect()
+                BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), None) => {
+                    let Some(names_valid) = &sess.parse_sess.check_config.names_valid else {
+                        bug!("it shouldn't be possible to have a diagnostic on a name if name checking is not enabled");
                     };
+                    let possibilities: Vec<Symbol> = names_valid.iter().map(|s| *s).collect();
+
+                    // Suggest the most probable if we found one
+                    if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
+                        db.span_suggestion(name_span, "did you mean", format!("{best_match}"), Applicability::MaybeIncorrect);
+                    }
+                },
+                BuiltinLintDiagnostics::UnexpectedCfg((name, name_span), Some((value, value_span))) => {
+                    let Some(values) = &sess.parse_sess.check_config.values_valid.get(&name) else {
+                        bug!("it shouldn't be possible to have a diagnostic on a value whose name is not in values");
+                    };
+                    let possibilities: Vec<Symbol> = values.iter().map(|&s| s).collect();
 
                     // Show the full list if all possible values for a given name, but don't do it
                     // for names as the possibilities could be very long
-                    if value.is_some() {
-                        if !possibilities.is_empty() {
+                    if !possibilities.is_empty() {
+                        {
                             let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
                             possibilities.sort();
 
                             let possibilities = possibilities.join(", ");
                             db.note(&format!("expected values for `{name}` are: {possibilities}"));
-                        } else {
-                            db.note(&format!("no expected value for `{name}`"));
                         }
-                    }
 
-                    // Suggest the most probable if we found one
-                    if let Some(best_match) = find_best_match_for_name(&possibilities, value.unwrap_or(name), None) {
-                        let punctuation = if value.is_some() { "\"" } else { "" };
-                        db.span_suggestion(span, "did you mean", format!("{punctuation}{best_match}{punctuation}"), Applicability::MaybeIncorrect);
+                        // Suggest the most probable if we found one
+                        if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) {
+                            db.span_suggestion(value_span, "did you mean", format!("\"{best_match}\""), Applicability::MaybeIncorrect);
+                        }
+                    } else {
+                        db.note(&format!("no expected value for `{name}`"));
+                        if name != sym::feature {
+                            db.span_suggestion(name_span.shrink_to_hi().to(value_span), "remove the value", String::new(), Applicability::MaybeIncorrect);
+                        }
                     }
                 },
+                BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => {
+                    db.multipart_suggestion(
+                        "move it to the end of the type declaration",
+                        vec![(db.span.primary_span().unwrap(), "".to_string()), (new_span, suggestion)],
+                        Applicability::MachineApplicable,
+                    );
+                    db.note(
+                        "see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information",
+                    );
+                },
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
index 1b2c88867d49dbe2822ff83ad1af5d59ea240b22..e9b7620bf1d7f50744eb66a3c026874629519887 100644 (file)
@@ -59,7 +59,8 @@ fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'a [ast::Attribute], f
         F: FnOnce(&mut Self),
     {
         let is_crate_node = id == ast::CRATE_NODE_ID;
-        let push = self.context.builder.push(attrs, is_crate_node);
+        let push = self.context.builder.push(attrs, is_crate_node, None);
+
         self.check_id(id);
         self.enter_attrs(attrs);
         f(self);
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
new file mode 100644 (file)
index 0000000..e6c9d0b
--- /dev/null
@@ -0,0 +1,49 @@
+use crate::builtin;
+use rustc_hir::HirId;
+use rustc_middle::{lint::LintExpectation, ty::TyCtxt};
+use rustc_session::lint::LintExpectationId;
+use rustc_span::symbol::sym;
+
+pub fn check_expectations(tcx: TyCtxt<'_>) {
+    if !tcx.sess.features_untracked().enabled(sym::lint_reasons) {
+        return;
+    }
+
+    let fulfilled_expectations = tcx.sess.diagnostic().steal_fulfilled_expectation_ids();
+    let lint_expectations = &tcx.lint_levels(()).lint_expectations;
+
+    for (id, expectation) in lint_expectations {
+        if !fulfilled_expectations.contains(id) {
+            // This check will always be true, since `lint_expectations` only
+            // holds stable ids
+            if let LintExpectationId::Stable { hir_id, .. } = id {
+                emit_unfulfilled_expectation_lint(tcx, *hir_id, expectation);
+            } else {
+                unreachable!("at this stage all `LintExpectationId`s are stable");
+            }
+        }
+    }
+}
+
+fn emit_unfulfilled_expectation_lint(
+    tcx: TyCtxt<'_>,
+    hir_id: HirId,
+    expectation: &LintExpectation,
+) {
+    // FIXME: The current implementation doesn't cover cases where the
+    // `unfulfilled_lint_expectations` is actually expected by another lint
+    // expectation. This can be added here by checking the lint level and
+    // retrieving the `LintExpectationId` if it was expected.
+    tcx.struct_span_lint_hir(
+        builtin::UNFULFILLED_LINT_EXPECTATIONS,
+        hir_id,
+        expectation.emission_span,
+        |diag| {
+            let mut diag = diag.build("this lint expectation is unfulfilled");
+            if let Some(rationale) = expectation.reason {
+                diag.note(&rationale.as_str());
+            }
+            diag.emit();
+        },
+    );
+}
index 0ce760b64d9ca0e889f01d8877421d0852fc4521..0ac636b878e0d0bb1ad90568f4b11ae8e4cac54b 100644 (file)
@@ -503,4 +503,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
             });
         },
     );
+
+    // This check has to be run after all lints are done processing for this crate
+    tcx.sess.time("check_lint_expectations", || crate::expect::check_expectations(tcx));
 }
index d7cdb08d81714c3cc940832ebd96a23784775e1c..bbfbf61f4869abefe4f17b0b76755001ddad8324 100644 (file)
@@ -7,17 +7,15 @@
 use rustc_hir as hir;
 use rustc_hir::{intravisit, HirId};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::lint::LevelAndSource;
-use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::lint::{
-    struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, LintStackIndex,
-    COMMAND_LINE,
+    struct_lint_level, LevelAndSource, LintDiagnosticBuilder, LintExpectation, LintLevelMap,
+    LintLevelSets, LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE,
 };
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{RegisteredTools, TyCtxt};
 use rustc_session::lint::{
     builtin::{self, FORBIDDEN_LINT_GROUPS},
-    Level, Lint, LintId,
+    Level, Lint, LintExpectationId, LintId,
 };
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
@@ -34,16 +32,23 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
 
     builder.levels.id_to_set.reserve(krate.owners.len() + 1);
 
-    let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), true);
+    let push =
+        builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), true, Some(hir::CRATE_HIR_ID));
+
     builder.levels.register_id(hir::CRATE_HIR_ID);
     tcx.hir().walk_toplevel_module(&mut builder);
     builder.levels.pop(push);
 
+    builder.levels.update_unstable_expectation_ids();
     builder.levels.build_map()
 }
 
 pub struct LintLevelsBuilder<'s> {
     sess: &'s Session,
+    lint_expectations: Vec<(LintExpectationId, LintExpectation)>,
+    /// Each expectation has a stable and an unstable identifier. This map
+    /// is used to map from unstable to stable [`LintExpectationId`]s.
+    expectation_id_map: FxHashMap<LintExpectationId, LintExpectationId>,
     sets: LintLevelSets,
     id_to_set: FxHashMap<HirId, LintStackIndex>,
     cur: LintStackIndex,
@@ -66,6 +71,8 @@ pub fn new(
     ) -> Self {
         let mut builder = LintLevelsBuilder {
             sess,
+            lint_expectations: Default::default(),
+            expectation_id_map: Default::default(),
             sets: LintLevelSets::new(),
             cur: COMMAND_LINE,
             id_to_set: Default::default(),
@@ -226,13 +233,24 @@ fn insert_spec(
     ///   `#[allow]`
     ///
     /// Don't forget to call `pop`!
-    pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) -> BuilderPush {
+    pub(crate) fn push(
+        &mut self,
+        attrs: &[ast::Attribute],
+        is_crate_node: bool,
+        source_hir_id: Option<HirId>,
+    ) -> BuilderPush {
         let mut specs = FxHashMap::default();
         let sess = self.sess;
         let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
-        for attr in attrs {
-            let Some(level) = Level::from_symbol(attr.name_or_empty()) else {
-                continue
+        for (attr_index, attr) in attrs.iter().enumerate() {
+            let level = match Level::from_attr(attr) {
+                None => continue,
+                Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => {
+                    let stable_id = self.create_stable_id(unstable_id, hir_id, attr_index);
+
+                    Level::Expect(stable_id)
+                }
+                Some(lvl) => lvl,
             };
 
             let Some(mut metas) = attr.meta_item_list() else {
@@ -240,7 +258,7 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
             };
 
             if metas.is_empty() {
-                // FIXME (#55112): issue unused-attributes lint for `#[level()]`
+                // This emits the unused_attributes lint for `#[level()]`
                 continue;
             }
 
@@ -253,8 +271,6 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
                     ast::MetaItemKind::Word => {} // actual lint names handled later
                     ast::MetaItemKind::NameValue(ref name_value) => {
                         if item.path == sym::reason {
-                            // FIXME (#55112): issue unused-attributes lint if we thereby
-                            // don't have any lint names (`#[level(reason = "foo")]`)
                             if let ast::LitKind::Str(rationale, _) = name_value.kind {
                                 if !self.sess.features_untracked().lint_reasons {
                                     feature_err(
@@ -285,9 +301,17 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
                 }
             }
 
-            for li in metas {
+            for (lint_index, li) in metas.iter_mut().enumerate() {
+                let level = match level {
+                    Level::Expect(mut id) => {
+                        id.set_lint_index(Some(lint_index as u16));
+                        Level::Expect(id)
+                    }
+                    level => level,
+                };
+
                 let sp = li.span();
-                let mut meta_item = match li {
+                let meta_item = match li {
                     ast::NestedMetaItem::MetaItem(meta_item) if meta_item.is_word() => meta_item,
                     _ => {
                         let mut err = bad_attr(sp);
@@ -327,6 +351,10 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
                             self.check_gated_lint(id, attr.span);
                             self.insert_spec(&mut specs, id, (level, src));
                         }
+                        if let Level::Expect(expect_id) = level {
+                            self.lint_expectations
+                                .push((expect_id, LintExpectation::new(reason, sp)));
+                        }
                     }
 
                     CheckLintNameResult::Tool(result) => {
@@ -342,6 +370,10 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
                                 for id in ids {
                                     self.insert_spec(&mut specs, *id, (level, src));
                                 }
+                                if let Level::Expect(expect_id) = level {
+                                    self.lint_expectations
+                                        .push((expect_id, LintExpectation::new(reason, sp)));
+                                }
                             }
                             Err((Some(ids), ref new_lint_name)) => {
                                 let lint = builtin::RENAMED_AND_REMOVED_LINTS;
@@ -378,6 +410,10 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
                                 for id in ids {
                                     self.insert_spec(&mut specs, *id, (level, src));
                                 }
+                                if let Level::Expect(expect_id) = level {
+                                    self.lint_expectations
+                                        .push((expect_id, LintExpectation::new(reason, sp)));
+                                }
                             }
                             Err((None, _)) => {
                                 // If Tool(Err(None, _)) is returned, then either the lint does not
@@ -471,6 +507,10 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
                             self.check_gated_lint(id, attr.span);
                             self.insert_spec(&mut specs, id, (level, src));
                         }
+                        if let Level::Expect(expect_id) = level {
+                            self.lint_expectations
+                                .push((expect_id, LintExpectation::new(reason, sp)));
+                        }
                     } else {
                         panic!("renamed lint does not exist: {}", new_name);
                     }
@@ -519,6 +559,20 @@ pub(crate) fn push(&mut self, attrs: &[ast::Attribute], is_crate_node: bool) ->
         BuilderPush { prev, changed: prev != self.cur }
     }
 
+    fn create_stable_id(
+        &mut self,
+        unstable_id: LintExpectationId,
+        hir_id: HirId,
+        attr_index: usize,
+    ) -> LintExpectationId {
+        let stable_id =
+            LintExpectationId::Stable { hir_id, attr_index: attr_index as u16, lint_index: None };
+
+        self.expectation_id_map.insert(unstable_id, stable_id);
+
+        stable_id
+    }
+
     /// Checks if the lint is gated on a feature that is not enabled.
     fn check_gated_lint(&self, lint_id: LintId, span: Span) {
         if let Some(feature) = lint_id.lint.feature_gate {
@@ -562,8 +616,16 @@ pub fn register_id(&mut self, id: HirId) {
         self.id_to_set.insert(id, self.cur);
     }
 
+    fn update_unstable_expectation_ids(&self) {
+        self.sess.diagnostic().update_unstable_expectation_id(&self.expectation_id_map);
+    }
+
     pub fn build_map(self) -> LintLevelMap {
-        LintLevelMap { sets: self.sets, id_to_set: self.id_to_set }
+        LintLevelMap {
+            sets: self.sets,
+            id_to_set: self.id_to_set,
+            lint_expectations: self.lint_expectations,
+        }
     }
 }
 
@@ -579,7 +641,8 @@ fn with_lint_attrs<F>(&mut self, id: hir::HirId, f: F)
     {
         let is_crate_hir = id == hir::CRATE_HIR_ID;
         let attrs = self.tcx.hir().attrs(id);
-        let push = self.levels.push(attrs, is_crate_hir);
+        let push = self.levels.push(attrs, is_crate_hir, Some(id));
+
         if push.changed {
             self.levels.register_id(id);
         }
index 72e1671449f1ce4223363b6e8f404c96bdccee79..18f229564c2a3818a8739f4a7c8637544054fd31 100644 (file)
@@ -51,6 +51,7 @@
 mod context;
 mod early;
 mod enum_intrinsics_non_enums;
+mod expect;
 pub mod hidden_unicode_codepoints;
 mod internal;
 mod late;
index c0bf64387ff376ab77bad579e4802c70bcc7779e..d4dac640cc7e189d71de027375b15d318f2c8516 100644 (file)
@@ -795,7 +795,9 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
         let field_ty_abi = &cx.layout_of(field_ty).unwrap().abi;
         if let Abi::Scalar(field_ty_scalar) = field_ty_abi {
             match (field_ty_scalar.valid_range.start, field_ty_scalar.valid_range.end) {
-                (0, _) => unreachable!("Non-null optimisation extended to a non-zero value."),
+                (0, x) if x == field_ty_scalar.value.size(&cx.tcx).unsigned_int_max() - 1 => {
+                    return Some(get_nullable_type(cx, field_ty).unwrap());
+                }
                 (1, _) => {
                     return Some(get_nullable_type(cx, field_ty).unwrap());
                 }
@@ -1349,7 +1351,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
             let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants)
                 .map(|(variant, variant_layout)| {
                     // Subtract the size of the enum tag.
-                    let bytes = variant_layout.size.bytes().saturating_sub(tag_size);
+                    let bytes = variant_layout.size().bytes().saturating_sub(tag_size);
 
                     debug!("- variant `{}` is {} bytes large", variant.ident, bytes);
                     bytes
index 798d50819e2d8b8449c5a74c10e9e9e97aee2bd5..8acf7943de9cf06b399124c0678ab76423734e58 100644 (file)
@@ -10,3 +10,4 @@ rustc_span = { path = "../rustc_span" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_target = { path = "../rustc_target" }
+rustc_hir = { path = "../rustc_hir" }
index adec1a3ab00d6c0e89805232dc89ff13f842f8ab..04a339f3c95a608f81fa3b53b8d75e17e35a8049 100644 (file)
     "unrecognized lint attribute"
 }
 
+declare_lint! {
+    /// The `unfulfilled_lint_expectations` lint detects lint trigger expectations
+    /// that have not been fulfilled.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(lint_reasons)]
+    ///
+    /// #[expect(unused_variables)]
+    /// let x = 10;
+    /// println!("{}", x);
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// It was expected that the marked code would emit a lint. This expectation
+    /// has not been fulfilled.
+    ///
+    /// The `expect` attribute can be removed if this is intended behavior otherwise
+    /// it should be investigated why the expected lint is no longer issued.
+    ///
+    /// Part of RFC 2383. The progress is being tracked in [#54503]
+    ///
+    /// [#54503]: https://github.com/rust-lang/rust/issues/54503
+    pub UNFULFILLED_LINT_EXPECTATIONS,
+    Warn,
+    "unfulfilled lint expectation",
+    @feature_gate = rustc_span::sym::lint_reasons;
+}
+
 declare_lint! {
     /// The `unused_variables` lint detects variables which are not used in
     /// any way.
         UNUSED_CRATE_DEPENDENCIES,
         UNUSED_QUALIFICATIONS,
         UNKNOWN_LINTS,
+        UNFULFILLED_LINT_EXPECTATIONS,
         UNUSED_VARIABLES,
         UNUSED_ASSIGNMENTS,
         DEAD_CODE,
         DUPLICATE_MACRO_ATTRIBUTES,
         SUSPICIOUS_AUTO_TRAIT_IMPLS,
         UNEXPECTED_CFGS,
+        DEPRECATED_WHERE_CLAUSE_LOCATION,
     ]
 }
 
         reference: "issue #93367 <https://github.com/rust-lang/rust/issues/93367>",
     };
 }
+
+declare_lint! {
+    /// The `deprecated_where_clause_location` lint detects when a where clause in front of the equals
+    /// in an associated type.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(generic_associated_types)]
+    ///
+    /// trait Trait {
+    ///   type Assoc<'a> where Self: 'a;
+    /// }
+    ///
+    /// impl Trait for () {
+    ///   type Assoc<'a> where Self: 'a = ();
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The preferred location for where clauses on associated types in impls
+    /// is after the type. However, for most of generic associated types development,
+    /// it was only accepted before the equals. To provide a transition period and
+    /// further evaluate this change, both are currently accepted. At some point in
+    /// the future, this may be disallowed at an edition boundary; but, that is
+    /// undecided currently.
+    pub DEPRECATED_WHERE_CLAUSE_LOCATION,
+    Warn,
+    "deprecated where clause location"
+}
index e9c62fc40065158ee61d38e29eec72663a17a6f5..cd328b087358cc4a8789fb55398c4b711803e78b 100644 (file)
@@ -1,9 +1,13 @@
+#![feature(min_specialization)]
+
 #[macro_use]
 extern crate rustc_macros;
 
 pub use self::Level::*;
 use rustc_ast::node_id::{NodeId, NodeMap};
+use rustc_ast::{AttrId, Attribute};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_hir::HirId;
 use rustc_serialize::json::Json;
 use rustc_span::edition::Edition;
 use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
@@ -46,13 +50,119 @@ pub enum Applicability {
     Unspecified,
 }
 
+/// Each lint expectation has a `LintExpectationId` assigned by the `LintLevelsBuilder`.
+/// Expected `Diagnostic`s get the lint level `Expect` which stores the `LintExpectationId`
+/// to match it with the actual expectation later on.
+///
+/// The `LintExpectationId` has to be has stable between compilations, as diagnostic
+/// instances might be loaded from cache. Lint messages can be emitted during an
+/// `EarlyLintPass` operating on the AST and during a `LateLintPass` traversing the
+/// HIR tree. The AST doesn't have enough information to create a stable id. The
+/// `LintExpectationId` will instead store the [`AttrId`] defining the expectation.
+/// These `LintExpectationId` will be updated to use the stable [`HirId`] once the
+/// AST has been lowered. The transformation is done by the `LintLevelsBuilder`
+///
+/// Each lint inside the `expect` attribute is tracked individually, the `lint_index`
+/// identifies the lint inside the attribute and ensures that the IDs are unique.
+///
+/// The index values have a type of `u16` to reduce the size of the `LintExpectationId`.
+/// It's reasonable to assume that no user will define 2^16 attributes on one node or
+/// have that amount of lints listed. `u16` values should therefore suffice.
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, Encodable, Decodable)]
+pub enum LintExpectationId {
+    /// Used for lints emitted during the `EarlyLintPass`. This id is not
+    /// has stable and should not be cached.
+    Unstable { attr_id: AttrId, lint_index: Option<u16> },
+    /// The [`HirId`] that the lint expectation is attached to. This id is
+    /// stable and can be cached. The additional index ensures that nodes with
+    /// several expectations can correctly match diagnostics to the individual
+    /// expectation.
+    Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16> },
+}
+
+impl LintExpectationId {
+    pub fn is_stable(&self) -> bool {
+        match self {
+            LintExpectationId::Unstable { .. } => false,
+            LintExpectationId::Stable { .. } => true,
+        }
+    }
+
+    pub fn get_lint_index(&self) -> Option<u16> {
+        let (LintExpectationId::Unstable { lint_index, .. }
+        | LintExpectationId::Stable { lint_index, .. }) = self;
+
+        *lint_index
+    }
+
+    pub fn set_lint_index(&mut self, new_lint_index: Option<u16>) {
+        let (LintExpectationId::Unstable { ref mut lint_index, .. }
+        | LintExpectationId::Stable { ref mut lint_index, .. }) = self;
+
+        *lint_index = new_lint_index
+    }
+}
+
+impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
+        match self {
+            LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
+                hir_id.hash_stable(hcx, hasher);
+                attr_index.hash_stable(hcx, hasher);
+                lint_index.hash_stable(hcx, hasher);
+            }
+            _ => {
+                unreachable!("HashStable should only be called for a filled `LintExpectationId`")
+            }
+        }
+    }
+}
+
+impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectationId {
+    type KeyType = (HirId, u16, u16);
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
+        match self {
+            LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
+                (*hir_id, *attr_index, *lint_index)
+            }
+            _ => {
+                unreachable!("HashStable should only be called for a filled `LintExpectationId`")
+            }
+        }
+    }
+}
+
 /// Setting for how to handle a lint.
+///
+/// See: <https://doc.rust-lang.org/rustc/lints/levels.html>
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
 pub enum Level {
+    /// The `allow` level will not issue any message.
     Allow,
+    /// The `expect` level will suppress the lint message but in turn produce a message
+    /// if the lint wasn't issued in the expected scope. `Expect` should not be used as
+    /// an initial level for a lint.
+    ///
+    /// Note that this still means that the lint is enabled in this position and should
+    /// be emitted, this will in turn fulfill the expectation and suppress the lint.
+    ///
+    /// See RFC 2383.
+    ///
+    /// The `LintExpectationId` is used to later link a lint emission to the actual
+    /// expectation. It can be ignored in most cases.
+    Expect(LintExpectationId),
+    /// The `warn` level will produce a warning if the lint was violated, however the
+    /// compiler will continue with its execution.
     Warn,
     ForceWarn,
+    /// The `deny` level will produce an error and stop further execution after the lint
+    /// pass is complete.
     Deny,
+    /// `Forbid` is equivalent to the `deny` level but can't be overwritten like the previous
+    /// levels.
     Forbid,
 }
 
@@ -63,6 +173,7 @@ impl Level {
     pub fn as_str(self) -> &'static str {
         match self {
             Level::Allow => "allow",
+            Level::Expect(_) => "expect",
             Level::Warn => "warn",
             Level::ForceWarn => "force-warn",
             Level::Deny => "deny",
@@ -70,21 +181,26 @@ pub fn as_str(self) -> &'static str {
         }
     }
 
-    /// Converts a lower-case string to a level.
+    /// Converts a lower-case string to a level. This will never construct the expect
+    /// level as that would require a [`LintExpectationId`]
     pub fn from_str(x: &str) -> Option<Level> {
         match x {
             "allow" => Some(Level::Allow),
             "warn" => Some(Level::Warn),
             "deny" => Some(Level::Deny),
             "forbid" => Some(Level::Forbid),
-            _ => None,
+            "expect" | _ => None,
         }
     }
 
     /// Converts a symbol to a level.
-    pub fn from_symbol(x: Symbol) -> Option<Level> {
-        match x {
+    pub fn from_attr(attr: &Attribute) -> Option<Level> {
+        match attr.name_or_empty() {
             sym::allow => Some(Level::Allow),
+            sym::expect => Some(Level::Expect(LintExpectationId::Unstable {
+                attr_id: attr.id,
+                lint_index: None,
+            })),
             sym::warn => Some(Level::Warn),
             sym::deny => Some(Level::Deny),
             sym::forbid => Some(Level::Forbid),
@@ -310,7 +426,8 @@ pub enum BuiltinLintDiagnostics {
     BreakWithLabelAndLoop(Span),
     NamedAsmLabel(String),
     UnicodeTextFlow(Span, String),
-    UnexpectedCfg(Span, Symbol, Option<Symbol>),
+    UnexpectedCfg((Symbol, Span), Option<(Symbol, Span)>),
+    DeprecatedWhereclauseLocation(Span, String),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
index d8dfcc84e68da444575638816b3ae1ba5a104718..34556df3c6d79e67e5004afbfdba234751caca68 100644 (file)
@@ -11,5 +11,4 @@ emscripten = []
 libc = "0.2.73"
 
 [build-dependencies]
-build_helper = { path = "../../src/build_helper" }
 cc = "1.0.69"
index 3b6808d693f2176bfa8a8b48194face0ededc109..ac758c15cca7875fce627f5f92879c881d258307 100644 (file)
@@ -1,8 +1,8 @@
 use std::env;
+use std::ffi::{OsStr, OsString};
+use std::fmt::Display;
 use std::path::{Path, PathBuf};
-use std::process::Command;
-
-use build_helper::{output, tracked_env_var_os};
+use std::process::{Command, Stdio};
 
 fn detect_llvm_link() -> (&'static str, &'static str) {
     // Force the link mode we want, preferring static by default, but
@@ -14,13 +14,74 @@ fn detect_llvm_link() -> (&'static str, &'static str) {
     }
 }
 
+// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
+// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
+// shared library, which means that when our freshly built llvm-config goes to load it's
+// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
+// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
+// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
+// perfect -- we might actually want to see something from Cargo's added library paths -- but
+// for now it works.
+fn restore_library_path() {
+    let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
+    if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") {
+        env::set_var(&key, &env);
+    } else {
+        env::remove_var(&key);
+    }
+}
+
+/// Reads an environment variable and adds it to dependencies.
+/// Supposed to be used for all variables except those set for build scripts by cargo
+/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
+fn tracked_env_var_os<K: AsRef<OsStr> + Display>(key: K) -> Option<OsString> {
+    println!("cargo:rerun-if-env-changed={}", key);
+    env::var_os(key)
+}
+
+fn rerun_if_changed_anything_in_dir(dir: &Path) {
+    let mut stack = dir
+        .read_dir()
+        .unwrap()
+        .map(|e| e.unwrap())
+        .filter(|e| &*e.file_name() != ".git")
+        .collect::<Vec<_>>();
+    while let Some(entry) = stack.pop() {
+        let path = entry.path();
+        if entry.file_type().unwrap().is_dir() {
+            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
+        } else {
+            println!("cargo:rerun-if-changed={}", path.display());
+        }
+    }
+}
+
+#[track_caller]
+fn output(cmd: &mut Command) -> String {
+    let output = match cmd.stderr(Stdio::inherit()).output() {
+        Ok(status) => status,
+        Err(e) => {
+            println!("\n\nfailed to execute command: {:?}\nerror: {}\n\n", cmd, e);
+            std::process::exit(1);
+        }
+    };
+    if !output.status.success() {
+        panic!(
+            "command did not execute successfully: {:?}\n\
+             expected success, got: {}",
+            cmd, output.status
+        );
+    }
+    String::from_utf8(output.stdout).unwrap()
+}
+
 fn main() {
     if tracked_env_var_os("RUST_CHECK").is_some() {
         // If we're just running `check`, there's no need for LLVM to be built.
         return;
     }
 
-    build_helper::restore_library_path();
+    restore_library_path();
 
     let target = env::var("TARGET").expect("TARGET was not set");
     let llvm_config =
@@ -160,7 +221,7 @@ fn main() {
         cfg.debug(false);
     }
 
-    build_helper::rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper"));
+    rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper"));
     cfg.file("llvm-wrapper/PassWrapper.cpp")
         .file("llvm-wrapper/RustWrapper.cpp")
         .file("llvm-wrapper/ArchiveWrapper.cpp")
index 919fe7cac5ce315aa775ce5632ec697e1439ea01..ef6c9ef6627d5beb3c2af7d11aa75ac6b767a4d6 100644 (file)
@@ -267,12 +267,6 @@ extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
   return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
 }
 
-extern "C" LLVMAttributeRef LLVMRustCreateAttrStringValue(LLVMContextRef C,
-                                                          const char *Name,
-                                                          const char *Value) {
-  return wrap(Attribute::get(*unwrap(C), StringRef(Name), StringRef(Value)));
-}
-
 extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
                                                         uint64_t Bytes) {
   return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
index f284e5cdd5c1e1be7e773f4adbd288e5a3c5428b..f5968a8a7ea73ce15c9b7f1ffb0c1a42c0b98019 100644 (file)
@@ -10,6 +10,7 @@ mod kw {
     syn::custom_keyword!(MAX);
     syn::custom_keyword!(ENCODABLE);
     syn::custom_keyword!(custom);
+    syn::custom_keyword!(ORD_IMPL);
 }
 
 #[derive(Debug)]
@@ -42,6 +43,7 @@ fn parse(input: ParseStream<'_>) -> Result<Self> {
         let mut max = None;
         let mut consts = Vec::new();
         let mut encodable = true;
+        let mut ord = true;
 
         // Parse an optional trailing comma
         let try_comma = || -> Result<()> {
@@ -99,13 +101,20 @@ fn parse(input: ParseStream<'_>) -> Result<Self> {
                     encodable = false;
                     continue;
                 }
+                if body.lookahead1().peek(kw::ORD_IMPL) {
+                    body.parse::<kw::ORD_IMPL>()?;
+                    body.parse::<Token![=]>()?;
+                    body.parse::<kw::custom>()?;
+                    ord = false;
+                    continue;
+                }
 
                 // We've parsed everything that the user provided, so we're done
                 if body.is_empty() {
                     break;
                 }
 
-                // Otherwise, we are parsng a user-defined constant
+                // Otherwise, we are parsing a user-defined constant
                 let const_attrs = body.call(Attribute::parse_outer)?;
                 body.parse::<Token![const]>()?;
                 let const_name: Ident = body.parse()?;
@@ -137,6 +146,40 @@ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
             quote! {}
         };
 
+        if ord {
+            derive_paths.push(parse_quote!(Ord));
+            derive_paths.push(parse_quote!(PartialOrd));
+        }
+
+        let step = if ord {
+            quote! {
+                impl ::std::iter::Step for #name {
+                    #[inline]
+                    fn steps_between(start: &Self, end: &Self) -> Option<usize> {
+                        <usize as ::std::iter::Step>::steps_between(
+                            &Self::index(*start),
+                            &Self::index(*end),
+                        )
+                    }
+
+                    #[inline]
+                    fn forward_checked(start: Self, u: usize) -> Option<Self> {
+                        Self::index(start).checked_add(u).map(Self::from_usize)
+                    }
+
+                    #[inline]
+                    fn backward_checked(start: Self, u: usize) -> Option<Self> {
+                        Self::index(start).checked_sub(u).map(Self::from_usize)
+                    }
+                }
+
+                // Safety: The implementation of `Step` upholds all invariants.
+                unsafe impl ::std::iter::TrustedStep for #name {}
+            }
+        } else {
+            quote! {}
+        };
+
         let debug_impl = match debug_format {
             DebugFormat::Custom => quote! {},
             DebugFormat::Format(format) => {
@@ -152,7 +195,7 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
 
         Ok(Self(quote! {
             #(#attrs)*
-            #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, #(#derive_paths),*)]
+            #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)]
             #[rustc_layout_scalar_valid_range_end(#max)]
             #vis struct #name {
                 private: u32,
@@ -247,28 +290,7 @@ fn index(self) -> usize {
                 }
             }
 
-            impl ::std::iter::Step for #name {
-                #[inline]
-                fn steps_between(start: &Self, end: &Self) -> Option<usize> {
-                    <usize as ::std::iter::Step>::steps_between(
-                        &Self::index(*start),
-                        &Self::index(*end),
-                    )
-                }
-
-                #[inline]
-                fn forward_checked(start: Self, u: usize) -> Option<Self> {
-                    Self::index(start).checked_add(u).map(Self::from_usize)
-                }
-
-                #[inline]
-                fn backward_checked(start: Self, u: usize) -> Option<Self> {
-                    Self::index(start).checked_sub(u).map(Self::from_usize)
-                }
-            }
-
-            // Safety: The implementation of `Step` upholds all invariants.
-            unsafe impl ::std::iter::TrustedStep for #name {}
+            #step
 
             impl From<#name> for u32 {
                 #[inline]
index 7cdcb6a4ab302604c30cb4fb95c1f1937cc56610..f4bc28f4da19914ee396fcb465356c030160e3da 100644 (file)
@@ -392,7 +392,7 @@ fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
                     .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
+                (layout.size().bytes_usize() + 3) & !3
             })
             .sum()
     }
index c3e168c47272965fdbed44f30d7ee5fb57080696..06f73c1c91600d4a955e39c5331dc4190b3efcce 100644 (file)
@@ -26,7 +26,7 @@
 use rustc_middle::thir;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
-use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams};
+use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_serialize::{opaque, Encodable, Encoder};
@@ -2043,7 +2043,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     let simplified_self_ty = fast_reject::simplify_type(
                         self.tcx,
                         trait_ref.self_ty(),
-                        SimplifyParams::No,
+                        TreatParams::AsPlaceholders,
                     );
 
                     self.impls
index c4e6734aa0fa71efa23fc2c361a991e462889b35..825dc79129d267a2eb7342432c112106c8d85360 100644 (file)
@@ -6,7 +6,7 @@
 macro_rules! arena_types {
     ($macro:path) => (
         $macro!([
-            [] layout: rustc_target::abi::Layout,
+            [] layout: rustc_target::abi::LayoutS<'tcx>,
             [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
             // AdtDef are interned and compared by address
             [decode] adt_def: rustc_middle::ty::AdtDef,
index 35e1558600d5b3fc2b76f37601fea1aacf6d2737..894947fa70d969506628d27370b25b6fbdcb0745 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::{
     builtin::{self, FORBIDDEN_LINT_GROUPS},
-    FutureIncompatibilityReason, Level, Lint, LintId,
+    FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId,
 };
 use rustc_session::{DiagnosticMessageId, Session};
 use rustc_span::hygiene::MacroKind;
@@ -153,6 +153,13 @@ pub fn get_lint_id_level(
 
 #[derive(Debug)]
 pub struct LintLevelMap {
+    /// This is a collection of lint expectations as described in RFC 2383, that
+    /// can be fulfilled during this compilation session. This means that at least
+    /// one expected lint is currently registered in the lint store.
+    ///
+    /// The [`LintExpectationId`] is stored as a part of the [`Expect`](Level::Expect)
+    /// lint level.
+    pub lint_expectations: Vec<(LintExpectationId, LintExpectation)>,
     pub sets: LintLevelSets,
     pub id_to_set: FxHashMap<HirId, LintStackIndex>,
 }
@@ -178,14 +185,33 @@ pub fn level_and_source(
 impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
     #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let LintLevelMap { ref sets, ref id_to_set } = *self;
+        let LintLevelMap { ref sets, ref id_to_set, ref lint_expectations } = *self;
 
         id_to_set.hash_stable(hcx, hasher);
+        lint_expectations.hash_stable(hcx, hasher);
 
         hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher))
     }
 }
 
+/// This struct represents a lint expectation and holds all required information
+/// to emit the `unfulfilled_lint_expectations` lint if it is unfulfilled after
+/// the `LateLintPass` has completed.
+#[derive(Clone, Debug, HashStable)]
+pub struct LintExpectation {
+    /// The reason for this expectation that can optionally be added as part of
+    /// the attribute. It will be displayed as part of the lint message.
+    pub reason: Option<Symbol>,
+    /// The [`Span`] of the attribute that this expectation originated from.
+    pub emission_span: Span,
+}
+
+impl LintExpectation {
+    pub fn new(reason: Option<Symbol>, attr_span: Span) -> Self {
+        Self { reason, emission_span: attr_span }
+    }
+}
+
 pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a, ()>);
 
 impl<'a> LintDiagnosticBuilder<'a> {
@@ -225,6 +251,9 @@ pub fn explain_lint_level_source(
                 Level::Forbid => "-F",
                 Level::Allow => "-A",
                 Level::ForceWarn => "--force-warn",
+                Level::Expect(_) => {
+                    unreachable!("the expect level does not have a commandline flag")
+                }
             };
             let hyphen_case_lint_name = name.replace('_', "-");
             if lint_flag_val.as_str() == name {
@@ -314,6 +343,16 @@ fn struct_lint_level_impl<'s, 'd>(
                     return;
                 }
             }
+            (Level::Expect(expect_id), _) => {
+                // This case is special as we actually allow the lint itself in this context, but
+                // we can't return early like in the case for `Level::Allow` because we still
+                // need the lint diagnostic to be emitted to `rustc_error::HanderInner`.
+                //
+                // We can also not mark the lint expectation as fulfilled here right away, as it
+                // can still be cancelled in the decorate function. All of this means that we simply
+                // create a `DiagnosticBuilder` and continue as we would for warnings.
+                sess.struct_expect("", expect_id)
+            }
             (Level::Warn | Level::ForceWarn, Some(span)) => sess.struct_span_warn(span, ""),
             (Level::Warn | Level::ForceWarn, None) => sess.struct_warn(""),
             (Level::Deny | Level::Forbid, Some(span)) => {
@@ -346,6 +385,17 @@ fn struct_lint_level_impl<'s, 'd>(
             }
         }
 
+        // Lint diagnostics that are covered by the expect level will not be emitted outside
+        // the compiler. It is therefore not necessary to add any information for the user.
+        // This will therefore directly call the decorate function which will in turn emit
+        // the `Diagnostic`.
+        if let Level::Expect(_) = level {
+            let name = lint.name_lower();
+            err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false });
+            decorate(LintDiagnosticBuilder::new(err));
+            return;
+        }
+
         explain_lint_level_source(sess, lint, level, src, &mut err);
 
         let name = lint.name_lower();
index ff19c33d8e8e1784de156268921c5823ad3ec803..167a097d9f8523b90d720e70b4eb1a803eb52598 100644 (file)
@@ -6,12 +6,12 @@
 use crate::ty::{self, DefIdTree, TyCtxt};
 use rustc_ast::NodeId;
 use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::{self, HirId};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
@@ -63,12 +63,6 @@ pub struct Index {
     pub stab_map: FxHashMap<LocalDefId, Stability>,
     pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
     pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
-
-    /// Maps for each crate whether it is part of the staged API.
-    pub staged_api: FxHashMap<CrateNum, bool>,
-
-    /// Features enabled for this crate.
-    pub active_features: FxHashSet<Symbol>,
 }
 
 impl Index {
@@ -423,7 +417,7 @@ pub fn eval_stability(
                     debug!("stability: skipping span={:?} since it is internal", span);
                     return EvalResult::Allow;
                 }
-                if self.stability().active_features.contains(&feature) {
+                if self.features().active(feature) {
                     return EvalResult::Allow;
                 }
 
index 5de119f956282b51448f6bda0135825b1517c9b1..17ff52cefcfa8f9ee4533de1822f075a3a422014 100644 (file)
@@ -2,11 +2,13 @@
 
 use std::borrow::Cow;
 use std::convert::{TryFrom, TryInto};
+use std::fmt;
 use std::iter;
 use std::ops::{Deref, Range};
 use std::ptr;
 
 use rustc_ast::Mutability;
+use rustc_data_structures::intern::Interned;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::{Align, HasDataLayout, Size};
@@ -47,6 +49,34 @@ pub struct Allocation<Tag = AllocId, Extra = ()> {
     pub extra: Extra,
 }
 
+/// Interned types generally have an `Outer` type and an `Inner` type, where
+/// `Outer` is a newtype around `Interned<Inner>`, and all the operations are
+/// done on `Outer`, because all occurrences are interned. E.g. `Ty` is an
+/// outer type and `TyS` is its inner type.
+///
+/// Here things are different because only const allocations are interned. This
+/// means that both the inner type (`Allocation`) and the outer type
+/// (`ConstAllocation`) are used quite a bit.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
+#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
+pub struct ConstAllocation<'tcx, Tag = AllocId, Extra = ()>(
+    pub Interned<'tcx, Allocation<Tag, Extra>>,
+);
+
+impl<'tcx> fmt::Debug for ConstAllocation<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This matches how `Allocation` is printed. We print it like this to
+        // avoid having to update expected output in a lot of tests.
+        write!(f, "{:?}", self.inner())
+    }
+}
+
+impl<'tcx, Tag, Extra> ConstAllocation<'tcx, Tag, Extra> {
+    pub fn inner(self) -> &'tcx Allocation<Tag, Extra> {
+        self.0.0
+    }
+}
+
 /// We have our own error type that does not know about the `AllocId`; that information
 /// is added when converting to `InterpError`.
 #[derive(Debug)]
index 4eac0009f69e2e1893d6448942cb2bfa8d466442..bce962491b7b1c99c17b43139d2743c12d78ebe6 100644 (file)
@@ -126,7 +126,8 @@ macro_rules! throw_machine_stop {
 pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit};
 
 pub use self::allocation::{
-    alloc_range, AllocRange, Allocation, InitChunk, InitChunkIter, InitMask, Relocations,
+    alloc_range, AllocRange, Allocation, ConstAllocation, InitChunk, InitChunkIter, InitMask,
+    Relocations,
 };
 
 pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
@@ -343,7 +344,7 @@ pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> AllocId
         let alloc_id = decoder.with_position(pos, |decoder| {
             match alloc_kind {
                 AllocDiscriminant::Alloc => {
-                    let alloc = <&'tcx Allocation as Decodable<_>>::decode(decoder);
+                    let alloc = <ConstAllocation<'tcx> as Decodable<_>>::decode(decoder);
                     // We already have a reserved `AllocId`.
                     let alloc_id = alloc_id.unwrap();
                     trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc);
@@ -387,14 +388,14 @@ pub enum GlobalAlloc<'tcx> {
     /// This is also used to break the cycle in recursive statics.
     Static(DefId),
     /// The alloc ID points to memory.
-    Memory(&'tcx Allocation),
+    Memory(ConstAllocation<'tcx>),
 }
 
 impl<'tcx> GlobalAlloc<'tcx> {
     /// Panics if the `GlobalAlloc` does not refer to an `GlobalAlloc::Memory`
     #[track_caller]
     #[inline]
-    pub fn unwrap_memory(&self) -> &'tcx Allocation {
+    pub fn unwrap_memory(&self) -> ConstAllocation<'tcx> {
         match *self {
             GlobalAlloc::Memory(mem) => mem,
             _ => bug!("expected memory, got {:?}", self),
@@ -512,7 +513,7 @@ pub fn create_fn_alloc(self, instance: Instance<'tcx>) -> AllocId {
     /// Statics with identical content will still point to the same `Allocation`, i.e.,
     /// their data will be deduplicated through `Allocation` interning -- but they
     /// are different places in memory and as such need different IDs.
-    pub fn create_memory_alloc(self, mem: &'tcx Allocation) -> AllocId {
+    pub fn create_memory_alloc(self, mem: ConstAllocation<'tcx>) -> AllocId {
         let id = self.reserve_alloc_id();
         self.set_alloc_id_memory(id, mem);
         id
@@ -543,7 +544,7 @@ pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
 
     /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
     /// call this function twice, even with the same `Allocation` will ICE the compiler.
-    pub fn set_alloc_id_memory(self, id: AllocId, mem: &'tcx Allocation) {
+    pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
         if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
             bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old);
         }
@@ -551,7 +552,7 @@ pub fn set_alloc_id_memory(self, id: AllocId, mem: &'tcx Allocation) {
 
     /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
     /// twice for the same `(AllocId, Allocation)` pair.
-    fn set_alloc_id_same_memory(self, id: AllocId, mem: &'tcx Allocation) {
+    fn set_alloc_id_same_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
         self.alloc_map.lock().alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
     }
 }
index 4a57f483c70e2b8a1069263ca031f8271ca817a5..8b0f92d23d75fb72f0aed5f404192901667cb9f9 100644 (file)
@@ -79,7 +79,7 @@ pub fn const_eval_global_id(
     pub fn eval_static_initializer(
         self,
         def_id: DefId,
-    ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
+    ) -> Result<mir::ConstAllocation<'tcx>, ErrorHandled> {
         trace!("eval_static_initializer: Need to compute {:?}", def_id);
         assert!(self.is_static(def_id));
         let instance = ty::Instance::mono(self, def_id);
@@ -92,7 +92,7 @@ fn eval_to_allocation(
         self,
         gid: GlobalId<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-    ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
+    ) -> Result<mir::ConstAllocation<'tcx>, ErrorHandled> {
         let param_env = param_env.with_const();
         trace!("eval_to_allocation: Need to compute {:?}", gid);
         let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
index c8ddc4edc8adae51efb0b50e5858c7ad696ba8c5..8e32603a357026f9b4af0b6fa1d8eccea5f83df8 100644 (file)
@@ -11,7 +11,7 @@
 use crate::ty::{Lift, ParamEnv, ScalarInt, Ty, TyCtxt};
 
 use super::{
-    AllocId, AllocRange, Allocation, InterpResult, Pointer, PointerArithmetic, Provenance,
+    AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance,
 };
 
 /// Represents the result of const evaluation via the `eval_to_allocation` query.
@@ -34,13 +34,13 @@ pub enum ConstValue<'tcx> {
     Scalar(Scalar),
 
     /// Used only for `&[u8]` and `&str`
-    Slice { data: &'tcx Allocation, start: usize, end: usize },
+    Slice { data: ConstAllocation<'tcx>, start: usize, end: usize },
 
     /// A value not represented/representable by `Scalar` or `Slice`
     ByRef {
         /// The backing memory of the value, may contain more memory than needed for just the value
-        /// in order to share `Allocation`s between values
-        alloc: &'tcx Allocation,
+        /// in order to share `ConstAllocation`s between values
+        alloc: ConstAllocation<'tcx>,
         /// Offset into `alloc`
         offset: Size,
     },
@@ -603,11 +603,12 @@ pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64
 pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] {
     if let ConstValue::Slice { data, start, end } = val {
         let len = end - start;
-        data.get_bytes(
-            cx,
-            AllocRange { start: Size::from_bytes(start), size: Size::from_bytes(len) },
-        )
-        .unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
+        data.inner()
+            .get_bytes(
+                cx,
+                AllocRange { start: Size::from_bytes(start), size: Size::from_bytes(len) },
+            )
+            .unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
     } else {
         bug!("expected const slice, but found another const value");
     }
index ce3d6f348d194c09430219a3b8a5bef1132b0107..aa061232d7e3c90d55a24db5d43410e9e510e053 100644 (file)
@@ -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, ConstValue, GlobalAlloc, Scalar};
+use crate::mir::interpret::{ConstAllocation, ConstValue, GlobalAlloc, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -2534,7 +2534,7 @@ pub enum ConstantKind<'tcx> {
 
 impl<'tcx> Constant<'tcx> {
     pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
-        match self.literal.const_for_ty()?.val().try_to_scalar() {
+        match self.literal.try_to_scalar() {
             Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) {
                 GlobalAlloc::Static(def_id) => {
                     assert!(!tcx.is_thread_local_static(def_id));
index 6886a0f4cf1489bbb1e448b8385ba0218c705822..50d9c8e98b9b2e193deb22bb3a61078a89f833c9 100644 (file)
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{
-    read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, Provenance,
+    read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc, Pointer,
+    Provenance,
 };
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::MirSource;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitor};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::abi::Size;
-use std::ops::ControlFlow;
 
 const INDENT: &str = "    ";
 /// Alignment for lining up comments following MIR statements
@@ -652,12 +652,14 @@ pub fn write_allocations<'tcx>(
     body: &Body<'_>,
     w: &mut dyn Write,
 ) -> io::Result<()> {
-    fn alloc_ids_from_alloc(alloc: &Allocation) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
-        alloc.relocations().values().map(|id| *id)
+    fn alloc_ids_from_alloc(
+        alloc: ConstAllocation<'_>,
+    ) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
+        alloc.inner().relocations().values().map(|id| *id)
     }
     fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
         match val {
-            ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _size)) => {
+            ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
                 Either::Left(Either::Left(std::iter::once(ptr.provenance)))
             }
             ConstValue::Scalar(interpret::Scalar::Int { .. }) => {
@@ -669,16 +671,27 @@ fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> +
         }
     }
     struct CollectAllocIds(BTreeSet<AllocId>);
-    impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds {
-        fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+
+    impl<'tcx> Visitor<'tcx> for CollectAllocIds {
+        fn visit_const(&mut self, c: ty::Const<'tcx>, _loc: Location) {
             if let ty::ConstKind::Value(val) = c.val() {
                 self.0.extend(alloc_ids_from_const(val));
             }
-            c.super_visit_with(self)
+        }
+
+        fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) {
+            match c.literal {
+                ConstantKind::Ty(c) => self.visit_const(c, loc),
+                ConstantKind::Val(val, _) => {
+                    self.0.extend(alloc_ids_from_const(val));
+                }
+            }
         }
     }
+
     let mut visitor = CollectAllocIds(Default::default());
-    body.visit_with(&mut visitor);
+    visitor.visit_body(body);
+
     // `seen` contains all seen allocations, including the ones we have *not* printed yet.
     // The protocol is to first `insert` into `seen`, and only if that returns `true`
     // then push to `todo`.
@@ -686,14 +699,14 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
     let mut todo: Vec<_> = seen.iter().copied().collect();
     while let Some(id) = todo.pop() {
         let mut write_allocation_track_relocs =
-            |w: &mut dyn Write, alloc: &Allocation| -> io::Result<()> {
+            |w: &mut dyn Write, alloc: ConstAllocation<'tcx>| -> io::Result<()> {
                 // `.rev()` because we are popping them from the back of the `todo` vector.
                 for id in alloc_ids_from_alloc(alloc).rev() {
                     if seen.insert(id) {
                         todo.push(id);
                     }
                 }
-                write!(w, "{}", display_allocation(tcx, alloc))
+                write!(w, "{}", display_allocation(tcx, alloc.inner()))
             };
         write!(w, "\n{}", id)?;
         match tcx.get_global_alloc(id) {
index 40dce281c82bf2460c6885bfadde72160f236a5d..04bc0c8b52114dccded115a8b98fa0c9a1ac94f1 100644 (file)
@@ -17,6 +17,7 @@
 use rustc_index::vec::IndexVec;
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::middle::region;
+use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::{
     BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection,
 };
@@ -419,7 +420,8 @@ pub enum ExprKind<'tcx> {
     /// This is only distinguished from `Literal` so that we can register some
     /// info for diagnostics.
     StaticRef {
-        literal: Const<'tcx>,
+        alloc_id: AllocId,
+        ty: Ty<'tcx>,
         def_id: DefId,
     },
     /// Inline assembly, i.e. `asm!()`.
index 95489ac3ab2c64c8413680dd4764fa6ef794318e..1c472f38184eadca7faedd6b7c4899278ee24356 100644 (file)
@@ -123,7 +123,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
         }
         Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
         Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
-        StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
+        StaticRef { alloc_id: _, ty: _, def_id: _ } => {}
         InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
             for op in &**operands {
                 use InlineAsmOperand::*;
index 23fb7a49d9c8e923602a56e5f66a1e504aaf8b92..69455951c5794b8a97f1814ad52fa33396bbd844 100644 (file)
@@ -10,7 +10,7 @@
 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use crate::mir::{
     self,
-    interpret::{AllocId, Allocation},
+    interpret::{AllocId, ConstAllocation},
 };
 use crate::thir;
 use crate::traits;
@@ -150,6 +150,12 @@ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
     }
 }
 
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ConstAllocation<'tcx> {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        self.inner().encode(e)
+    }
+}
+
 impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
     fn encode(&self, e: &mut E) -> Result<(), E::Error> {
         e.encode_alloc_id(self)
@@ -355,8 +361,8 @@ fn decode(decoder: &mut D) -> &'tcx Self {
     }
 }
 
-impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for Allocation {
-    fn decode(decoder: &mut D) -> &'tcx Self {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
+    fn decode(decoder: &mut D) -> Self {
         decoder.tcx().intern_const_alloc(Decodable::decode(decoder))
     }
 }
@@ -399,7 +405,6 @@ fn decode(decoder: &mut D) -> &'tcx Self {
     &'tcx ty::List<Ty<'tcx>>,
     &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
     &'tcx traits::ImplSource<'tcx, ()>,
-    &'tcx Allocation,
     &'tcx mir::Body<'tcx>,
     &'tcx mir::UnsafetyCheckResult,
     &'tcx mir::BorrowCheckResult<'tcx>,
index d32276364e0f93fc8638215e9a782309d94d28d2..99dd4ab1bf5fd8e14d620c27f5b441fdfd97a3aa 100644 (file)
@@ -7,7 +7,7 @@
 use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
 use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath};
 use crate::middle::stability;
-use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
+use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
 use crate::mir::{
     Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
 };
@@ -56,7 +56,7 @@
 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};
+use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
 
 use rustc_type_ir::TypeFlags;
@@ -114,7 +114,7 @@ pub struct CtxtInterners<'tcx> {
     const_: InternedSet<'tcx, ConstS<'tcx>>,
     const_allocation: InternedSet<'tcx, Allocation>,
     bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
-    layout: InternedSet<'tcx, Layout>,
+    layout: InternedSet<'tcx, LayoutS<'tcx>>,
     adt_def: InternedSet<'tcx, AdtDef>,
 }
 
@@ -1653,22 +1653,6 @@ pub trait Lift<'tcx>: fmt::Debug {
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
 }
 
-// Deprecated: we are in the process of converting all uses to `nop_lift`.
-macro_rules! nop_lift_old {
-    ($set:ident; $ty:ty => $lifted:ty) => {
-        impl<'a, 'tcx> Lift<'tcx> for $ty {
-            type Lifted = $lifted;
-            fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-                if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) {
-                    Some(unsafe { mem::transmute(self) })
-                } else {
-                    None
-                }
-            }
-        }
-    };
-}
-
 macro_rules! nop_lift {
     ($set:ident; $ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
@@ -1726,7 +1710,7 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 nop_lift! {type_; Ty<'a> => Ty<'tcx>}
 nop_lift! {region; Region<'a> => Region<'tcx>}
 nop_lift! {const_; Const<'a> => Const<'tcx>}
-nop_lift_old! {const_allocation; &'a Allocation => &'tcx Allocation}
+nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
 nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
 
 nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>}
@@ -2161,6 +2145,8 @@ pub fn $method(self, v: $ty) -> $ret_ty {
 direct_interners! {
     region: mk_region(RegionKind): Region -> Region<'tcx>,
     const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>,
+    const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
+    layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>,
 }
 
 macro_rules! direct_interners_old {
@@ -2201,8 +2187,6 @@ pub fn $method(self, v: $ty) -> &'tcx $ty {
 
 // FIXME: eventually these should all be converted to `direct_interners`.
 direct_interners_old! {
-    const_allocation: intern_const_alloc(Allocation),
-    layout: intern_layout(Layout),
     adt_def: intern_adt_def(AdtDef),
 }
 
@@ -2755,7 +2739,7 @@ pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId
                 return bound;
             }
 
-            if hir.attrs(id).iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some()) {
+            if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
                 return id;
             }
             let next = hir.get_parent_node(id);
@@ -2999,11 +2983,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
     };
 
-    providers.lookup_stability = |tcx, id| tcx.stability().local_stability(id.expect_local());
-    providers.lookup_const_stability =
-        |tcx, id| tcx.stability().local_const_stability(id.expect_local());
-    providers.lookup_deprecation_entry =
-        |tcx, id| tcx.stability().local_deprecation_entry(id.expect_local());
     providers.extern_mod_stmt_cnum =
         |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
     providers.output_filenames = |tcx, ()| &tcx.output_filenames;
index 3c1ac66e2d136c7287a6130915042c225572315d..c0dd4db2945dc0f0c710b0449d08a3d215943fc8 100644 (file)
@@ -49,9 +49,14 @@ pub enum SimplifiedTypeGen<D>
 }
 
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
-pub enum SimplifyParams {
-    Yes,
-    No,
+pub enum TreatParams {
+    /// Treat parameters as bound types in the given environment.
+    ///
+    /// For this to be correct the input has to be fully normalized
+    /// in its param env as it may otherwise cause us to ignore
+    /// potentially applying impls.
+    AsBoundTypes,
+    AsPlaceholders,
 }
 
 /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
@@ -59,26 +64,21 @@ pub enum SimplifyParams {
 /// The idea is to get something simple that we can use to quickly decide if two types could unify,
 /// for example during method lookup.
 ///
-/// A special case here are parameters and projections. Projections can be normalized to
-/// a different type, meaning that `<T as Trait>::Assoc` and `u8` can be unified, even though
-/// their outermost layer is different while parameters like `T` of impls are later replaced
-/// with an inference variable, which then also allows unification with other types.
+/// A special case here are parameters and projections, which are only injective
+/// if they are treated as bound types.
 ///
-/// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections²,
-/// the reasoning for this can be seen at the places doing this.
+/// For example when storing impls based on their simplified self type, we treat
+/// generic parameters as placeholders. We must not simplify them here,
+/// as they can unify with any other type.
 ///
+/// With projections we have to be even more careful, as even when treating them as bound types
+/// this is still only correct if they are fully normalized.
 ///
-/// Â¹ meaning that if two outermost layers are different, then the whole types are also different.
-/// Â² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during
-///   candidate selection. We do not consider non blanket impls for `<_ as Trait>::Assoc` even
-///   though `_` can be inferred to a concrete type later at which point a concrete impl
-///   could actually apply. After experimenting for about an hour I wasn't able to cause any issues
-///   this way so I am not going to change this until we actually find an issue as I am really
-///   interesting in getting an actual test for this.
-pub fn simplify_type(
-    tcx: TyCtxt<'_>,
-    ty: Ty<'_>,
-    can_simplify_params: SimplifyParams,
+/// Â¹ meaning that if the outermost layers are different, then the whole types are also different.
+pub fn simplify_type<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    treat_params: TreatParams,
 ) -> Option<SimplifiedType> {
     match *ty.kind() {
         ty::Bool => Some(BoolSimplifiedType),
@@ -91,7 +91,7 @@ pub fn simplify_type(
         ty::Array(..) => Some(ArraySimplifiedType),
         ty::Slice(..) => Some(SliceSimplifiedType),
         ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)),
-        ty::Dynamic(ref trait_info, ..) => match trait_info.principal_def_id() {
+        ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
             Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
                 Some(TraitSimplifiedType(principal_def_id))
             }
@@ -100,24 +100,21 @@ pub fn simplify_type(
         ty::Ref(_, _, mutbl) => Some(RefSimplifiedType(mutbl)),
         ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
         ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
-        ty::GeneratorWitness(ref tys) => {
-            Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len()))
-        }
+        ty::GeneratorWitness(tys) => Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())),
         ty::Never => Some(NeverSimplifiedType),
-        ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())),
-        ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
-        ty::Projection(_) | ty::Param(_) => {
-            if can_simplify_params == SimplifyParams::Yes {
-                // In normalized types, projections don't unify with
-                // anything. when lazy normalization happens, this
-                // will change. It would still be nice to have a way
-                // to deal with known-not-to-unify-with-anything
-                // projections (e.g., the likes of <__S as Encoder>::Error).
+        ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())),
+        ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
+        ty::Param(_) | ty::Projection(_) => match treat_params {
+            // When treated as bound types, projections don't unify with
+            // anything as long as they are fully normalized.
+            //
+            // We will have to be careful with lazy normalization here.
+            TreatParams::AsBoundTypes => {
+                debug!("treating `{}` as a bound type", ty);
                 Some(ParameterSimplifiedType)
-            } else {
-                None
             }
-        }
+            TreatParams::AsPlaceholders => None,
+        },
         ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)),
         ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
         ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
index c77047f8a2ec25e94d31e0dec98371e944f11aad..23664640aaef0f8987c7b82121bb7675359a769c 100644 (file)
@@ -5,6 +5,7 @@
 use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
 use rustc_ast as ast;
 use rustc_attr as attr;
+use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::BitSet;
@@ -302,7 +303,7 @@ fn invert_mapping(map: &[u32]) -> Vec<u32> {
 }
 
 impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
-    fn scalar_pair(&self, a: Scalar, b: Scalar) -> Layout {
+    fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS<'tcx> {
         let dl = self.data_layout();
         let b_align = b.value.align(dl);
         let align = a.value.align(dl).max(b_align).max(dl.aggregate_align);
@@ -316,7 +317,7 @@ fn scalar_pair(&self, a: Scalar, b: Scalar) -> Layout {
             .chain(Niche::from_scalar(dl, Size::ZERO, a))
             .max_by_key(|niche| niche.available(dl));
 
-        Layout {
+        LayoutS {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Arbitrary {
                 offsets: vec![Size::ZERO, b_offset],
@@ -335,7 +336,7 @@ fn univariant_uninterned(
         fields: &[TyAndLayout<'_>],
         repr: &ReprOptions,
         kind: StructKind,
-    ) -> Result<Layout, LayoutError<'tcx>> {
+    ) -> Result<LayoutS<'tcx>, LayoutError<'tcx>> {
         let dl = self.data_layout();
         let pack = repr.pack;
         if pack.is_some() && repr.align.is_some() {
@@ -503,8 +504,20 @@ fn univariant_uninterned(
 
                 // Two non-ZST fields, and they're both scalars.
                 (
-                    Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(a), .. }, .. })),
-                    Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(b), .. }, .. })),
+                    Some((
+                        i,
+                        &TyAndLayout {
+                            layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(a), .. }, _)),
+                            ..
+                        },
+                    )),
+                    Some((
+                        j,
+                        &TyAndLayout {
+                            layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(b), .. }, _)),
+                            ..
+                        },
+                    )),
                     None,
                 ) => {
                     // Order by the memory placement, not source order.
@@ -537,7 +550,7 @@ fn univariant_uninterned(
             abi = Abi::Uninhabited;
         }
 
-        Ok(Layout {
+        Ok(LayoutS {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Arbitrary { offsets, memory_index },
             abi,
@@ -547,7 +560,7 @@ fn univariant_uninterned(
         })
     }
 
-    fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> {
+    fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
         let tcx = self.tcx;
         let param_env = self.param_env;
         let dl = self.data_layout();
@@ -556,7 +569,8 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
             assert!(size.bits() <= 128);
             Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } }
         };
-        let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value)));
+        let scalar =
+            |value: Primitive| tcx.intern_layout(LayoutS::scalar(self, scalar_unit(value)));
 
         let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
             Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?))
@@ -565,11 +579,11 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
         Ok(match *ty.kind() {
             // Basic scalars.
-            ty::Bool => tcx.intern_layout(Layout::scalar(
+            ty::Bool => tcx.intern_layout(LayoutS::scalar(
                 self,
                 Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } },
             )),
-            ty::Char => tcx.intern_layout(Layout::scalar(
+            ty::Char => tcx.intern_layout(LayoutS::scalar(
                 self,
                 Scalar {
                     value: Int(I32, false),
@@ -585,11 +599,11 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
             ty::FnPtr(_) => {
                 let mut ptr = scalar_unit(Pointer);
                 ptr.valid_range = ptr.valid_range.with_start(1);
-                tcx.intern_layout(Layout::scalar(self, ptr))
+                tcx.intern_layout(LayoutS::scalar(self, ptr))
             }
 
             // The never type.
-            ty::Never => tcx.intern_layout(Layout {
+            ty::Never => tcx.intern_layout(LayoutS {
                 variants: Variants::Single { index: VariantIdx::new(0) },
                 fields: FieldsShape::Primitive,
                 abi: Abi::Uninhabited,
@@ -607,13 +621,13 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
                 let pointee = tcx.normalize_erasing_regions(param_env, pointee);
                 if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
-                    return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr)));
+                    return Ok(tcx.intern_layout(LayoutS::scalar(self, data_ptr)));
                 }
 
                 let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 let metadata = match unsized_part.kind() {
                     ty::Foreign(..) => {
-                        return Ok(tcx.intern_layout(Layout::scalar(self, data_ptr)));
+                        return Ok(tcx.intern_layout(LayoutS::scalar(self, data_ptr)));
                     }
                     ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
                     ty::Dynamic(..) => {
@@ -651,7 +665,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
                 let largest_niche = if count != 0 { element.largest_niche } else { None };
 
-                tcx.intern_layout(Layout {
+                tcx.intern_layout(LayoutS {
                     variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldsShape::Array { stride: element.size, count },
                     abi,
@@ -662,7 +676,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
             }
             ty::Slice(element) => {
                 let element = self.layout_of(element)?;
-                tcx.intern_layout(Layout {
+                tcx.intern_layout(LayoutS {
                     variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldsShape::Array { stride: element.size, count: 0 },
                     abi: Abi::Aggregate { sized: false },
@@ -671,7 +685,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                     size: Size::ZERO,
                 })
             }
-            ty::Str => tcx.intern_layout(Layout {
+            ty::Str => tcx.intern_layout(LayoutS {
                 variants: Variants::Single { index: VariantIdx::new(0) },
                 fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
                 abi: Abi::Aggregate { sized: false },
@@ -775,7 +789,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
                     // Extract the number of elements from the layout of the array field:
                     let Ok(TyAndLayout {
-                        layout: Layout { fields: FieldsShape::Array { count, .. }, .. },
+                        layout: Layout(Interned(LayoutS { fields: FieldsShape::Array { count, .. }, .. }, _)),
                         ..
                     }) = self.layout_of(f0_ty) else {
                         return Err(LayoutError::Unknown(ty));
@@ -825,7 +839,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                     FieldsShape::Array { stride: e_ly.size, count: e_len }
                 };
 
-                tcx.intern_layout(Layout {
+                tcx.intern_layout(LayoutS {
                     variants: Variants::Single { index: VariantIdx::new(0) },
                     fields,
                     abi: Abi::Vector { element: e_abi, count: e_len },
@@ -905,7 +919,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                         align = align.min(AbiAndPrefAlign::new(pack));
                     }
 
-                    return Ok(tcx.intern_layout(Layout {
+                    return Ok(tcx.intern_layout(LayoutS {
                         variants: Variants::Single { index },
                         fields: FieldsShape::Union(
                             NonZeroUsize::new(variants[index].len())
@@ -1100,17 +1114,17 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
                                     align = align.max(st.align);
 
-                                    Ok(st)
+                                    Ok(tcx.intern_layout(st))
                                 })
                                 .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
-                            let offset = st[i].fields.offset(field_index) + niche.offset;
-                            let size = st[i].size;
+                            let offset = st[i].fields().offset(field_index) + niche.offset;
+                            let size = st[i].size();
 
-                            let abi = if st.iter().all(|v| v.abi.is_uninhabited()) {
+                            let abi = if st.iter().all(|v| v.abi().is_uninhabited()) {
                                 Abi::Uninhabited
                             } else {
-                                match st[i].abi {
+                                match st[i].abi() {
                                     Abi::Scalar(_) => Abi::Scalar(niche_scalar),
                                     Abi::ScalarPair(first, second) => {
                                         // We need to use scalar_unit to reset the
@@ -1130,7 +1144,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
                             let largest_niche = Niche::from_scalar(dl, offset, niche_scalar);
 
-                            niche_filling_layout = Some(Layout {
+                            niche_filling_layout = Some(LayoutS {
                                 variants: Variants::Multiple {
                                     tag: niche_scalar,
                                     tag_encoding: TagEncoding::Niche {
@@ -1377,7 +1391,10 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
                 let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
 
-                let tagged_layout = Layout {
+                let layout_variants =
+                    layout_variants.into_iter().map(|v| tcx.intern_layout(v)).collect();
+
+                let tagged_layout = LayoutS {
                     variants: Variants::Multiple {
                         tag,
                         tag_encoding: TagEncoding::Direct,
@@ -1563,7 +1580,7 @@ fn generator_layout(
         ty: Ty<'tcx>,
         def_id: hir::def_id::DefId,
         substs: SubstsRef<'tcx>,
-    ) -> Result<&'tcx Layout, LayoutError<'tcx>> {
+    ) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
         use SavedLocalEligibility::*;
         let tcx = self.tcx;
         let subst_field = |ty: Ty<'tcx>| ty.subst(tcx, substs);
@@ -1586,7 +1603,7 @@ fn generator_layout(
             value: Primitive::Int(discr_int, false),
             valid_range: WrappingRange { start: 0, end: max_discr },
         };
-        let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag));
+        let tag_layout = self.tcx.intern_layout(LayoutS::scalar(self, tag));
         let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
 
         let promoted_layouts = ineligible_locals
@@ -1722,20 +1739,20 @@ fn generator_layout(
 
                 size = size.max(variant.size);
                 align = align.max(variant.align);
-                Ok(variant)
+                Ok(tcx.intern_layout(variant))
             })
             .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
         size = size.align_to(align.abi);
 
-        let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi.is_uninhabited())
-        {
-            Abi::Uninhabited
-        } else {
-            Abi::Aggregate { sized: true }
-        };
+        let abi =
+            if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi().is_uninhabited()) {
+                Abi::Uninhabited
+            } else {
+                Abi::Aggregate { sized: true }
+            };
 
-        let layout = tcx.intern_layout(Layout {
+        let layout = tcx.intern_layout(LayoutS {
             variants: Variants::Multiple {
                 tag,
                 tag_encoding: TagEncoding::Direct,
@@ -2250,7 +2267,7 @@ fn ty_and_layout_for_variant(
                     ty::Adt(def, _) => def.variants[variant_index].fields.len(),
                     _ => bug!(),
                 };
-                tcx.intern_layout(Layout {
+                tcx.intern_layout(LayoutS {
                     variants: Variants::Single { index: variant_index },
                     fields: match NonZeroUsize::new(fields) {
                         Some(fields) => FieldsShape::Union(fields),
@@ -2263,10 +2280,10 @@ fn ty_and_layout_for_variant(
                 })
             }
 
-            Variants::Multiple { ref variants, .. } => &variants[variant_index],
+            Variants::Multiple { ref variants, .. } => variants[variant_index],
         };
 
-        assert_eq!(layout.variants, Variants::Single { index: variant_index });
+        assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
 
         TyAndLayout { ty: this.ty, layout }
     }
@@ -2284,8 +2301,10 @@ fn field_ty_or_layout<'tcx>(
         ) -> TyMaybeWithLayout<'tcx> {
             let tcx = cx.tcx();
             let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
-                let layout = Layout::scalar(cx, tag);
-                TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
+                TyAndLayout {
+                    layout: tcx.intern_layout(LayoutS::scalar(cx, tag)),
+                    ty: tag.value.to_ty(tcx),
+                }
             };
 
             match *this.ty.kind() {
@@ -3226,12 +3245,8 @@ fn fn_abi_adjust_for_abi(
                     _ => return,
                 }
 
-                // Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`.
-                // LLVM will usually pass these in 2 registers, which is more efficient than by-ref.
-                let max_by_val_size = Pointer.size(self) * 2;
                 let size = arg.layout.size;
-
-                if arg.layout.is_unsized() || size > max_by_val_size {
+                if arg.layout.is_unsized() || size > Pointer.size(self) {
                     arg.make_indirect();
                 } else {
                     // We want to pass small aggregates as immediates, but using
index 542bc3b02e02bb0b587f97503fa4fd13c146bbd7..0927dc2d266abe4353b461d3276fcfe135bb76d6 100644 (file)
@@ -1267,7 +1267,7 @@ fn pretty_print_const_scalar_ptr(
                 Some(GlobalAlloc::Memory(alloc)) => {
                     let len = int.assert_bits(self.tcx().data_layout.pointer_size);
                     let range = AllocRange { start: offset, size: Size::from_bytes(len) };
-                    if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), range) {
+                    if let Ok(byte_str) = alloc.inner().get_bytes(&self.tcx(), range) {
                         p!(pretty_print_byte_str(byte_str))
                     } else {
                         p!("<too short allocation>")
@@ -1424,7 +1424,8 @@ fn pretty_print_const_value(
                 // The `inspect` here is okay since we checked the bounds, and there are
                 // no relocations (we have an active slice reference here). We don't use
                 // this result to affect interpreter execution.
-                let byte_str = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
+                let byte_str =
+                    data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end);
                 self.pretty_print_byte_str(byte_str)
             }
             (
@@ -1434,7 +1435,8 @@ fn pretty_print_const_value(
                 // The `inspect` here is okay since we checked the bounds, and there are no
                 // relocations (we have an active `str` reference here). We don't use this
                 // result to affect interpreter execution.
-                let slice = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
+                let slice =
+                    data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end);
                 p!(write("{:?}", String::from_utf8_lossy(slice)));
                 Ok(self)
             }
@@ -1443,7 +1445,7 @@ fn pretty_print_const_value(
                 // cast is ok because we already checked for pointer size (32 or 64 bit) above
                 let range = AllocRange { start: offset, size: Size::from_bytes(n) };
 
-                let byte_str = alloc.get_bytes(&self.tcx(), range).unwrap();
+                let byte_str = alloc.inner().get_bytes(&self.tcx(), range).unwrap();
                 p!("*");
                 p!(pretty_print_byte_str(byte_str));
                 Ok(self)
index a1e906140e0e8211a8f5620f9b05029e1523d0d4..8b0e7794f92ace6b3af4ba94c24d2f41e311cc40 100644 (file)
@@ -977,7 +977,6 @@ pub fn from_method(
         substs: SubstsRef<'tcx>,
     ) -> ty::TraitRef<'tcx> {
         let defs = tcx.generics_of(trait_id);
-
         ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
     }
 }
index 6100eb48a18634892a6c0ba7c7224253e9111efb..8ebeca50c4174c5b8d353fc7bbc0be39c81fa5d5 100644 (file)
@@ -1,5 +1,5 @@
 use crate::traits::specialization_graph;
-use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams};
+use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
 use crate::ty::fold::TypeFoldable;
 use crate::ty::{Ident, Ty, TyCtxt};
 use rustc_hir as hir;
@@ -150,7 +150,7 @@ pub fn non_blanket_impls_for_ty(
         self_ty: Ty<'tcx>,
     ) -> impl Iterator<Item = DefId> + 'tcx {
         let impls = self.trait_impls_of(def_id);
-        if let Some(simp) = fast_reject::simplify_type(self, self_ty, SimplifyParams::No) {
+        if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsPlaceholders) {
             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
                 return impls.iter().copied();
             }
@@ -180,14 +180,14 @@ pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>(
             }
         }
 
-        // Note that we're using `SimplifyParams::Yes` to query `non_blanket_impls` while using
-        // `SimplifyParams::No` while actually adding them.
+        // Note that we're using `TreatParams::AsBoundTypes` to query `non_blanket_impls` while using
+        // `TreatParams::AsPlaceholders` while actually adding them.
         //
         // This way, when searching for some impl for `T: Trait`, we do not look at any impls
         // whose outer level is not a parameter or projection. Especially for things like
         // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
         // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
-        if let Some(simp) = fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes) {
+        if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsBoundTypes) {
             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
                 for &impl_def_id in impls {
                     if let result @ Some(_) = f(impl_def_id) {
@@ -247,7 +247,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
         }
 
         if let Some(simplified_self_ty) =
-            fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No)
+            fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsPlaceholders)
         {
             impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
         } else {
index 79ac09d523d079f55b7f5b4c6429a2b6d463d334..0c0b0f2bd05affc985dad8dd83c21e488da36c4c 100644 (file)
@@ -1,6 +1,7 @@
 //! See docs in build/expr/mod.rs
 
 use crate::build::Builder;
+use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
@@ -26,8 +27,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 assert_eq!(literal.ty(), ty);
                 Constant { span, user_ty, literal: literal.into() }
             }
-            ExprKind::StaticRef { literal, .. } => {
-                Constant { span, user_ty: None, literal: literal.into() }
+            ExprKind::StaticRef { alloc_id, ty, .. } => {
+                let const_val =
+                    ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &this.tcx));
+                let literal = ConstantKind::Val(const_val, ty);
+
+                Constant { span, user_ty: None, literal }
             }
             ExprKind::ConstBlock { value } => {
                 Constant { span: span, user_ty: None, literal: value.into() }
index 651edc827c320310775024274d9f62a0706425a9..5a7e1d88dd03f9d8cb2084497fe86edb30c80a6e 100644 (file)
@@ -8,7 +8,6 @@
 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
 use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
 use rustc_middle::middle::region;
-use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::{BinOp, BorrowKind, Field, UnOp};
 use rustc_middle::thir::*;
 use rustc_middle::ty::adjustment::{
@@ -941,15 +940,8 @@ fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKi
                 let kind = if self.tcx.is_thread_local_static(id) {
                     ExprKind::ThreadLocalRef(id)
                 } else {
-                    let ptr = self.tcx.create_static_alloc(id);
-                    ExprKind::StaticRef {
-                        literal: ty::Const::from_scalar(
-                            self.tcx,
-                            Scalar::from_pointer(ptr.into(), &self.tcx),
-                            ty,
-                        ),
-                        def_id: id,
-                    }
+                    let alloc_id = self.tcx.create_static_alloc(id);
+                    ExprKind::StaticRef { alloc_id, ty, def_id: id }
                 };
                 ExprKind::Deref {
                     arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }),
index 27a6b5beb627cb2c0360ea67a899b9194d2fe365..b80d2e52ee709cabe32710b81b38ecbad2294d33 100644 (file)
@@ -20,7 +20,7 @@
 };
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
-use rustc_span::{DesugaringKind, ExpnKind, Span};
+use rustc_span::{DesugaringKind, ExpnKind, MultiSpan, Span};
 
 crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
     let body_id = match def_id.as_local() {
@@ -64,7 +64,9 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> {
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         intravisit::walk_expr(self, ex);
         match &ex.kind {
-            hir::ExprKind::Match(scrut, arms, source) => self.check_match(scrut, arms, *source),
+            hir::ExprKind::Match(scrut, arms, source) => {
+                self.check_match(scrut, arms, *source, ex.span)
+            }
             hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => {
                 self.check_let(pat, init, *span)
             }
@@ -163,6 +165,7 @@ fn check_match(
         scrut: &hir::Expr<'_>,
         hir_arms: &'tcx [hir::Arm<'tcx>],
         source: hir::MatchSource,
+        expr_span: Span,
     ) {
         let mut cx = self.new_cx(scrut.hir_id);
 
@@ -208,7 +211,6 @@ fn check_match(
         }
 
         // Check if the match is exhaustive.
-        let is_empty_match = arms.is_empty();
         let witnesses = report.non_exhaustiveness_witnesses;
         if !witnesses.is_empty() {
             if source == hir::MatchSource::ForLoopDesugar && hir_arms.len() == 2 {
@@ -216,7 +218,7 @@ fn check_match(
                 let pat = hir_arms[1].pat.for_loop_some().unwrap();
                 self.check_irrefutable(pat, "`for` loop binding", None);
             } else {
-                non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, is_empty_match);
+                non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, hir_arms, expr_span);
             }
         }
     }
@@ -334,7 +336,7 @@ fn check_for_bindings_named_same_as_variants(
                     let ty_path = cx.tcx.def_path_str(edef.did);
                     let mut err = lint.build(&format!(
                         "pattern binding `{}` is named the same as one \
-                                        of the variants of the type `{}`",
+                         of the variants of the type `{}`",
                         ident, ty_path
                     ));
                     err.code(error_code!(E0170));
@@ -494,8 +496,10 @@ fn non_exhaustive_match<'p, 'tcx>(
     scrut_ty: Ty<'tcx>,
     sp: Span,
     witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
-    is_empty_match: bool,
+    arms: &[hir::Arm<'tcx>],
+    expr_span: Span,
 ) {
+    let is_empty_match = arms.is_empty();
     let non_empty_enum = match scrut_ty.kind() {
         ty::Adt(def, _) => def.is_enum() && !def.variants.is_empty(),
         _ => false,
@@ -503,12 +507,15 @@ fn non_exhaustive_match<'p, 'tcx>(
     // In the case of an empty match, replace the '`_` not covered' diagnostic with something more
     // informative.
     let mut err;
+    let pattern;
+    let mut patterns_len = 0;
     if is_empty_match && !non_empty_enum {
         err = create_e0004(
             cx.tcx.sess,
             sp,
             format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
         );
+        pattern = "_".to_string();
     } else {
         let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
         err = create_e0004(
@@ -517,6 +524,16 @@ fn non_exhaustive_match<'p, 'tcx>(
             format!("non-exhaustive patterns: {} not covered", joined_patterns),
         );
         err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+        patterns_len = witnesses.len();
+        pattern = if witnesses.len() < 4 {
+            witnesses
+                .iter()
+                .map(|witness| witness.to_pat(cx).to_string())
+                .collect::<Vec<String>>()
+                .join(" | ")
+        } else {
+            "_".to_string()
+        };
     };
 
     let is_variant_list_non_exhaustive = match scrut_ty.kind() {
@@ -525,10 +542,6 @@ fn non_exhaustive_match<'p, 'tcx>(
     };
 
     adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
-    err.help(
-        "ensure that all possible cases are being handled, \
-              possibly by adding wildcards or more match arms",
-    );
     err.note(&format!(
         "the matched value is of type `{}`{}",
         scrut_ty,
@@ -540,14 +553,14 @@ fn non_exhaustive_match<'p, 'tcx>(
         && matches!(witnesses[0].ctor(), Constructor::NonExhaustive)
     {
         err.note(&format!(
-            "`{}` does not have a fixed maximum value, \
-                so a wildcard `_` is necessary to match exhaustively",
+            "`{}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \
+             exhaustively",
             scrut_ty,
         ));
         if cx.tcx.sess.is_nightly_build() {
             err.help(&format!(
-                "add `#![feature(precise_pointer_size_matching)]` \
-                    to the crate attributes to enable precise `{}` matching",
+                "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \
+                 enable precise `{}` matching",
                 scrut_ty,
             ));
         }
@@ -557,6 +570,84 @@ fn non_exhaustive_match<'p, 'tcx>(
             err.note("references are always considered inhabited");
         }
     }
+
+    let mut suggestion = None;
+    let sm = cx.tcx.sess.source_map();
+    match arms {
+        [] if sp.ctxt() == expr_span.ctxt() => {
+            // Get the span for the empty match body `{}`.
+            let (indentation, more) = if let Some(snippet) = sm.indentation_before(sp) {
+                (format!("\n{}", snippet), "    ")
+            } else {
+                (" ".to_string(), "")
+            };
+            suggestion = Some((
+                sp.shrink_to_hi().with_hi(expr_span.hi()),
+                format!(
+                    " {{{indentation}{more}{pattern} => todo!(),{indentation}}}",
+                    indentation = indentation,
+                    more = more,
+                    pattern = pattern,
+                ),
+            ));
+        }
+        [only] => {
+            let pre_indentation = if let (Some(snippet), true) = (
+                sm.indentation_before(only.span),
+                sm.is_multiline(sp.shrink_to_hi().with_hi(only.span.lo())),
+            ) {
+                format!("\n{}", snippet)
+            } else {
+                " ".to_string()
+            };
+            let comma = if matches!(only.body.kind, hir::ExprKind::Block(..)) { "" } else { "," };
+            suggestion = Some((
+                only.span.shrink_to_hi(),
+                format!("{}{}{} => todo!()", comma, pre_indentation, pattern),
+            ));
+        }
+        [.., prev, last] if prev.span.ctxt() == last.span.ctxt() => {
+            if let Ok(snippet) = sm.span_to_snippet(prev.span.between(last.span)) {
+                let comma =
+                    if matches!(last.body.kind, hir::ExprKind::Block(..)) { "" } else { "," };
+                suggestion = Some((
+                    last.span.shrink_to_hi(),
+                    format!(
+                        "{}{}{} => todo!()",
+                        comma,
+                        snippet.strip_prefix(",").unwrap_or(&snippet),
+                        pattern
+                    ),
+                ));
+            }
+        }
+        _ => {}
+    }
+
+    let msg = format!(
+        "ensure that all possible cases are being handled by adding a match arm with a wildcard \
+         pattern{}{}",
+        if patterns_len > 1 && patterns_len < 4 && suggestion.is_some() {
+            ", a match arm with multiple or-patterns"
+        } else {
+            // we are either not suggesting anything, or suggesting `_`
+            ""
+        },
+        match patterns_len {
+            // non-exhaustive enum case
+            0 if suggestion.is_some() => " as shown",
+            0 => "",
+            1 if suggestion.is_some() => " or an explicit pattern as shown",
+            1 => " or an explicit pattern",
+            _ if suggestion.is_some() => " as shown, or multiple match arms",
+            _ => " or multiple match arms",
+        },
+    );
+    if let Some((span, sugg)) = suggestion {
+        err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
+    } else {
+        err.help(&msg);
+    }
     err.emit();
 }
 
@@ -597,15 +688,27 @@ fn adt_defined_here<'p, 'tcx>(
 ) {
     let ty = ty.peel_refs();
     if let ty::Adt(def, _) = ty.kind() {
-        if let Some(sp) = cx.tcx.hir().span_if_local(def.did) {
-            err.span_label(sp, format!("`{}` defined here", ty));
-        }
-
-        if witnesses.len() < 4 {
+        let mut spans = vec![];
+        if witnesses.len() < 5 {
             for sp in maybe_point_at_variant(cx, def, witnesses.iter()) {
-                err.span_label(sp, "not covered");
+                spans.push(sp);
             }
         }
+        let def_span = cx
+            .tcx
+            .hir()
+            .get_if_local(def.did)
+            .and_then(|node| node.ident())
+            .map(|ident| ident.span)
+            .unwrap_or_else(|| cx.tcx.def_span(def.did));
+        let mut span: MultiSpan =
+            if spans.is_empty() { def_span.into() } else { spans.clone().into() };
+
+        span.push_span_label(def_span, String::new());
+        for pat in spans {
+            span.push_span_label(pat, "not covered".to_string());
+        }
+        err.span_note(span, &format!("`{}` defined here", ty));
     }
 }
 
index 7b000e2e1d22645303479956ce3b6cbf56f982c8..4c1a7eaf6f03b83c6af0c2e6b0c82845cb2074ab 100644 (file)
@@ -7,7 +7,7 @@ edition = "2021"
 doctest = false
 
 [dependencies]
-itertools = "0.10"
+itertools = "0.10.1"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 tracing = "0.1"
 rustc_ast = { path = "../rustc_ast" }
index d849bc408fab47caebac145afd4a6cdcb9ba01d0..34c539f319194761c161ca96b6e6c372a9a3e8ec 100644 (file)
@@ -31,8 +31,8 @@
 use crate::MirPass;
 use rustc_const_eval::const_eval::ConstEvalErr;
 use rustc_const_eval::interpret::{
-    self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
-    Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy,
+    self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame,
+    ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy,
     Operand as InterpOperand, PlaceTy, Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind,
 };
 
@@ -274,7 +274,7 @@ fn access_local_mut<'a>(
     fn before_access_global(
         _memory_extra: &(),
         _alloc_id: AllocId,
-        allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
+        alloc: ConstAllocation<'tcx, Self::PointerTag, Self::AllocExtra>,
         _static_def_id: Option<DefId>,
         is_write: bool,
     ) -> InterpResult<'tcx> {
@@ -283,7 +283,7 @@ fn before_access_global(
         }
         // If the static allocation is mutable, then we can't const prop it as its content
         // might be different at runtime.
-        if allocation.mutability == Mutability::Mut {
+        if alloc.inner().mutability == Mutability::Mut {
             throw_machine_stop_str!("can't access mutable globals in ConstProp");
         }
 
index 7133724d07d95c6639b922ce61ab40cd8fb3ebbf..bd196f1187966db729fe37b77b544bfa79e6b621 100644 (file)
@@ -65,7 +65,7 @@ fn variant_discriminants<'tcx>(
         Variants::Multiple { variants, .. } => variants
             .iter_enumerated()
             .filter_map(|(idx, layout)| {
-                (layout.abi != Abi::Uninhabited)
+                (layout.abi() != Abi::Uninhabited)
                     .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
             })
             .collect(),
index 819cffd3a9bf1dc0e0acccc53c537e08835d3f6c..ed771534c4c4c2c152252541c294998261dcc65d 100644 (file)
@@ -401,7 +401,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.inner().relocations().values() {
                     collect_miri(tcx, id, &mut neighbors);
                 }
             }
@@ -1370,7 +1370,7 @@ fn collect_miri<'tcx>(
         }
         GlobalAlloc::Memory(alloc) => {
             trace!("collecting {:?} with {:#?}", alloc_id, alloc);
-            for &inner in alloc.relocations().values() {
+            for &inner in alloc.inner().relocations().values() {
                 rustc_data_structures::stack::ensure_sufficient_stack(|| {
                     collect_miri(tcx, inner, output);
                 });
@@ -1405,7 +1405,7 @@ fn collect_const_value<'tcx>(
     match value {
         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.inner().relocations().values() {
                 collect_miri(tcx, id, output);
             }
         }
index c7aa9ffc7937d10f7c06c72e6dd24dd1f06da6b3..40daf4eb28fc1b558e78fbf8e1b016b048b731ac 100644 (file)
@@ -1,5 +1,5 @@
 use super::pat::Expected;
-use super::ty::{AllowPlus, IsAsCast};
+use super::ty::{AllowPlus, RecoverQuestionMark};
 use super::{
     BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions,
     SemiColonMode, SeqSep, TokenExpectType, TokenType,
@@ -1049,9 +1049,9 @@ pub(super) fn maybe_report_ambiguous_plus(
     pub(super) fn maybe_recover_from_question_mark(
         &mut self,
         ty: P<Ty>,
-        is_as_cast: IsAsCast,
+        recover_question_mark: RecoverQuestionMark,
     ) -> P<Ty> {
-        if let IsAsCast::Yes = is_as_cast {
+        if let RecoverQuestionMark::No = recover_question_mark {
             return ty;
         }
         if self.token == token::Question {
index df865d77b9bb4cc5d40a66adc61c72a4f305ebfc..b993d48c995b4748ec20c05d3a1b148215e8b108 100644 (file)
@@ -20,7 +20,6 @@
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
 use rustc_session::lint::BuiltinLintDiagnostics;
-use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos};
@@ -2712,8 +2711,7 @@ pub(super) fn parse_struct_fields(
         let mut async_block_err = |e: &mut Diagnostic, span: Span| {
             recover_async = true;
             e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
-            e.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
-            e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
+            e.help_use_latest_edition();
         };
 
         while self.token != token::CloseDelim(close_delim) {
index ae46bfe3540835e01065b3e9a9b6f3c8c187c053..06460c7b1b31ddcc8e21ec89ff01fe4bdbfb2c00 100644 (file)
 use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
 use rustc_ast::{MacArgs, MacCall, MacDelimiter};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability, ErrorGuaranteed, PResult, StashKey};
-use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
+use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
+use rustc_span::edition::Edition;
 use rustc_span::lev_distance::lev_distance;
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::DUMMY_SP;
 
 use std::convert::TryFrom;
 use std::mem;
@@ -449,6 +450,16 @@ fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
         if end.is_doc_comment() {
             err.span_label(end.span, "this doc comment doesn't document anything");
         }
+        if end.meta_kind().is_some() {
+            if self.token.kind == TokenKind::Semi {
+                err.span_suggestion_verbose(
+                    self.token.span,
+                    "consider removing this semicolon",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
         if let [.., penultimate, _] = attrs {
             err.span_label(start.span.to(penultimate.span), "other attributes here");
         }
@@ -791,44 +802,6 @@ fn parse_assoc_item(
         ))
     }
 
-    /// Emits an error that the where clause at the end of a type alias is not
-    /// allowed and suggests moving it.
-    fn error_ty_alias_where(
-        &self,
-        before_where_clause_present: bool,
-        before_where_clause_span: Span,
-        after_predicates: &[WherePredicate],
-        after_where_clause_span: Span,
-    ) -> ErrorGuaranteed {
-        let mut err =
-            self.struct_span_err(after_where_clause_span, "where clause not allowed here");
-        if !after_predicates.is_empty() {
-            let mut state = crate::pprust::State::new();
-            if !before_where_clause_present {
-                state.space();
-                state.word_space("where");
-            } else {
-                state.word_space(",");
-            }
-            let mut first = true;
-            for p in after_predicates.iter() {
-                if !first {
-                    state.word_space(",");
-                }
-                first = false;
-                state.print_where_predicate(p);
-            }
-            let suggestion = state.s.eof();
-            err.span_suggestion(
-                before_where_clause_span.shrink_to_hi(),
-                "move it here",
-                suggestion,
-                Applicability::MachineApplicable,
-            );
-        }
-        err.emit()
-    }
-
     /// Parses a `type` alias with the following grammar:
     /// ```
     /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
@@ -841,27 +814,40 @@ fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo
         // Parse optional colon and param bounds.
         let bounds =
             if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
-
-        generics.where_clause = self.parse_where_clause()?;
+        let before_where_clause = self.parse_where_clause()?;
 
         let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
 
-        if self.token.is_keyword(kw::Where) {
-            let after_where_clause = self.parse_where_clause()?;
+        let after_where_clause = self.parse_where_clause()?;
 
-            self.error_ty_alias_where(
-                generics.where_clause.has_where_token,
-                generics.where_clause.span,
-                &after_where_clause.predicates,
-                after_where_clause.span,
-            );
-
-            generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter());
-        }
+        let where_clauses = (
+            TyAliasWhereClause(before_where_clause.has_where_token, before_where_clause.span),
+            TyAliasWhereClause(after_where_clause.has_where_token, after_where_clause.span),
+        );
+        let where_predicates_split = before_where_clause.predicates.len();
+        let mut predicates = before_where_clause.predicates;
+        predicates.extend(after_where_clause.predicates.into_iter());
+        let where_clause = WhereClause {
+            has_where_token: before_where_clause.has_where_token
+                || after_where_clause.has_where_token,
+            predicates,
+            span: DUMMY_SP,
+        };
+        generics.where_clause = where_clause;
 
         self.expect_semi()?;
 
-        Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
+        Ok((
+            ident,
+            ItemKind::TyAlias(Box::new(TyAlias {
+                defaultness,
+                generics,
+                where_clauses,
+                where_predicates_split,
+                bounds,
+                ty,
+            })),
+        ))
     }
 
     /// Parses a `UseTree`.
@@ -2116,8 +2102,7 @@ fn ban_async_in_2015(&self, span: Span) {
             let diag = self.diagnostic();
             struct_span_err!(diag, span, E0670, "`async fn` is not permitted in Rust 2015")
                 .span_label(span, "to use `async fn`, switch to Rust 2018 or later")
-                .help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION))
-                .note("for more on editions, read https://doc.rust-lang.org/edition-guide")
+                .help_use_latest_edition()
                 .emit();
         }
     }
index 83e0a4997ad85020b539b5d61a67a513d86a5cbe..40902fa18331333568612d39c47405282c111909 100644 (file)
@@ -140,7 +140,7 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
             }
 
             NonterminalKind::Ty => {
-                token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty())?)
+                token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?)
             }
             // this could be handled like a token, since it is one
             NonterminalKind::Ident
index 0b01f9e927f33e77d520e8e8a40fd554e5d5bc44..436c5bd4fcac23fc7b62f5f305d0442530613c21 100644 (file)
@@ -44,7 +44,7 @@ pub(super) enum RecoverQPath {
     No,
 }
 
-pub(super) enum IsAsCast {
+pub(super) enum RecoverQuestionMark {
     Yes,
     No,
 }
@@ -105,7 +105,7 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -119,7 +119,7 @@ pub(super) fn parse_ty_with_generics_recovery(
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             Some(ty_params),
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -133,7 +133,7 @@ pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -150,7 +150,7 @@ pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -163,9 +163,21 @@ pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
             RecoverQPath::Yes,
             RecoverReturnSign::Yes,
             None,
-            IsAsCast::Yes,
+            RecoverQuestionMark::No,
         )
     }
+
+    pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(
+            AllowPlus::Yes,
+            AllowCVariadic::No,
+            RecoverQPath::Yes,
+            RecoverReturnSign::Yes,
+            None,
+            RecoverQuestionMark::No,
+        )
+    }
+
     /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
     pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
@@ -174,7 +186,7 @@ pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
             RecoverQPath::Yes,
             RecoverReturnSign::OnlyFatArrow,
             None,
-            IsAsCast::No,
+            RecoverQuestionMark::Yes,
         )
     }
 
@@ -193,7 +205,7 @@ pub(super) fn parse_ret_ty(
                 recover_qpath,
                 recover_return_sign,
                 None,
-                IsAsCast::No,
+                RecoverQuestionMark::Yes,
             )?;
             FnRetTy::Ty(ty)
         } else if recover_return_sign.can_recover(&self.token.kind) {
@@ -214,7 +226,7 @@ pub(super) fn parse_ret_ty(
                 recover_qpath,
                 recover_return_sign,
                 None,
-                IsAsCast::No,
+                RecoverQuestionMark::Yes,
             )?;
             FnRetTy::Ty(ty)
         } else {
@@ -229,7 +241,7 @@ fn parse_ty_common(
         recover_qpath: RecoverQPath,
         recover_return_sign: RecoverReturnSign,
         ty_generics: Option<&Generics>,
-        is_as_cast: IsAsCast,
+        recover_question_mark: RecoverQuestionMark,
     ) -> PResult<'a, P<Ty>> {
         let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
@@ -305,7 +317,7 @@ fn parse_ty_common(
         // Try to recover from use of `+` with incorrect priority.
         self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
         self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
-        let ty = self.maybe_recover_from_question_mark(ty, is_as_cast);
+        let ty = self.maybe_recover_from_question_mark(ty, recover_question_mark);
         self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
     }
 
index d94ad7ba71a9c63a19560b02cde7e77b2a0d1409..01b12eec628ec074877dc828802fdd3fea137f7b 100644 (file)
@@ -4,7 +4,7 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
+use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
@@ -178,34 +178,7 @@ fn check_attributes(
                 check_duplicates(self.tcx, attr, hir_id, *duplicates, &mut seen);
             }
 
-            // Warn on useless empty attributes.
-            if matches!(
-                attr.name_or_empty(),
-                sym::macro_use
-                    | sym::allow
-                    | sym::warn
-                    | sym::deny
-                    | sym::forbid
-                    | sym::feature
-                    | sym::repr
-                    | sym::target_feature
-            ) && attr.meta_item_list().map_or(false, |list| list.is_empty())
-            {
-                self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
-                    lint.build("unused attribute")
-                        .span_suggestion(
-                            attr.span,
-                            "remove this attribute",
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        )
-                        .note(&format!(
-                            "attribute `{}` with an empty list has no effect",
-                            attr.name_or_empty()
-                        ))
-                        .emit();
-                });
-            }
+            self.check_unused_attribute(hir_id, attr)
         }
 
         if !is_valid {
@@ -1372,7 +1345,7 @@ fn check_rustc_legacy_const_generics(
         target: Target,
         item: Option<ItemLike<'_>>,
     ) -> bool {
-        let is_function = matches!(target, Target::Fn | Target::Method(..));
+        let is_function = matches!(target, Target::Fn);
         if !is_function {
             self.tcx
                 .sess
@@ -1969,6 +1942,55 @@ fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target
             });
         }
     }
+
+    fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
+        // Warn on useless empty attributes.
+        let note = if matches!(
+            attr.name_or_empty(),
+            sym::macro_use
+                | sym::allow
+                | sym::expect
+                | sym::warn
+                | sym::deny
+                | sym::forbid
+                | sym::feature
+                | sym::repr
+                | sym::target_feature
+        ) && attr.meta_item_list().map_or(false, |list| list.is_empty())
+        {
+            format!(
+                "attribute `{}` with an empty list has no effect",
+                attr.name_or_empty()
+            )
+        } else if matches!(
+                attr.name_or_empty(),
+                sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
+            ) && let Some(meta) = attr.meta_item_list()
+            && meta.len() == 1
+            && let Some(item) = meta[0].meta_item()
+            && let MetaItemKind::NameValue(_) = &item.kind
+            && item.path == sym::reason
+        {
+            format!(
+                "attribute `{}` without any lints has no effect",
+                attr.name_or_empty()
+            )
+        } else {
+            return;
+        };
+
+        self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+            lint.build("unused attribute")
+                .span_suggestion(
+                    attr.span,
+                    "remove this attribute",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .note(&note)
+                .emit();
+        });
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
index fdabe41dafaedff61466dea6036b6be20c155163..f5040a373c29637b1c72a243762b73ce58a76993 100644 (file)
@@ -218,9 +218,9 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
     // The file may be empty, which leads to the diagnostic machinery not emitting this
     // note. This is a relatively simple way to detect that case and emit a span-less
     // note instead.
-    if tcx.sess.source_map().lookup_line(sp.lo()).is_ok() {
-        err.set_span(sp);
-        err.span_label(sp, &note);
+    if tcx.sess.source_map().lookup_line(sp.hi()).is_ok() {
+        err.set_span(sp.shrink_to_hi());
+        err.span_label(sp.shrink_to_hi(), &note);
     } else {
         err.note(&note);
     }
index df3853d8744d620017735cba1a82bf4cb4656ae0..37a9f0ecd8c1867956ad0fe13e4cdf249047bce8 100644 (file)
@@ -1,13 +1,12 @@
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
-use rustc_ast::Attribute;
 use rustc_attr::{self as attr, ConstStability, Stability};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX};
 use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
@@ -113,12 +112,8 @@ fn annotate<F>(
     {
         let attrs = self.tcx.get_attrs(def_id.to_def_id());
         debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
-        let mut did_error = false;
-        if !self.tcx.features().staged_api {
-            did_error = self.forbid_staged_api_attrs(def_id, attrs, inherit_deprecation.clone());
-        }
 
-        let depr = if did_error { None } else { attr::find_deprecation(&self.tcx.sess, attrs) };
+        let depr = attr::find_deprecation(&self.tcx.sess, attrs);
         let mut is_deprecated = false;
         if let Some((depr, span)) = &depr {
             is_deprecated = true;
@@ -148,16 +143,15 @@ fn annotate<F>(
             }
         }
 
-        if self.tcx.features().staged_api {
-            if let Some(a) = attrs.iter().find(|a| a.has_name(sym::deprecated)) {
-                self.tcx
-                    .sess
-                    .struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API")
-                    .span_label(a.span, "use `#[rustc_deprecated]` instead")
-                    .span_label(item_sp, "")
-                    .emit();
+        if !self.tcx.features().staged_api {
+            // Propagate unstability.  This can happen even for non-staged-api crates in case
+            // -Zforce-unstable-if-unmarked is set.
+            if let Some(stab) = self.parent_stab {
+                if inherit_deprecation.yes() && stab.level.is_unstable() {
+                    self.index.stab_map.insert(def_id, stab);
+                }
             }
-        } else {
+
             self.recurse_with_stability_attrs(
                 depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
                 None,
@@ -329,47 +323,6 @@ fn recurse_with_stability_attrs(
             self.parent_const_stab = orig_parent_const_stab;
         }
     }
-
-    // returns true if an error occurred, used to suppress some spurious errors
-    fn forbid_staged_api_attrs(
-        &mut self,
-        def_id: LocalDefId,
-        attrs: &[Attribute],
-        inherit_deprecation: InheritDeprecation,
-    ) -> bool {
-        // Emit errors for non-staged-api crates.
-        let unstable_attrs = [
-            sym::unstable,
-            sym::stable,
-            sym::rustc_deprecated,
-            sym::rustc_const_unstable,
-            sym::rustc_const_stable,
-        ];
-        let mut has_error = false;
-        for attr in attrs {
-            let name = attr.name_or_empty();
-            if unstable_attrs.contains(&name) {
-                struct_span_err!(
-                    self.tcx.sess,
-                    attr.span,
-                    E0734,
-                    "stability attributes may not be used outside of the standard library",
-                )
-                .emit();
-                has_error = true;
-            }
-        }
-
-        // Propagate unstability.  This can happen even for non-staged-api crates in case
-        // -Zforce-unstable-if-unmarked is set.
-        if let Some(stab) = self.parent_stab {
-            if inherit_deprecation.yes() && stab.level.is_unstable() {
-                self.index.stab_map.insert(def_id, stab);
-            }
-        }
-
-        has_error
-    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
@@ -654,28 +607,12 @@ fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
 }
 
 fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
-    let is_staged_api =
-        tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api;
-    let mut staged_api = FxHashMap::default();
-    staged_api.insert(LOCAL_CRATE, is_staged_api);
     let mut index = Index {
-        staged_api,
         stab_map: Default::default(),
         const_stab_map: Default::default(),
         depr_map: Default::default(),
-        active_features: Default::default(),
     };
 
-    let active_lib_features = &tcx.features().declared_lib_features;
-    let active_lang_features = &tcx.features().declared_lang_features;
-
-    // Put the active features into a map for quick lookup.
-    index.active_features = active_lib_features
-        .iter()
-        .map(|&(s, ..)| s)
-        .chain(active_lang_features.iter().map(|&(s, ..)| s))
-        .collect();
-
     {
         let mut annotator = Annotator {
             tcx,
@@ -728,7 +665,16 @@ fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_unstable_api_usage, stability_index, ..*providers };
+    *providers = Providers {
+        check_mod_unstable_api_usage,
+        stability_index,
+        lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()),
+        lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()),
+        lookup_deprecation_entry: |tcx, id| {
+            tcx.stability().local_deprecation_entry(id.expect_local())
+        },
+        ..*providers
+    };
 }
 
 struct Checker<'tcx> {
@@ -884,9 +830,10 @@ fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {
 /// were expected to be library features), and the list of features used from
 /// libraries, identify activated features that don't exist and error about them.
 pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
-    let access_levels = &tcx.privacy_access_levels(());
-
-    if tcx.stability().staged_api[&LOCAL_CRATE] {
+    let is_staged_api =
+        tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api;
+    if is_staged_api {
+        let access_levels = &tcx.privacy_access_levels(());
         let mut missing = MissingStabilityAnnotations { tcx, access_levels };
         missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
         tcx.hir().walk_toplevel_module(&mut missing);
@@ -907,7 +854,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     }
 
     let declared_lib_features = &tcx.features().declared_lib_features;
-    let mut remaining_lib_features = FxHashMap::default();
+    let mut remaining_lib_features = FxIndexMap::default();
     for (feature, span) in declared_lib_features {
         if !tcx.sess.opts.unstable_features.is_nightly_build() {
             struct_span_err!(
@@ -934,7 +881,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     remaining_lib_features.remove(&sym::libc);
     remaining_lib_features.remove(&sym::test);
 
-    let check_features = |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &[_]| {
+    let check_features = |remaining_lib_features: &mut FxIndexMap<_, _>, defined_features: &[_]| {
         for &(feature, since) in defined_features {
             if let Some(since) = since {
                 if let Some(span) = remaining_lib_features.get(&feature) {
index b56cb86a18c86f30cd2697d4b0ffbae32c57e6be..fd1c0239b596511b011a76acd04436b0d90ff95c 100644 (file)
@@ -852,7 +852,7 @@ fn generics(&mut self) -> &mut Self {
                         self.visit(self.ev.tcx.type_of(param.def_id));
                     }
                 }
-                GenericParamDefKind::Const { has_default, .. } => {
+                GenericParamDefKind::Const { has_default } => {
                     self.visit(self.ev.tcx.type_of(param.def_id));
                     if has_default {
                         self.visit(self.ev.tcx.const_param_default(param.def_id));
index bf570fb0f80b00a75279c3b439dc22fad545bd24..70ade7a5600ba9dffbf9cf7f41b9e24b6d27c019 100644 (file)
@@ -720,7 +720,9 @@ pub fn finalize_imports(&mut self) {
                     note: Vec::new(),
                     suggestion: None,
                 };
-                errors.push((path, err));
+                if path.contains("::") {
+                    errors.push((path, err))
+                }
             }
         }
 
index 086f0249114baabc58636d92aabc44f1ddbd6e47..3342bd146c4ee50a6c8a6f948aa9aa64af30bec0 100644 (file)
@@ -3207,7 +3207,7 @@ fn add_suggestion_for_rename_of_use(
                     }
                 }
             }
-            ImportKind::ExternCrate { source, target, .. } => {
+            ImportKind::ExternCrate { source, target } => {
                 suggestion = Some(format!(
                     "extern crate {} as {};",
                     source.unwrap_or(target.name),
index 37cfc4a0dc3c2b91d586228a5d61df1dda0e7912..6b1eaa4d399d9d291133d36e7de2d46c93464b22 100644 (file)
@@ -15,6 +15,5 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_span = { path = "../rustc_span" }
 rustc_fs_util = { path = "../rustc_fs_util" }
-num_cpus = "1.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
index f9b75690e375fd253c97632dfe61ebb302486813..221dc86c1d46d931ad424bfdb2575d44c2e5fd5f 100644 (file)
@@ -13,6 +13,7 @@
 
 use rustc_target::abi::{Align, TargetDataLayout};
 use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
+use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS};
 
 use rustc_serialize::json;
 
@@ -1025,13 +1026,19 @@ pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig
 pub struct CheckCfg<T = String> {
     /// The set of all `names()`, if None no name checking is performed
     pub names_valid: Option<FxHashSet<T>>,
+    /// Is well known values activated
+    pub well_known_values: bool,
     /// The set of all `values()`
     pub values_valid: FxHashMap<T, FxHashSet<T>>,
 }
 
 impl<T> Default for CheckCfg<T> {
     fn default() -> Self {
-        CheckCfg { names_valid: Default::default(), values_valid: Default::default() }
+        CheckCfg {
+            names_valid: Default::default(),
+            values_valid: Default::default(),
+            well_known_values: false,
+        }
     }
 }
 
@@ -1047,6 +1054,7 @@ fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> {
                 .iter()
                 .map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect()))
                 .collect(),
+            well_known_values: self.well_known_values,
         }
     }
 }
@@ -1060,8 +1068,9 @@ pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig {
 
 impl CrateCheckConfig {
     /// Fills a `CrateCheckConfig` with well-known configuration names.
-    pub fn fill_well_known(&mut self) {
-        // NOTE: This should be kept in sync with `default_configuration`
+    fn fill_well_known_names(&mut self) {
+        // NOTE: This should be kept in sync with `default_configuration` and
+        // `fill_well_known_values`
         const WELL_KNOWN_NAMES: &[Symbol] = &[
             sym::unix,
             sym::windows,
@@ -1086,11 +1095,106 @@ pub fn fill_well_known(&mut self) {
             sym::doctest,
             sym::feature,
         ];
+
+        // We only insert well-known names if `names()` was activated
         if let Some(names_valid) = &mut self.names_valid {
-            for &name in WELL_KNOWN_NAMES {
-                names_valid.insert(name);
-            }
+            names_valid.extend(WELL_KNOWN_NAMES);
+        }
+    }
+
+    /// Fills a `CrateCheckConfig` with well-known configuration values.
+    fn fill_well_known_values(&mut self) {
+        if !self.well_known_values {
+            return;
         }
+
+        // NOTE: This should be kept in sync with `default_configuration` and
+        // `fill_well_known_names`
+
+        let panic_values = &PanicStrategy::all();
+
+        let atomic_values = &[
+            sym::ptr,
+            sym::integer(8usize),
+            sym::integer(16usize),
+            sym::integer(32usize),
+            sym::integer(64usize),
+            sym::integer(128usize),
+        ];
+
+        let sanitize_values = SanitizerSet::all()
+            .into_iter()
+            .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
+
+        // No-values
+        for name in [
+            sym::unix,
+            sym::windows,
+            sym::debug_assertions,
+            sym::proc_macro,
+            sym::test,
+            sym::doc,
+            sym::doctest,
+            sym::target_thread_local,
+        ] {
+            self.values_valid.entry(name).or_default();
+        }
+
+        // Pre-defined values
+        self.values_valid.entry(sym::panic).or_default().extend(panic_values);
+        self.values_valid.entry(sym::sanitize).or_default().extend(sanitize_values);
+        self.values_valid.entry(sym::target_has_atomic).or_default().extend(atomic_values);
+        self.values_valid
+            .entry(sym::target_has_atomic_load_store)
+            .or_default()
+            .extend(atomic_values);
+        self.values_valid
+            .entry(sym::target_has_atomic_equal_alignment)
+            .or_default()
+            .extend(atomic_values);
+
+        // Target specific values
+        for target in
+            TARGETS.iter().map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
+        {
+            self.values_valid
+                .entry(sym::target_os)
+                .or_default()
+                .insert(Symbol::intern(&target.options.os));
+            self.values_valid
+                .entry(sym::target_family)
+                .or_default()
+                .extend(target.options.families.iter().map(|family| Symbol::intern(family)));
+            self.values_valid
+                .entry(sym::target_arch)
+                .or_default()
+                .insert(Symbol::intern(&target.arch));
+            self.values_valid
+                .entry(sym::target_endian)
+                .or_default()
+                .insert(Symbol::intern(&target.options.endian.as_str()));
+            self.values_valid
+                .entry(sym::target_env)
+                .or_default()
+                .insert(Symbol::intern(&target.options.env));
+            self.values_valid
+                .entry(sym::target_abi)
+                .or_default()
+                .insert(Symbol::intern(&target.options.abi));
+            self.values_valid
+                .entry(sym::target_vendor)
+                .or_default()
+                .insert(Symbol::intern(&target.options.vendor));
+            self.values_valid
+                .entry(sym::target_pointer_width)
+                .or_default()
+                .insert(sym::integer(target.pointer_width));
+        }
+    }
+
+    pub fn fill_well_known(&mut self) {
+        self.fill_well_known_names();
+        self.fill_well_known_values();
     }
 
     /// Fills a `CrateCheckConfig` with configuration names and values that are actually active.
@@ -2509,7 +2613,6 @@ fn parse_pretty(debugging_opts: &DebuggingOptions, efmt: ErrorOutputType) -> Opt
     let first = match debugging_opts.unpretty.as_deref()? {
         "normal" => Source(PpSourceMode::Normal),
         "identified" => Source(PpSourceMode::Identified),
-        "everybody_loops" => Source(PpSourceMode::EveryBodyLoops),
         "expanded" => Source(PpSourceMode::Expanded),
         "expanded,identified" => Source(PpSourceMode::ExpandedIdentified),
         "expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene),
@@ -2525,11 +2628,10 @@ fn parse_pretty(debugging_opts: &DebuggingOptions, efmt: ErrorOutputType) -> Opt
         name => early_error(
             efmt,
             &format!(
-                "argument to `unpretty` must be one of `normal`, \
-                            `expanded`, `identified`, `expanded,identified`, \
-                            `expanded,hygiene`, `everybody_loops`, \
+                "argument to `unpretty` must be one of `normal`, `identified`, \
+                            `expanded`, `expanded,identified`, `expanded,hygiene`, \
                             `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
-                            `hir,typed`, `hir-tree`, `mir` or `mir-cfg`; got {}",
+                            `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {}",
                 name
             ),
         ),
@@ -2645,8 +2747,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 pub enum PpSourceMode {
     /// `-Zunpretty=normal`
     Normal,
-    /// `-Zunpretty=everybody_loops`
-    EveryBodyLoops,
     /// `-Zunpretty=expanded`
     Expanded,
     /// `-Zunpretty=identified`
@@ -2678,7 +2778,7 @@ pub enum PpHirMode {
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpMode {
     /// Options that print the source code, i.e.
-    /// `-Zunpretty=normal` and `-Zunpretty=everybody_loops`
+    /// `-Zunpretty=normal` and `-Zunpretty=expanded`
     Source(PpSourceMode),
     AstTree(PpAstTreeMode),
     /// Options that print the HIR, i.e. `-Zunpretty=hir`
@@ -2700,7 +2800,7 @@ pub fn needs_ast_map(&self) -> bool {
         match *self {
             Source(Normal | Identified) | AstTree(PpAstTreeMode::Normal) => false,
 
-            Source(Expanded | EveryBodyLoops | ExpandedIdentified | ExpandedHygiene)
+            Source(Expanded | ExpandedIdentified | ExpandedHygiene)
             | AstTree(PpAstTreeMode::Expanded)
             | Hir(_)
             | HirTree
index c2b13346cd6c9cf6e939bebb29692669c2c3b6c6..c42a1530451d673f3d58df0dcf075713929673e0 100644 (file)
@@ -551,7 +551,7 @@ mod parse {
     crate fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool {
         match v.and_then(|s| s.parse().ok()) {
             Some(0) => {
-                *slot = ::num_cpus::get();
+                *slot = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get);
                 true
             }
             Some(i) => {
@@ -1491,7 +1491,6 @@ mod parse {
         `normal`, `identified`,
         `expanded`, `expanded,identified`,
         `expanded,hygiene` (with internal representations),
-        `everybody_loops` (all function bodies replaced with `loop {}`),
         `ast-tree` (raw AST before expansion),
         `ast-tree,expanded` (raw AST after expansion),
         `hir` (the HIR), `hir,identified`,
index 360682558a5ef0e7d34796991089e48542024e3d..eabebfcf3eae5145c17133b636d54596ab4f8a84 100644 (file)
@@ -331,6 +331,13 @@ pub fn struct_span_allow<S: Into<MultiSpan>>(
     pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_allow(msg)
     }
+    pub fn struct_expect(
+        &self,
+        msg: &str,
+        id: lint::LintExpectationId,
+    ) -> DiagnosticBuilder<'_, ()> {
+        self.diagnostic().struct_expect(msg, id)
+    }
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
index 5fae46d5fd89b52fa313df0209012bbbc9840175..86adfa7a18cdf7f5573a7067833566d6c298c847 100644 (file)
@@ -85,10 +85,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     /// A unique ID associated with a macro invocation and expansion.
     pub struct LocalExpnId {
         ENCODABLE = custom
+        ORD_IMPL = custom
         DEBUG_FORMAT = "expn{}"
     }
 }
 
+// To ensure correctness of incremental compilation,
+// `LocalExpnId` must not implement `Ord` or `PartialOrd`.
+// See https://github.com/rust-lang/rust/issues/90317.
+impl !Ord for LocalExpnId {}
+impl !PartialOrd for LocalExpnId {}
+
 /// Assert that the provided `HashStableContext` is configured with the 'default'
 /// `HashingControls`. We should always have bailed out before getting to here
 /// with a non-default mode. With this check in place, we can avoid the need
index 6767593bbc51a8ce455cd8daec8e5d5cbb57db0e..3f44292e03425ad301d7806ef215ceea12088ef0 100644 (file)
         custom_inner_attributes,
         custom_test_frameworks,
         d,
+        d32,
         dbg_macro,
         dead_code,
         dealloc,
         proc_macro_path_invoc,
         profiler_builtins,
         profiler_runtime,
+        ptr,
         ptr_guaranteed_eq,
         ptr_guaranteed_ne,
         ptr_null,
index 62b5436142f5a35bafd3a418017718bd10429337..a9c41ce0c4ea4033bdfecb76bd9c261cafd5eff2 100644 (file)
@@ -633,8 +633,9 @@ fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error
                         // The `inspect` here is okay since we checked the bounds, and there are no
                         // relocations (we have an active `str` reference here). We don't use this
                         // result to affect interpreter execution.
-                        let slice =
-                            data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
+                        let slice = data
+                            .inner()
+                            .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
                         let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
 
                         self.push("e");
index 4ef863712983f802b793c2f87c717e08c5e39cfc..fb5e0272cc359c36e5273fa685b17eb45fcdc966 100644 (file)
@@ -10,6 +10,7 @@
 use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
+use rustc_data_structures::intern::Interned;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::json::{Json, ToJson};
@@ -1024,7 +1025,7 @@ pub struct VariantIdx {
 }
 
 #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum Variants {
+pub enum Variants<'a> {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single { index: VariantIdx },
 
@@ -1038,7 +1039,7 @@ pub enum Variants {
         tag: Scalar,
         tag_encoding: TagEncoding,
         tag_field: usize,
-        variants: IndexVec<VariantIdx, Layout>,
+        variants: IndexVec<VariantIdx, Layout<'a>>,
     },
 }
 
@@ -1146,8 +1147,8 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
     }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub struct Layout {
+#[derive(PartialEq, Eq, Hash, HashStable_Generic)]
+pub struct LayoutS<'a> {
     /// Says where the fields are located within the layout.
     pub fields: FieldsShape,
 
@@ -1158,7 +1159,7 @@ pub struct Layout {
     ///
     /// To access all fields of this layout, both `fields` and the fields of the active variant
     /// must be taken into account.
-    pub variants: Variants,
+    pub variants: Variants<'a>,
 
     /// The `abi` defines how this data is passed between functions, and it defines
     /// value restrictions via `valid_range`.
@@ -1177,12 +1178,12 @@ pub struct Layout {
     pub size: Size,
 }
 
-impl Layout {
+impl<'a> LayoutS<'a> {
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
         let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
         let size = scalar.value.size(cx);
         let align = scalar.value.align(cx);
-        Layout {
+        LayoutS {
             variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Primitive,
             abi: Abi::Scalar(scalar),
@@ -1193,6 +1194,59 @@ pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
     }
 }
 
+impl<'a> fmt::Debug for LayoutS<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This is how `Layout` used to print before it become
+        // `Interned<LayoutS>`. We print it like this to avoid having to update
+        // expected output in a lot of tests.
+        f.debug_struct("Layout")
+            .field("fields", &self.fields)
+            .field("variants", &self.variants)
+            .field("abi", &self.abi)
+            .field("largest_niche", &self.largest_niche)
+            .field("align", &self.align)
+            .field("size", &self.size)
+            .finish()
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
+#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
+pub struct Layout<'a>(pub Interned<'a, LayoutS<'a>>);
+
+impl<'a> fmt::Debug for Layout<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // See comment on `<LayoutS as Debug>::fmt` above.
+        self.0.0.fmt(f)
+    }
+}
+
+impl<'a> Layout<'a> {
+    pub fn fields(self) -> &'a FieldsShape {
+        &self.0.0.fields
+    }
+
+    pub fn variants(self) -> &'a Variants<'a> {
+        &self.0.0.variants
+    }
+
+    pub fn abi(self) -> Abi {
+        self.0.0.abi
+    }
+
+    pub fn largest_niche(self) -> Option<Niche> {
+        self.0.0.largest_niche
+    }
+
+    pub fn align(self) -> AbiAndPrefAlign {
+        self.0.0.align
+    }
+
+    pub fn size(self) -> Size {
+        self.0.0.size
+    }
+}
+
 /// The layout of a type, alongside the type itself.
 /// Provides various type traversal APIs (e.g., recursing into fields).
 ///
@@ -1203,13 +1257,13 @@ pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
 pub struct TyAndLayout<'a, Ty> {
     pub ty: Ty,
-    pub layout: &'a Layout,
+    pub layout: Layout<'a>,
 }
 
 impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
-    type Target = &'a Layout;
-    fn deref(&self) -> &&'a Layout {
-        &self.layout
+    type Target = &'a LayoutS<'a>;
+    fn deref(&self) -> &&'a LayoutS<'a> {
+        &self.layout.0.0
     }
 }
 
index 88f2d3f80d2c38d352d19fdcb7b2a18c99d1b122..aaa632333db3808b993e4d714baa66425f771207 100644 (file)
@@ -50,9 +50,12 @@ pub fn supported_types(
         match self {
             Self::reg => types! { _: I8, I16, I32, F32; },
             Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; },
-            Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! {
+            Self::dreg_low16 | Self::dreg_low8 => types! {
                 vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
             },
+            Self::dreg => types! {
+                d32: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
+            },
             Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! {
                 neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
             },
index 2919743e4996fa12e9d65f7f2df4a5da3b5a7b8c..e9ef71ede51821469a6d3840fc8b26ef055de3b5 100644 (file)
@@ -8,13 +8,14 @@
 //! LLVM.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(bool_to_option)]
-#![feature(let_else)]
-#![feature(nll)]
-#![feature(never_type)]
 #![feature(associated_type_bounds)]
+#![feature(bool_to_option)]
 #![feature(exhaustive_patterns)]
+#![feature(let_else)]
 #![feature(min_specialization)]
+#![feature(never_type)]
+#![feature(nll)]
+#![feature(rustc_attrs)]
 #![feature(step_trait)]
 
 use std::iter::FromIterator;
index 5692925f63beb2057fe5841634de915cad2e0898..87696b3664cfe235ac27725a45cef0aa80b4c7ab 100644 (file)
@@ -16,7 +16,8 @@ pub fn target() -> Target {
             features: "+neon,+fp-armv8".to_string(),
             supported_sanitizers: SanitizerSet::CFI
                 | SanitizerSet::HWADDRESS
-                | SanitizerSet::MEMTAG,
+                | SanitizerSet::MEMTAG
+                | SanitizerSet::ADDRESS,
             ..super::android_base::opts()
         },
     }
index 9b5366c576ec6a30b54b0113d61b509a300fb841..933b43986c9978fbbdbd7cde24bb169b901ab031 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
@@ -10,6 +10,7 @@ pub fn target() -> Target {
             abi: "eabi".to_string(),
             // https://developer.android.com/ndk/guides/abis.html#armeabi
             features: "+strict-align,+v5te".to_string(),
+            supported_sanitizers: SanitizerSet::ADDRESS,
             max_atomic_width: Some(32),
             ..super::android_base::opts()
         },
index 55956f3bad4fa7cad5be88bb6b8c4b2aa6977ada..adf831c12eb4bd0893ea3b932ab32e196c1fdb01 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
 
 // This target if is for the baseline of the Android v7a ABI
 // in thumb mode. It's named armv7-* instead of thumbv7-*
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             abi: "eabi".to_string(),
             features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(),
+            supported_sanitizers: SanitizerSet::ADDRESS,
             max_atomic_width: Some(64),
             ..base
         },
index 640f9e42f4ab1c19ea5d990e1cc8559e4bb2ee72..e9ddaa37c262c42cfa1bc99bc2f4d2569e4f6dc6 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{StackProbeType, Target};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions};
 
 // See https://developer.android.com/ndk/guides/abis.html#x86
 // for target ABI requirements.
@@ -21,6 +21,6 @@ pub fn target() -> Target {
             f64:32:64-f80:32-n8:16:32-S128"
             .to_string(),
         arch: "x86".to_string(),
-        options: base,
+        options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
     }
 }
index 92678aed5b1a291dcc0fd808793f90e30e22668c..ca5f2b4af8a97a0860d438bcec65a3af1b400932 100644 (file)
@@ -186,12 +186,16 @@ pub fn desc(&self) -> &str {
         }
     }
 
-    pub fn desc_symbol(&self) -> Symbol {
+    pub const fn desc_symbol(&self) -> Symbol {
         match *self {
             PanicStrategy::Unwind => sym::unwind,
             PanicStrategy::Abort => sym::abort,
         }
     }
+
+    pub const fn all() -> [Symbol; 2] {
+        [Self::Abort.desc_symbol(), Self::Unwind.desc_symbol()]
+    }
 }
 
 impl ToJson for PanicStrategy {
@@ -614,7 +618,7 @@ impl SanitizerSet {
     /// Return sanitizer's name
     ///
     /// Returns none if the flags is a set of sanitizers numbering not exactly one.
-    fn as_str(self) -> Option<&'static str> {
+    pub fn as_str(self) -> Option<&'static str> {
         Some(match self {
             SanitizerSet::ADDRESS => "address",
             SanitizerSet::CFI => "cfi",
@@ -2137,6 +2141,18 @@ macro_rules! key {
         ))
     }
 
+    /// Load a built-in target
+    pub fn expect_builtin(target_triple: &TargetTriple) -> Target {
+        match *target_triple {
+            TargetTriple::TargetTriple(ref target_triple) => {
+                load_builtin(target_triple).expect("built-in target")
+            }
+            TargetTriple::TargetPath(..) => {
+                panic!("built-in targets doens't support target-paths")
+            }
+        }
+    }
+
     /// Search for a JSON file specifying the given target triple.
     ///
     /// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the
index 9065283b731ee79c3132225de8c1a80f517fc666..657520a8cafd1210f6afa24148e8ba86f7f17101 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::android_base::opts();
@@ -16,6 +16,6 @@ pub fn target() -> Target {
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .to_string(),
         arch: "x86_64".to_string(),
-        options: base,
+        options: TargetOptions { supported_sanitizers: SanitizerSet::ADDRESS, ..base },
     }
 }
index 018d1eefef7d289e6dba87c9fa62f626eb0b4282..63efa951f9674717f5af28044c85678c20160027 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::TraitEngine;
 use rustc_middle::traits::specialization_graph::OverlapMode;
-use rustc_middle::ty::fast_reject::{self, SimplifyParams};
+use rustc_middle::ty::fast_reject::{self, TreatParams};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -87,8 +87,8 @@ pub fn overlapping_impls<F1, F2, R>(
         impl2_ref.iter().flat_map(|tref| tref.substs.types()),
     )
     .any(|(ty1, ty2)| {
-        let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No);
-        let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No);
+        let t1 = fast_reject::simplify_type(tcx, ty1, TreatParams::AsPlaceholders);
+        let t2 = fast_reject::simplify_type(tcx, ty2, TreatParams::AsPlaceholders);
 
         if let (Some(t1), Some(t2)) = (t1, t2) {
             // Simplified successfully
index a277f74f7a43fbf8bb6a17c247390eeaedeb4e0b..6dfbdace8e2a0f9a76262c2c17a67778578434a8 100644 (file)
@@ -4,7 +4,7 @@
 use crate::infer::InferCtxt;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::Subst;
+use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind};
 use rustc_span::symbol::sym;
 use std::iter;
@@ -17,7 +17,7 @@ fn impl_similar_to(
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
-    ) -> Option<DefId>;
+    ) -> Option<(DefId, SubstsRef<'tcx>)>;
 
     /*private*/
     fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>;
@@ -34,7 +34,7 @@ fn impl_similar_to(
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
-    ) -> Option<DefId> {
+    ) -> Option<(DefId, SubstsRef<'tcx>)> {
         let tcx = self.tcx;
         let param_env = obligation.param_env;
         let trait_ref = tcx.erase_late_bound_regions(trait_ref);
@@ -50,7 +50,7 @@ fn impl_similar_to(
             let impl_self_ty = impl_trait_ref.self_ty();
 
             if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
-                self_match_impls.push(def_id);
+                self_match_impls.push((def_id, impl_substs));
 
                 if iter::zip(
                     trait_ref.substs.types().skip(1),
@@ -58,12 +58,12 @@ fn impl_similar_to(
                 )
                 .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
                 {
-                    fuzzy_match_impls.push(def_id);
+                    fuzzy_match_impls.push((def_id, impl_substs));
                 }
             }
         });
 
-        let impl_def_id = if self_match_impls.len() == 1 {
+        let impl_def_id_and_substs = if self_match_impls.len() == 1 {
             self_match_impls[0]
         } else if fuzzy_match_impls.len() == 1 {
             fuzzy_match_impls[0]
@@ -71,7 +71,8 @@ fn impl_similar_to(
             return None;
         };
 
-        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
+        tcx.has_attr(impl_def_id_and_substs.0, sym::rustc_on_unimplemented)
+            .then_some(impl_def_id_and_substs)
     }
 
     /// Used to set on_unimplemented's `ItemContext`
@@ -120,8 +121,9 @@ fn on_unimplemented_note(
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
     ) -> OnUnimplementedNote {
-        let def_id =
-            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
+        let (def_id, substs) = self
+            .impl_similar_to(trait_ref, obligation)
+            .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
         let trait_ref = trait_ref.skip_binder();
 
         let mut flags = vec![(
@@ -176,7 +178,7 @@ fn on_unimplemented_note(
             for param in generics.params.iter() {
                 let value = match param.kind {
                     GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
-                        trait_ref.substs[param.index as usize].to_string()
+                        substs[param.index as usize].to_string()
                     }
                     GenericParamDefKind::Lifetime => continue,
                 };
@@ -184,7 +186,7 @@ fn on_unimplemented_note(
                 flags.push((name, Some(value)));
 
                 if let GenericParamDefKind::Type { .. } = param.kind {
-                    let param_ty = trait_ref.substs[param.index as usize].expect_ty();
+                    let param_ty = substs[param.index as usize].expect_ty();
                     if let Some(def) = param_ty.ty_adt_def() {
                         // We also want to be able to select the parameter's
                         // original signature with no type arguments resolved
@@ -229,9 +231,7 @@ fn on_unimplemented_note(
             }
         });
 
-        if let Ok(Some(command)) =
-            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
-        {
+        if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
             command.evaluate(self.tcx, trait_ref, &flags)
         } else {
             OnUnimplementedNote::default()
index b194e6a6d89f31f6624264677f9cfbe46f3dea18..f2ddc3ea7fa3909eebfebdd593ef60acc0fbf0a1 100644 (file)
@@ -405,7 +405,7 @@ fn suggest_restricting_param_bound(
                 }
                 hir::Node::Item(hir::Item {
                     kind:
-                        hir::ItemKind::Trait(_, _, generics, _, _)
+                        hir::ItemKind::Trait(_, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. }),
                     ..
                 }) if projection.is_some() => {
index b4b2e4cd0422933837ac9f29520d39df7e7948bb..62c6c8454797a8f9592a5207a19b55e4b6761739 100644 (file)
@@ -346,6 +346,8 @@ fn process_changed_obligations(
 
         let obligation = &mut pending_obligation.obligation;
 
+        debug!(?obligation, "process_obligation pre-resolve");
+
         if obligation.predicate.has_infer_types_or_consts() {
             obligation.predicate =
                 self.selcx.infcx().resolve_vars_if_possible(obligation.predicate);
@@ -355,6 +357,21 @@ fn process_changed_obligations(
 
         let infcx = self.selcx.infcx();
 
+        if obligation.predicate.has_projections() {
+            let mut obligations = Vec::new();
+            let predicate = crate::traits::project::try_normalize_with_depth_to(
+                self.selcx,
+                obligation.param_env,
+                obligation.cause.clone(),
+                obligation.recursion_depth + 1,
+                obligation.predicate,
+                &mut obligations,
+            );
+            if predicate != obligation.predicate {
+                obligations.push(obligation.with(predicate));
+                return ProcessResult::Changed(mk_pending(obligations));
+            }
+        }
         let binder = obligation.predicate.kind();
         match binder.no_bound_vars() {
             None => match binder.skip_binder() {
index 9752ff453235ad0572ca1ac6d92a2426d5cb178a..2f697c1fa27b79e3eb4f7d2a902a9a24f520fb5f 100644 (file)
@@ -54,7 +54,7 @@ fn parse_error(
 impl<'tcx> OnUnimplementedDirective {
     fn parse(
         tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
+        item_def_id: DefId,
         items: &[NestedMetaItem],
         span: Span,
         is_root: bool,
@@ -63,7 +63,7 @@ fn parse(
         let mut item_iter = items.iter();
 
         let parse_value = |value_str| {
-            OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
+            OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some)
         };
 
         let condition = if is_root {
@@ -135,7 +135,7 @@ fn parse(
             {
                 if let Some(items) = item.meta_item_list() {
                     if let Ok(subcommand) =
-                        Self::parse(tcx, trait_def_id, &items, item.span(), false)
+                        Self::parse(tcx, item_def_id, &items, item.span(), false)
                     {
                         subcommands.push(subcommand);
                     } else {
@@ -178,19 +178,15 @@ fn parse(
         }
     }
 
-    pub fn of_item(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        impl_def_id: DefId,
-    ) -> Result<Option<Self>, ErrorGuaranteed> {
-        let attrs = tcx.get_attrs(impl_def_id);
+    pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> {
+        let attrs = tcx.get_attrs(item_def_id);
 
         let Some(attr) = tcx.sess.find_by_name(&attrs, sym::rustc_on_unimplemented) else {
             return Ok(None);
         };
 
         let result = if let Some(items) = attr.meta_item_list() {
-            Self::parse(tcx, trait_def_id, &items, attr.span, true).map(Some)
+            Self::parse(tcx, item_def_id, &items, attr.span, true).map(Some)
         } else if let Some(value) = attr.value_str() {
             Ok(Some(OnUnimplementedDirective {
                 condition: None,
@@ -198,7 +194,7 @@ pub fn of_item(
                 subcommands: vec![],
                 label: Some(OnUnimplementedFormatString::try_parse(
                     tcx,
-                    trait_def_id,
+                    item_def_id,
                     value,
                     attr.span,
                 )?),
@@ -209,7 +205,7 @@ pub fn of_item(
         } else {
             return Err(ErrorGuaranteed);
         };
-        debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
+        debug!("of_item({:?}) = {:?}", item_def_id, result);
         result
     }
 
@@ -280,23 +276,29 @@ pub fn evaluate(
 impl<'tcx> OnUnimplementedFormatString {
     fn try_parse(
         tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
+        item_def_id: DefId,
         from: Symbol,
         err_sp: Span,
     ) -> Result<Self, ErrorGuaranteed> {
         let result = OnUnimplementedFormatString(from);
-        result.verify(tcx, trait_def_id, err_sp)?;
+        result.verify(tcx, item_def_id, err_sp)?;
         Ok(result)
     }
 
     fn verify(
         &self,
         tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
+        item_def_id: DefId,
         span: Span,
     ) -> Result<(), ErrorGuaranteed> {
-        let name = tcx.item_name(trait_def_id);
-        let generics = tcx.generics_of(trait_def_id);
+        let trait_def_id = if tcx.is_trait(item_def_id) {
+            item_def_id
+        } else {
+            tcx.trait_id_of_impl(item_def_id)
+                .expect("expected `on_unimplemented` to correspond to a trait")
+        };
+        let trait_name = tcx.item_name(trait_def_id);
+        let generics = tcx.generics_of(item_def_id);
         let s = self.0.as_str();
         let parser = Parser::new(s, None, None, false, ParseMode::Format);
         let mut result = Ok(());
@@ -307,7 +309,7 @@ fn verify(
                     // `{Self}` is allowed
                     Position::ArgumentNamed(s, _) if s == kw::SelfUpper => (),
                     // `{ThisTraitsName}` is allowed
-                    Position::ArgumentNamed(s, _) if s == name => (),
+                    Position::ArgumentNamed(s, _) if s == trait_name => (),
                     // `{from_method}` is allowed
                     Position::ArgumentNamed(s, _) if s == sym::from_method => (),
                     // `{from_desugaring}` is allowed
@@ -329,9 +331,13 @@ fn verify(
                                     tcx.sess,
                                     span,
                                     E0230,
-                                    "there is no parameter `{}` on trait `{}`",
+                                    "there is no parameter `{}` on {}",
                                     s,
-                                    name
+                                    if trait_def_id == item_def_id {
+                                        format!("trait `{}`", trait_name)
+                                    } else {
+                                        "impl".to_string()
+                                    }
                                 )
                                 .emit();
                                 result = Err(ErrorGuaranteed);
index c32c73c6384127b9a82ec9b57ab7193ae16cf692..ea48fab1cebb88b00b12a59bf48d6fba82fd95ab 100644 (file)
@@ -295,6 +295,32 @@ pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
     result
 }
 
+#[instrument(level = "info", skip(selcx, param_env, cause, obligations))]
+pub fn try_normalize_with_depth_to<'a, 'b, 'tcx, T>(
+    selcx: &'a mut SelectionContext<'b, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: usize,
+    value: T,
+    obligations: &mut Vec<PredicateObligation<'tcx>>,
+) -> T
+where
+    T: TypeFoldable<'tcx>,
+{
+    debug!(obligations.len = obligations.len());
+    let mut normalizer = AssocTypeNormalizer::new_without_eager_inference_replacement(
+        selcx,
+        param_env,
+        cause,
+        depth,
+        obligations,
+    );
+    let result = ensure_sufficient_stack(|| normalizer.fold(value));
+    debug!(?result, obligations.len = normalizer.obligations.len());
+    debug!(?normalizer.obligations,);
+    result
+}
+
 pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool {
     match reveal {
         Reveal::UserFacing => value
@@ -314,6 +340,10 @@ struct AssocTypeNormalizer<'a, 'b, 'tcx> {
     obligations: &'a mut Vec<PredicateObligation<'tcx>>,
     depth: usize,
     universes: Vec<Option<ty::UniverseIndex>>,
+    /// If true, when a projection is unable to be completed, an inference
+    /// variable will be created and an obligation registered to project to that
+    /// inference variable. Also, constants will be eagerly evaluated.
+    eager_inference_replacement: bool,
 }
 
 impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
@@ -324,7 +354,33 @@ fn new(
         depth: usize,
         obligations: &'a mut Vec<PredicateObligation<'tcx>>,
     ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
-        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes: vec![] }
+        AssocTypeNormalizer {
+            selcx,
+            param_env,
+            cause,
+            obligations,
+            depth,
+            universes: vec![],
+            eager_inference_replacement: true,
+        }
+    }
+
+    fn new_without_eager_inference_replacement(
+        selcx: &'a mut SelectionContext<'b, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        cause: ObligationCause<'tcx>,
+        depth: usize,
+        obligations: &'a mut Vec<PredicateObligation<'tcx>>,
+    ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
+        AssocTypeNormalizer {
+            selcx,
+            param_env,
+            cause,
+            obligations,
+            depth,
+            universes: vec![],
+            eager_inference_replacement: false,
+        }
     }
 
     fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
@@ -428,14 +484,28 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 // there won't be bound vars there.
 
                 let data = data.super_fold_with(self);
-                let normalized_ty = normalize_projection_type(
-                    self.selcx,
-                    self.param_env,
-                    data,
-                    self.cause.clone(),
-                    self.depth,
-                    &mut self.obligations,
-                );
+                let normalized_ty = if self.eager_inference_replacement {
+                    normalize_projection_type(
+                        self.selcx,
+                        self.param_env,
+                        data,
+                        self.cause.clone(),
+                        self.depth,
+                        &mut self.obligations,
+                    )
+                } else {
+                    opt_normalize_projection_type(
+                        self.selcx,
+                        self.param_env,
+                        data,
+                        self.cause.clone(),
+                        self.depth,
+                        &mut self.obligations,
+                    )
+                    .ok()
+                    .flatten()
+                    .unwrap_or_else(|| ty::Term::Ty(ty.super_fold_with(self)))
+                };
                 debug!(
                     ?self.depth,
                     ?ty,
@@ -501,7 +571,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if self.selcx.tcx().lazy_normalization() {
+        if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
             constant
         } else {
             let constant = constant.super_fold_with(self);
index 092ef5f11e9a2357758cca9cbb19a4d0c5db888b..8af4606db85200eec7d87ecd70e71776ee725ffe 100644 (file)
@@ -36,7 +36,7 @@
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::abstract_const::NotConstEvaluatable;
-use rustc_middle::ty::fast_reject::{self, SimplifyParams};
+use rustc_middle::ty::fast_reject::{self, TreatParams};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
@@ -2176,8 +2176,8 @@ fn match_impl(
 
     fn fast_reject_trait_refs(
         &mut self,
-        obligation: &TraitObligation<'_>,
-        impl_trait_ref: &ty::TraitRef<'_>,
+        obligation: &TraitObligation<'tcx>,
+        impl_trait_ref: &ty::TraitRef<'tcx>,
     ) -> bool {
         // We can avoid creating type variables and doing the full
         // substitution if we find that any of the input types, when
@@ -2193,10 +2193,13 @@ fn fast_reject_trait_refs(
                         let simplified_obligation_ty = fast_reject::simplify_type(
                             self.tcx(),
                             obligation_ty,
-                            SimplifyParams::Yes,
+                            TreatParams::AsBoundTypes,
+                        );
+                        let simplified_impl_ty = fast_reject::simplify_type(
+                            self.tcx(),
+                            impl_ty,
+                            TreatParams::AsPlaceholders,
                         );
-                        let simplified_impl_ty =
-                            fast_reject::simplify_type(self.tcx(), impl_ty, SimplifyParams::No);
 
                         simplified_obligation_ty.is_some()
                             && simplified_impl_ty.is_some()
index e31a9b200e873c5069a2c3981c03472b48ef5319..8b23dcfe3808abce209899d91b369e28e7dfd85f 100644 (file)
@@ -2,7 +2,7 @@
 
 use crate::traits;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams};
+use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 
@@ -49,7 +49,9 @@ impl ChildrenExt<'_> for Children {
     /// Insert an impl into this set of children without comparing to any existing impls.
     fn insert_blindly(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), SimplifyParams::No) {
+        if let Some(st) =
+            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsPlaceholders)
+        {
             debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
             self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
         } else {
@@ -64,7 +66,9 @@ fn insert_blindly(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) {
     fn remove_existing(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
         let vec: &mut Vec<DefId>;
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), SimplifyParams::No) {
+        if let Some(st) =
+            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsPlaceholders)
+        {
             debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
             vec = self.non_blanket_impls.get_mut(&st).unwrap();
         } else {
@@ -312,7 +316,8 @@ fn insert(
 
         let mut parent = trait_def_id;
         let mut last_lint = None;
-        let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), SimplifyParams::No);
+        let simplified =
+            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsPlaceholders);
 
         // Descend the specialization tree, where `parent` is the current parent node.
         loop {
index 765b752691f231eb94db144368a2a5e88f03b28d..7c3594175b85508ed4c10ac92fc306d6cbf79d52 100644 (file)
@@ -742,12 +742,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                     impl_trait_ref,
                     &impl_.items,
                 );
-                let trait_def_id = impl_trait_ref.def_id;
-                check_on_unimplemented(tcx, trait_def_id, it);
+                check_on_unimplemented(tcx, it);
             }
         }
         hir::ItemKind::Trait(_, _, _, _, ref items) => {
-            check_on_unimplemented(tcx, it.def_id.to_def_id(), it);
+            check_on_unimplemented(tcx, it);
 
             for item in items.iter() {
                 let item = tcx.hir().trait_item(item.id);
@@ -857,9 +856,9 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
     }
 }
 
-pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item<'_>) {
+pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     // an error would be reported if this fails.
-    let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item.def_id.to_def_id());
+    let _ = traits::OnUnimplementedDirective::of_item(tcx, item.def_id.to_def_id());
 }
 
 pub(super) fn check_specialization_validity<'tcx>(
index 8e245beaa3db073a2af3fcbda35e07b3e4becb6f..7e7104f62fdc67588d58a2b91cf844d982422644 100644 (file)
@@ -43,7 +43,6 @@
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable};
 use rustc_session::parse::feature_err;
-use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
@@ -2010,8 +2009,7 @@ fn ban_nonexisting_field(
             // We know by construction that `<expr>.await` is either on Rust 2015
             // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
             err.note("to `.await` a `Future`, switch to Rust 2018 or later");
-            err.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
-            err.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
+            err.help_use_latest_edition();
         }
 
         err.emit();
index fed3aac6da3fd39449088234840675d92eabe43c..b3213451d76c43049bddb5ecef655d312455c6a5 100644 (file)
@@ -315,11 +315,14 @@ pub fn apply_adjustments(&self, expr: &hir::Expr<'_>, adj: Vec<Adjustment<'tcx>>
                     }
                     // FIXME: currently we never try to compose autoderefs
                     // and ReifyFnPointer/UnsafeFnPointer, but we could.
-                    _ => bug!(
-                        "while adjusting {:?}, can't compose {:?} and {:?}",
-                        expr,
-                        entry.get(),
-                        adj
+                    _ => self.tcx.sess.delay_span_bug(
+                        expr.span,
+                        &format!(
+                            "while adjusting {:?}, can't compose {:?} and {:?}",
+                            expr,
+                            entry.get(),
+                            adj
+                        ),
                     ),
                 };
                 *entry.get_mut() = adj;
@@ -1400,7 +1403,7 @@ fn inferred_kind(
                             self.fcx.var_for_def(self.span, param)
                         }
                     }
-                    GenericParamDefKind::Const { has_default, .. } => {
+                    GenericParamDefKind::Const { has_default } => {
                         if !infer_args && has_default {
                             tcx.const_param_default(param.def_id)
                                 .subst_spanned(tcx, substs.unwrap(), Some(self.span))
index 3dfee99b83599f0e97edbe82f2c45a13b2148107..f165093c958dba28ffcfcd499828aadf6a9f4beb 100644 (file)
@@ -234,11 +234,6 @@ pub(in super::super) fn check_argument_types(
         // This is more complicated than just checking type equality, as arguments could be coerced
         // This version writes those types back so further type checking uses the narrowed types
         let demand_compatible = |idx, final_arg_types: &mut Vec<Option<(Ty<'tcx>, Ty<'tcx>)>>| {
-            // Do not check argument compatibility if the number of args do not match
-            if arg_count_error.is_some() {
-                return;
-            }
-
             let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
             let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
             let provided_arg = &provided_args[idx];
@@ -286,6 +281,8 @@ pub(in super::super) fn check_argument_types(
             self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty);
         };
 
+        let minimum_input_count = formal_input_tys.len();
+
         // Check the arguments.
         // We do this in a pretty awful way: first we type-check any arguments
         // that are not closures, then we type-check the closures. This is so
@@ -308,7 +305,6 @@ pub(in super::super) fn check_argument_types(
                 })
             }
 
-            let minimum_input_count = formal_input_tys.len();
             for (idx, arg) in provided_args.iter().enumerate() {
                 // Warn only for the first loop (the "no closures" one).
                 // Closure arguments themselves can't be diverging, but
@@ -461,17 +457,18 @@ pub(in super::super) fn check_argument_types(
             err.emit();
         }
 
-        // We also need to make sure we at least write the ty of the other
-        // arguments which we skipped above.
-        if c_variadic {
-            fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
-                use crate::structured_errors::MissingCastForVariadicArg;
+        for arg in provided_args.iter().skip(minimum_input_count) {
+            let arg_ty = self.check_expr(&arg);
 
-                MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
-            }
+            if c_variadic {
+                // We also need to make sure we at least write the ty of the other
+                // arguments which we skipped above, either because they were additional
+                // c_variadic args, or because we had an argument count mismatch.
+                fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
+                    use crate::structured_errors::MissingCastForVariadicArg;
 
-            for arg in provided_args.iter().skip(expected_arg_count) {
-                let arg_ty = self.check_expr(&arg);
+                    MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
+                }
 
                 // There are a few types which get autopromoted when passed via varargs
                 // in C but we just error out instead and require explicit casts.
index 03d3b23bb23d5cc35d4f6ab5e048bd338c401ef2..40ee6d863b5a7043fed064be998a6b635ae87159 100644 (file)
@@ -6,14 +6,14 @@
 use hir::{def_id::DefId, Body, HirId, HirIdMap};
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_hir as hir;
-use rustc_middle::hir::map::Map;
+use rustc_middle::ty::{ParamEnv, TyCtxt};
 
 pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
     fcx: &'a FnCtxt<'a, 'tcx>,
     def_id: DefId,
     body: &'tcx Body<'tcx>,
 ) -> ConsumedAndBorrowedPlaces {
-    let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx.hir());
+    let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx, fcx.param_env);
     expr_use_visitor.consume_body(fcx, def_id, body);
     expr_use_visitor.places
 }
@@ -36,14 +36,16 @@ pub(super) struct ConsumedAndBorrowedPlaces {
 /// Interesting values are those that are either dropped or borrowed. For dropped values, we also
 /// record the parent expression, which is the point where the drop actually takes place.
 struct ExprUseDelegate<'tcx> {
-    hir: Map<'tcx>,
+    tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
     places: ConsumedAndBorrowedPlaces,
 }
 
 impl<'tcx> ExprUseDelegate<'tcx> {
-    fn new(hir: Map<'tcx>) -> Self {
+    fn new(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
         Self {
-            hir,
+            tcx,
+            param_env,
             places: ConsumedAndBorrowedPlaces {
                 consumed: <_>::default(),
                 borrowed: <_>::default(),
@@ -77,7 +79,7 @@ fn consume(
         place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
         diag_expr_id: HirId,
     ) {
-        let parent = match self.hir.find_parent_node(place_with_id.hir_id) {
+        let parent = match self.tcx.hir().find_parent_node(place_with_id.hir_id) {
             Some(parent) => parent,
             None => place_with_id.hir_id,
         };
@@ -107,11 +109,22 @@ fn mutate(
         assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
         diag_expr_id: HirId,
     ) {
-        debug!("mutate {:?}; diag_expr_id={:?}", assignee_place, diag_expr_id);
-        // Count mutations as a borrow.
-        self.places
-            .borrowed
-            .insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
+        debug!("mutate {assignee_place:?}; diag_expr_id={diag_expr_id:?}");
+        // If the type being assigned needs dropped, then the mutation counts as a borrow
+        // since it is essentially doing `Drop::drop(&mut x); x = new_value;`.
+        if assignee_place.place.base_ty.needs_drop(self.tcx, self.param_env) {
+            self.places
+                .borrowed
+                .insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
+        }
+    }
+
+    fn bind(
+        &mut self,
+        binding_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
+        diag_expr_id: HirId,
+    ) {
+        debug!("bind {binding_place:?}; diag_expr_id={diag_expr_id:?}");
     }
 
     fn fake_read(
index 1a345a303caea04d87e0704b02e1557584fd8805..0ae2dfa180b9eaaf940ca348cd98afd21bf80ff7 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::traits::util::supertraits;
-use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams};
+use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
 use rustc_middle::ty::ToPolyTraitRef;
 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
@@ -1777,7 +1777,8 @@ fn suggest_traits_to_import(
                 // FIXME: Even though negative bounds are not implemented, we could maybe handle
                 // cases where a positive bound implies a negative impl.
                 (candidates, Vec::new())
-            } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes)
+            } else if let Some(simp_rcvr_ty) =
+                simplify_type(self.tcx, rcvr_ty, TreatParams::AsBoundTypes)
             {
                 let mut potential_candidates = Vec::new();
                 let mut explicitly_negative = Vec::new();
@@ -1792,7 +1793,7 @@ fn suggest_traits_to_import(
                         .any(|imp_did| {
                             let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
                             let imp_simp =
-                                simplify_type(self.tcx, imp.self_ty(), SimplifyParams::Yes);
+                                simplify_type(self.tcx, imp.self_ty(), TreatParams::AsBoundTypes);
                             imp_simp.map_or(false, |s| s == simp_rcvr_ty)
                         })
                     {
index e2a91635a2d8b5f54bfee480833fde095e72824e..4c0eab51c355833decf4392b29e624345c2921a9 100644 (file)
@@ -553,7 +553,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: S
     // the consumer's responsibility to ensure all bytes that have been read
     // have defined values.
     if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) {
-        if alloc.relocations().len() != 0 {
+        if alloc.inner().relocations().len() != 0 {
             let msg = "statics with a custom `#[link_section]` must be a \
                            simple list of bytes on the wasm target with no \
                            extra levels of indirection such as references";
index f45cd3ed68948655ec3304aeec7ddc3d9413f2b1..1826c3f5f7fa506ea806d7546b90b3c881b7b35f 100644 (file)
@@ -82,8 +82,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
             // The `def_id` here actually was calculated during resolution (at least
             // at the time of this writing) and is being shipped to us via a side
             // channel of the tcx. There may have been extra expansion phases,
-            // however, which ended up removing the `def_id` *after* expansion such
-            // as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
+            // however, which ended up removing the `def_id` *after* expansion.
             //
             // As a result we need to verify that `def_id` is indeed still valid for
             // our AST and actually present in the HIR map. If it's not there then
index db1c80ae433b20de2a320f81fa66aaa720cb0826..8c19bbd3214eea75bec1513f8aa9ea23656010eb 100644 (file)
@@ -51,6 +51,15 @@ fn borrow(
     /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
     fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
 
+    /// The path at `binding_place` is a binding that is being initialized.
+    ///
+    /// This covers cases such as `let x = 42;`
+    fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
+        // Bindings can normally be treated as a regular assignment, so by default we
+        // forward this to the mutate callback.
+        self.mutate(binding_place, diag_expr_id)
+    }
+
     /// The `place` should be a fake read because of specified `cause`.
     fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId);
 }
@@ -648,11 +657,9 @@ fn walk_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) {
                     let pat_ty = return_if_err!(mc.node_ty(pat.hir_id));
                     debug!("walk_pat: pat_ty={:?}", pat_ty);
 
-                    // Each match binding is effectively an assignment to the
-                    // binding being produced.
                     let def = Res::Local(canonical_id);
                     if let Ok(ref binding_place) = mc.cat_res(pat.hir_id, pat.span, pat_ty, def) {
-                        delegate.mutate(binding_place, binding_place.hir_id);
+                        delegate.bind(binding_place, binding_place.hir_id);
                     }
 
                     // It is also a borrow or copy/move of the value being matched.
index 5cef007a46f0d1ea9d725fd87c3b8f703288426c..66608d09082d77363f10718a13cfa74f4e68a8c1 100644 (file)
@@ -3,7 +3,7 @@
 use core::mem;
 
 use super::super::borrow::DormantMutRef;
-use super::super::node::{marker, Handle, InsertResult::*, NodeRef};
+use super::super::node::{marker, Handle, NodeRef};
 use super::BTreeMap;
 
 use Entry::*;
@@ -313,13 +313,13 @@ pub fn into_key(self) -> K {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(self, value: V) -> &'a mut V {
         let out_ptr = match self.handle.insert_recursing(self.key, value) {
-            (Fit(_), val_ptr) => {
+            (None, val_ptr) => {
                 // SAFETY: We have consumed self.handle and the handle returned.
                 let map = unsafe { self.dormant_map.awaken() };
                 map.length += 1;
                 val_ptr
             }
-            (Split(ins), val_ptr) => {
+            (Some(ins), val_ptr) => {
                 drop(ins.left);
                 // SAFETY: We have consumed self.handle and the reference returned.
                 let map = unsafe { self.dormant_map.awaken() };
index dfce98f97bd4496f280e2dab003a8891fed80f86..44f5bc850b8527c61482e5e1da3957d5b4d9196b 100644 (file)
@@ -861,11 +861,10 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
     /// this edge. This method splits the node if there isn't enough room.
     ///
     /// The returned pointer points to the inserted value.
-    fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *mut V) {
+    fn insert(mut self, key: K, val: V) -> (Option<SplitResult<'a, K, V, marker::Leaf>>, *mut V) {
         if self.node.len() < CAPACITY {
             let val_ptr = self.insert_fit(key, val);
-            let kv = unsafe { Handle::new_kv(self.node, self.idx) };
-            (InsertResult::Fit(kv), val_ptr)
+            (None, val_ptr)
         } else {
             let (middle_kv_idx, insertion) = splitpoint(self.idx);
             let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
@@ -879,7 +878,7 @@ fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *m
                 },
             };
             let val_ptr = insertion_edge.insert_fit(key, val);
-            (InsertResult::Split(result), val_ptr)
+            (Some(result), val_ptr)
         }
     }
 }
@@ -923,13 +922,12 @@ fn insert(
         key: K,
         val: V,
         edge: Root<K, V>,
-    ) -> InsertResult<'a, K, V, marker::Internal> {
+    ) -> Option<SplitResult<'a, K, V, marker::Internal>> {
         assert!(edge.height == self.node.height - 1);
 
         if self.node.len() < CAPACITY {
             self.insert_fit(key, val, edge);
-            let kv = unsafe { Handle::new_kv(self.node, self.idx) };
-            InsertResult::Fit(kv)
+            None
         } else {
             let (middle_kv_idx, insertion) = splitpoint(self.idx);
             let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
@@ -943,7 +941,7 @@ fn insert(
                 },
             };
             insertion_edge.insert_fit(key, val, edge);
-            InsertResult::Split(result)
+            Some(result)
         }
     }
 }
@@ -953,32 +951,26 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
     /// this edge. This method splits the node if there isn't enough room, and tries to
     /// insert the split off portion into the parent node recursively, until the root is reached.
     ///
-    /// If the returned result is a `Fit`, its handle's node can be this edge's node or an ancestor.
-    /// If the returned result is a `Split`, the `left` field will be the root node.
-    /// The returned pointer points to the inserted value.
+    /// If the returned result is some `SplitResult`, the `left` field will be the root node.
+    /// The returned pointer points to the inserted value, which in the case of `SplitResult`
+    /// is in the `left` or `right` tree.
     pub fn insert_recursing(
         self,
         key: K,
         value: V,
-    ) -> (InsertResult<'a, K, V, marker::LeafOrInternal>, *mut V) {
+    ) -> (Option<SplitResult<'a, K, V, marker::LeafOrInternal>>, *mut V) {
         let (mut split, val_ptr) = match self.insert(key, value) {
-            (InsertResult::Fit(handle), ptr) => {
-                return (InsertResult::Fit(handle.forget_node_type()), ptr);
-            }
-            (InsertResult::Split(split), val_ptr) => (split.forget_node_type(), val_ptr),
+            (None, val_ptr) => return (None, val_ptr),
+            (Some(split), val_ptr) => (split.forget_node_type(), val_ptr),
         };
 
         loop {
             split = match split.left.ascend() {
                 Ok(parent) => match parent.insert(split.kv.0, split.kv.1, split.right) {
-                    InsertResult::Fit(handle) => {
-                        return (InsertResult::Fit(handle.forget_node_type()), val_ptr);
-                    }
-                    InsertResult::Split(split) => split.forget_node_type(),
+                    None => return (None, val_ptr),
+                    Some(split) => split.forget_node_type(),
                 },
-                Err(root) => {
-                    return (InsertResult::Split(SplitResult { left: root, ..split }), val_ptr);
-                }
+                Err(root) => return (Some(SplitResult { left: root, ..split }), val_ptr),
             };
         }
     }
@@ -1529,14 +1521,6 @@ pub fn forget_node_type(
     }
 }
 
-impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::KV> {
-    pub fn forget_node_type(
-        self,
-    ) -> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV> {
-        unsafe { Handle::new_kv(self.node.forget_type(), self.idx) }
-    }
-}
-
 impl<BorrowType, K, V, Type> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, Type> {
     /// Checks whether the underlying node is an `Internal` node or a `Leaf` node.
     pub fn force(
@@ -1621,7 +1605,7 @@ pub enum ForceResult<Leaf, Internal> {
 pub struct SplitResult<'a, K, V, NodeType> {
     // Altered node in existing tree with elements and edges that belong to the left of `kv`.
     pub left: NodeRef<marker::Mut<'a>, K, V, NodeType>,
-    // Some key and value split off, to be inserted elsewhere.
+    // Some key and value that existed before and were split off, to be inserted elsewhere.
     pub kv: (K, V),
     // Owned, unattached, new node with elements and edges that belong to the right of `kv`.
     pub right: NodeRef<marker::Owned, K, V, NodeType>,
@@ -1639,11 +1623,6 @@ pub fn forget_node_type(self) -> SplitResult<'a, K, V, marker::LeafOrInternal> {
     }
 }
 
-pub enum InsertResult<'a, K, V, NodeType> {
-    Fit(Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV>),
-    Split(SplitResult<'a, K, V, NodeType>),
-}
-
 pub mod marker {
     use core::marker::PhantomData;
 
index 82493f9c398cb5805d7653cab651b6b19b570538..0a180b83355e0d7c8f8a843c4504dd04c6b527f2 100644 (file)
 #![feature(box_syntax)]
 #![feature(cfg_sanitize)]
 #![feature(const_deref)]
-#![feature(const_fn_trait_bound)]
+#![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
 #![feature(const_mut_refs)]
 #![feature(const_ptr_write)]
 #![feature(const_precise_live_drops)]
index a3e7747991190acccc0337aecfcb00c9462d7a6c..ddaeb9eca975c7d28364bdeb2dc641119d24b4e4 100644 (file)
@@ -885,19 +885,18 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 /// 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`).
+/// The methods of this trait must be consistent with each other and with those of [`PartialEq`].
+/// The following conditions must hold:
+///
+/// 1. `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
+/// 2. `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
+/// 3. `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
+/// 4. `a <= b` if and only if `a < b || a == b`
+/// 5. `a >= b` if and only if `a > b || a == b`
+/// 6. `a != b` if and only if `!(a == b)`.
+///
+/// Conditions 2–5 above are ensured by the default implementation.
+/// Condition 6 is already ensured by [`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
index 330c43d2948357f3951c7a4e3cdd69407499f3f9..58ea109c735b67afbde616c0d21cb46ce1890ca0 100644 (file)
@@ -173,3 +173,126 @@ pub fn spin_loop() {
 pub const fn black_box<T>(dummy: T) -> T {
     crate::intrinsics::black_box(dummy)
 }
+
+/// An identity function that causes an `unused_must_use` warning to be
+/// triggered if the given value is not used (returned, stored in a variable,
+/// etc) by the caller.
+///
+/// This is primarily intended for use in macro-generated code, in which a
+/// [`#[must_use]` attribute][must_use] either on a type or a function would not
+/// be convenient.
+///
+/// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
+///
+/// # Example
+///
+/// ```
+/// #![feature(hint_must_use)]
+///
+/// use core::fmt;
+///
+/// pub struct Error(/* ... */);
+///
+/// #[macro_export]
+/// macro_rules! make_error {
+///     ($($args:expr),*) => {
+///         core::hint::must_use({
+///             let error = $crate::make_error(core::format_args!($($args),*));
+///             error
+///         })
+///     };
+/// }
+///
+/// // Implementation detail of make_error! macro.
+/// #[doc(hidden)]
+/// pub fn make_error(args: fmt::Arguments<'_>) -> Error {
+///     Error(/* ... */)
+/// }
+///
+/// fn demo() -> Option<Error> {
+///     if true {
+///         // Oops, meant to write `return Some(make_error!("..."));`
+///         Some(make_error!("..."));
+///     }
+///     None
+/// }
+/// #
+/// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works
+/// # fn main() {}
+/// ```
+///
+/// In the above example, we'd like an `unused_must_use` lint to apply to the
+/// value created by `make_error!`. However, neither `#[must_use]` on a struct
+/// nor `#[must_use]` on a function is appropriate here, so the macro expands
+/// using `core::hint::must_use` instead.
+///
+/// - We wouldn't want `#[must_use]` on the `struct Error` because that would
+///   make the following unproblematic code trigger a warning:
+///
+///   ```
+///   # struct Error;
+///   #
+///   fn f(arg: &str) -> Result<(), Error>
+///   # { Ok(()) }
+///
+///   #[test]
+///   fn t() {
+///       // Assert that `f` returns error if passed an empty string.
+///       // A value of type `Error` is unused here but that's not a problem.
+///       f("").unwrap_err();
+///   }
+///   ```
+///
+/// - Using `#[must_use]` on `fn make_error` can't help because the return value
+///   *is* used, as the right-hand side of a `let` statement. The `let`
+///   statement looks useless but is in fact necessary for ensuring that
+///   temporaries within the `format_args` expansion are not kept alive past the
+///   creation of the `Error`, as keeping them alive past that point can cause
+///   autotrait issues in async code:
+///
+///   ```
+///   # #![feature(hint_must_use)]
+///   #
+///   # struct Error;
+///   #
+///   # macro_rules! make_error {
+///   #     ($($args:expr),*) => {
+///   #         core::hint::must_use({
+///   #             // If `let` isn't used, then `f()` produces a non-Send future.
+///   #             let error = make_error(core::format_args!($($args),*));
+///   #             error
+///   #         })
+///   #     };
+///   # }
+///   #
+///   # fn make_error(args: core::fmt::Arguments<'_>) -> Error {
+///   #     Error
+///   # }
+///   #
+///   async fn f() {
+///       // Using `let` inside the make_error expansion causes temporaries like
+///       // `unsync()` to drop at the semicolon of that `let` statement, which
+///       // is prior to the await point. They would otherwise stay around until
+///       // the semicolon on *this* statement, which is after the await point,
+///       // and the enclosing Future would not implement Send.
+///       log(make_error!("look: {:p}", unsync())).await;
+///   }
+///
+///   async fn log(error: Error) {/* ... */}
+///
+///   // Returns something without a Sync impl.
+///   fn unsync() -> *const () {
+///       0 as *const ()
+///   }
+///   #
+///   # fn test() {
+///   #     fn assert_send(_: impl Send) {}
+///   #     assert_send(f());
+///   # }
+///   ```
+#[unstable(feature = "hint_must_use", issue = "94745")]
+#[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
+#[must_use] // <-- :)
+pub const fn must_use<T>(value: T) -> T {
+    value
+}
index b2ed82508dd297afb69dad6a258eebbb08f6e523..d2077a63e150a96b6d589ec7d836fe7fab107be5 100644 (file)
@@ -38,7 +38,7 @@
 /// }
 /// ```
 ///
-/// This will print "('a', 1), ('b', 2), ('c', 3)".
+/// This will print `('a', 1), ('b', 2), ('c', 3)`.
 ///
 /// Now consider this twist where we add a call to `rev`. This version will
 /// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
index 5a361edecd9c00298e95a3d91446d73a241a8f4d..f5c0a3b5cd849b0b3c71bf2652bb3aec3be9733d 100644 (file)
@@ -1877,9 +1877,9 @@ fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
     /// ```
     /// let a = [1, 2, 3];
     ///
-    /// let (even, odd): (Vec<i32>, Vec<i32>) = a
-    ///     .iter()
-    ///     .partition(|&n| n % 2 == 0);
+    /// let (even, odd): (Vec<_>, Vec<_>) = a
+    ///     .into_iter()
+    ///     .partition(|n| n % 2 == 0);
     ///
     /// assert_eq!(even, vec![2]);
     /// assert_eq!(odd, vec![1, 3]);
index e7896b2cb66ed0b59d503b933948a023d04de276..f436afbee448e4cb375ec379621c130fb9b8e7c0 100644 (file)
 #![feature(cfg_target_has_atomic)]
 #![feature(cfg_target_has_atomic_equal_alignment)]
 #![feature(const_fn_floating_point_arithmetic)]
-#![feature(const_fn_fn_ptr_basics)]
-#![feature(const_fn_trait_bound)]
-#![feature(const_impl_trait)]
+#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))]
+#![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
+#![cfg_attr(bootstrap, feature(const_impl_trait))]
 #![feature(const_mut_refs)]
 #![feature(const_precise_live_drops)]
 #![feature(const_refs_to_cell)]
@@ -408,12 +408,12 @@ pub mod arch {
 #[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)]
 #[allow(rustdoc::bare_urls)]
 #[unstable(feature = "portable_simd", issue = "86656")]
-#[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics
+#[cfg(not(all(miri, doctest)))] // Skip SIMD doctests in Miri
 mod core_simd;
 
 #[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")]
 #[unstable(feature = "portable_simd", issue = "86656")]
-#[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics
+#[cfg(not(all(miri, doctest)))] // Skip SIMD doctests in Miri
 pub mod simd {
     #[unstable(feature = "portable_simd", issue = "86656")]
     pub use crate::core_simd::simd::*;
index e38c0412a0afe444d14eb4826c1a8582998083f0..9db5a9a288940df0d70f79d23d784946024f6bc3 100644 (file)
@@ -817,6 +817,7 @@ pub unsafe fn assume_init_drop(&mut self) {
     /// ### Correct usage of this method:
     ///
     /// ```rust
+    /// # #![allow(unexpected_cfgs)]
     /// use std::mem::MaybeUninit;
     ///
     /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] }
index 775d2ded9daad2c1933df0769d9d47b9b44cd88f..cef6a68b4d329e5d2f7ef343ce53880bcc33b888 100644 (file)
@@ -954,7 +954,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
 /// stuff(pin!(Foo { /* â€¦ */ }));
 /// ```
 ///
-/// ### Manually polling a `Future` (wihout `Unpin` bounds)
+/// ### Manually polling a `Future` (without `Unpin` bounds)
 ///
 /// ```rust
 /// #![feature(pin_macro)]
index 801e3a0b3a4ccaf34038d70ed286bd3185d7802f..1827860a39045cba2b82b2db56fb5a3142bc8db3 100644 (file)
@@ -632,10 +632,16 @@ pub fn is_err_with(&self, f: impl FnOnce(&E) -> bool) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn ok(self) -> Option<T> {
+    #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
+    pub const fn ok(self) -> Option<T>
+    where
+        E: ~const Drop,
+    {
         match self {
             Ok(x) => Some(x),
-            Err(_) => None,
+            // FIXME: ~const Drop doesn't quite work right yet
+            #[allow(unused_variables)]
+            Err(x) => None,
         }
     }
 
@@ -657,9 +663,15 @@ pub fn ok(self) -> Option<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn err(self) -> Option<E> {
+    #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
+    pub const fn err(self) -> Option<E>
+    where
+        T: ~const Drop,
+    {
         match self {
-            Ok(_) => None,
+            // FIXME: ~const Drop doesn't quite work right yet
+            #[allow(unused_variables)]
+            Ok(x) => None,
             Err(x) => Some(x),
         }
     }
@@ -1266,10 +1278,18 @@ pub fn into_err(self) -> E
     /// assert_eq!(x.and(y), Ok("different result type"));
     /// ```
     #[inline]
+    #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
+    pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E>
+    where
+        T: ~const Drop,
+        U: ~const Drop,
+        E: ~const Drop,
+    {
         match self {
-            Ok(_) => res,
+            // FIXME: ~const Drop doesn't quite work right yet
+            #[allow(unused_variables)]
+            Ok(x) => res,
             Err(e) => Err(e),
         }
     }
@@ -1343,11 +1363,19 @@ pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
     /// assert_eq!(x.or(y), Ok(2));
     /// ```
     #[inline]
+    #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> {
+    pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F>
+    where
+        T: ~const Drop,
+        E: ~const Drop,
+        F: ~const Drop,
+    {
         match self {
             Ok(v) => Ok(v),
-            Err(_) => res,
+            // FIXME: ~const Drop doesn't quite work right yet
+            #[allow(unused_variables)]
+            Err(e) => res,
         }
     }
 
@@ -1399,11 +1427,18 @@ pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
     /// assert_eq!(x.unwrap_or(default), default);
     /// ```
     #[inline]
+    #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn unwrap_or(self, default: T) -> T {
+    pub const fn unwrap_or(self, default: T) -> T
+    where
+        T: ~const Drop,
+        E: ~const Drop,
+    {
         match self {
             Ok(t) => t,
-            Err(_) => default,
+            // FIXME: ~const Drop doesn't quite work right yet
+            #[allow(unused_variables)]
+            Err(e) => default,
         }
     }
 
index 08b95d791a38caf8d4aafd86059ca71fa0285c06..9467c7f54bac7d56d5062017675b0ef520da4d27 100644 (file)
@@ -16,7 +16,7 @@
 use crate::ptr;
 use crate::result::Result;
 use crate::result::Result::{Err, Ok};
-#[cfg(not(miri))] // Miri does not support all SIMD intrinsics
+#[cfg(not(all(miri, doctest)))] // Miri skips SIMD doctests
 use crate::simd::{self, Simd};
 use crate::slice;
 
@@ -3540,7 +3540,7 @@ pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
     /// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0);
     /// ```
     #[unstable(feature = "portable_simd", issue = "86656")]
-    #[cfg(not(miri))] // Miri does not support all SIMD intrinsics
+    #[cfg(not(all(miri, doctest)))] // Miri skips SIMD doctests
     pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T])
     where
         Simd<T, LANES>: AsRef<[T; LANES]>,
@@ -3584,7 +3584,7 @@ pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T])
     /// be lifted in a way that would make it possible to see panics from this
     /// method for something like `LANES == 3`.
     #[unstable(feature = "portable_simd", issue = "86656")]
-    #[cfg(not(miri))] // Miri does not support all SIMD intrinsics
+    #[cfg(not(all(miri, doctest)))] // Miri skips SIMD doctests
     pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T])
     where
         Simd<T, LANES>: AsMut<[T; LANES]>,
index 2b8bbe1924450a41a8f20d01e3018631f6da3aae..2da04ab2cea7d4d78d1f9e517cd35a821b3ab87e 100644 (file)
@@ -352,7 +352,7 @@ pub fn from_mut(v: &mut bool) -> &mut Self {
     /// let a = &*AtomicBool::from_mut_slice(&mut some_bools);
     /// std::thread::scope(|s| {
     ///     for i in 0..a.len() {
-    ///         s.spawn(move |_| a[i].store(true, Ordering::Relaxed));
+    ///         s.spawn(move || a[i].store(true, Ordering::Relaxed));
     ///     }
     /// });
     /// assert_eq!(some_bools, [true; 10]);
@@ -984,7 +984,7 @@ pub fn from_mut(v: &mut *mut T) -> &mut Self {
     /// let a = &*AtomicPtr::from_mut_slice(&mut some_ptrs);
     /// std::thread::scope(|s| {
     ///     for i in 0..a.len() {
-    ///         s.spawn(move |_| {
+    ///         s.spawn(move || {
     ///             let name = Box::new(format!("thread{i}"));
     ///             a[i].store(Box::into_raw(name), Ordering::Relaxed);
     ///         });
@@ -1533,7 +1533,7 @@ pub fn from_mut(v: &mut $int_type) -> &mut Self {
             #[doc = concat!("let a = &*", stringify!($atomic_type), "::from_mut_slice(&mut some_ints);")]
             /// std::thread::scope(|s| {
             ///     for i in 0..a.len() {
-            ///         s.spawn(move |_| a[i].store(i as _, Ordering::Relaxed));
+            ///         s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
             ///     }
             /// });
             /// for (i, n) in some_ints.into_iter().enumerate() {
index b84f3228e780039362a1d854f6ca3c8b99b47a60..5b516a72360aa008d2ff233d70e87f11f84f2eda 100644 (file)
@@ -1,5 +1,3 @@
-#![cfg(not(miri))] // Miri does not support all SIMD intrinsics
-
 use core::simd::f32x4;
 
 #[test]
index 06a30d7096c775d4ef306f7d89fbcbd6ae5274d7..7c4d2f266f958753839fedb347b1696a2c496438 100644 (file)
@@ -2457,9 +2457,11 @@ fn $test_name() {
     (take_last_mut_empty, (), None, &mut []),
 }
 
+#[cfg(not(miri))] // unused in Miri
 const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
 
 // can't be a constant due to const mutability rules
+#[cfg(not(miri))] // unused in Miri
 macro_rules! empty_max_mut {
     () => {
         &mut [(); usize::MAX] as _
index c5afca6d56a2d29a33255a1330dc74b579541284..31900912df4683a1dec2a7e61b5d63d43d8bd85f 100644 (file)
@@ -20,8 +20,8 @@
 #![feature(rustc_allow_const_fn_unstable)]
 #![feature(nll)]
 #![feature(staged_api)]
-#![feature(const_fn_trait_bound)]
-#![feature(const_fn_fn_ptr_basics)]
+#![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
+#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))]
 #![feature(allow_internal_unstable)]
 #![feature(decl_macro)]
 #![feature(extern_types)]
index 71a59fb58032115e17e61ff233003068ad7887da..3fa965d08e6981b629f39fa4e6a4fdba30287eb5 100644 (file)
 pub use self::stdio::set_output_capture;
 #[unstable(feature = "print_internals", issue = "none")]
 pub use self::stdio::{_eprint, _print};
-#[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::{
     buffered::{BufReader, BufWriter, IntoInnerError, LineWriter},
index 3d6de20d8609142a50544cf4331a9e87e68746d3..5414ff648d4d5f5051ccf64d5a71e0aa3b5ed239 100644 (file)
@@ -307,48 +307,6 @@ 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, BufRead};
-///
-/// fn main() -> io::Result<()> {
-///     let mut buffer = String::new();
-///     let mut handle = io::stdin_locked();
-///
-///     handle.read_line(&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.
@@ -372,8 +330,10 @@ impl Stdin {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn lock(&self) -> StdinLock<'_> {
-        self.lock_any()
+    pub fn lock(&self) -> StdinLock<'static> {
+        // Locks this handle with 'static lifetime. This depends on the
+        // implementation detail that the underlying `Mutex` is static.
+        StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
     }
 
     /// Locks this handle and reads a line of input, appending it to the specified buffer.
@@ -407,43 +367,6 @@ pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
         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, BufRead};
-    ///
-    /// fn main() -> io::Result<()> {
-    ///     let mut buffer = String::new();
-    ///     let mut handle = io::stdin().into_locked();
-    ///
-    ///     handle.read_line(&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
@@ -463,7 +386,7 @@ pub fn into_locked(self) -> StdinLock<'static> {
     #[must_use = "`self` will be dropped if the result is not used"]
     #[unstable(feature = "stdin_forwarders", issue = "87096")]
     pub fn lines(self) -> Lines<StdinLock<'static>> {
-        self.into_locked().lines()
+        self.lock().lines()
     }
 }
 
@@ -649,42 +572,6 @@ 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
@@ -712,55 +599,20 @@ impl Stdout {
     /// use std::io::{self, Write};
     ///
     /// fn main() -> io::Result<()> {
-    ///     let stdout = io::stdout();
-    ///     let mut handle = stdout.lock();
+    ///     let mut stdout = io::stdout().lock();
     ///
-    ///     handle.write_all(b"hello world")?;
+    ///     stdout.write_all(b"hello world")?;
     ///
     ///     Ok(())
     /// }
     /// ```
     #[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> {
+    pub fn lock(&self) -> StdoutLock<'static> {
+        // Locks this handle with 'static lifetime. This depends on the
+        // implementation detail that the underlying `ReentrantMutex` is
+        // static.
         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")]
@@ -935,35 +787,6 @@ 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.
@@ -986,43 +809,12 @@ 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> {
+    pub fn lock(&self) -> StderrLock<'static> {
+        // Locks this handle with 'static lifetime. This depends on the
+        // implementation detail that the underlying `ReentrantMutex` is
+        // static.
         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")]
index b1df6b7131c8779f0fe2a3da9a51faedc9b36807..f89fd27ce6c23b2ed6ae874b61daa2f6f81b7616 100644 (file)
@@ -50,17 +50,17 @@ fn panic_doesnt_poison() {
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
 fn test_lock_stderr() {
-    test_lock(stderr, stderr_locked);
+    test_lock(stderr, || stderr().lock());
 }
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
 fn test_lock_stdin() {
-    test_lock(stdin, stdin_locked);
+    test_lock(stdin, || stdin().lock());
 }
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
 fn test_lock_stdout() {
-    test_lock(stdout, stdout_locked);
+    test_lock(stdout, || stdout().lock());
 }
 
 // Helper trait to make lock testing function generic.
index 10fec8e1152458aaf7f243ea7742025f5cb1fa8d..c35389d44f9fc927d70d235678e127dbfae0369d 100644 (file)
 #![needs_panic_runtime]
 // std may use features in a platform-specific way
 #![allow(unused_features)]
-#![feature(rustc_allow_const_fn_unstable)]
 #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
 // NB: the following list is sorted to minimize merge conflicts.
-#![feature(absolute_path)]
 #![feature(alloc_error_handler)]
 #![feature(alloc_layout_extra)]
 #![feature(allocator_api)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
-#![feature(arbitrary_self_types)]
 #![feature(array_error_internals)]
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
 #![feature(async_iterator)]
 #![feature(atomic_mut_ptr)]
-#![feature(auto_traits)]
 #![feature(bench_black_box)]
-#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(c_unwind)]
 #![feature(c_variadic)]
 #![feature(char_internals)]
 #![feature(concat_bytes)]
 #![feature(concat_idents)]
-#![feature(const_fn_floating_point_arithmetic)]
-#![feature(const_fn_fn_ptr_basics)]
-#![feature(const_fn_trait_bound)]
+#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))]
+#![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
 #![feature(const_format_args)]
 #![feature(const_io_structs)]
 #![feature(const_ip)]
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
-#![feature(const_option)]
 #![feature(const_mut_refs)]
+#![feature(const_option)]
 #![feature(const_socketaddr)]
 #![feature(const_trait_impl)]
-#![feature(container_error_extra)]
 #![feature(c_size_t)]
 #![feature(core_ffi_c)]
 #![feature(core_intrinsics)]
 #![feature(exact_size_is_empty)]
 #![feature(exhaustive_patterns)]
 #![feature(extend_one)]
-#![feature(fn_traits)]
 #![feature(float_minimum_maximum)]
 #![feature(format_args_nl)]
-#![feature(gen_future)]
-#![feature(generator_trait)]
 #![feature(get_mut_unchecked)]
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
-#![feature(integer_atomics)]
-#![feature(int_log)]
-#![feature(into_future)]
 #![feature(intra_doc_pointers)]
 #![feature(lang_items)]
 #![feature(linkage)]
 #![feature(log_syntax)]
 #![feature(map_try_insert)]
 #![feature(maybe_uninit_slice)]
-#![feature(maybe_uninit_uninit_array)]
 #![feature(maybe_uninit_write_slice)]
 #![feature(min_specialization)]
 #![feature(mixed_integer_ops)]
 #![feature(portable_simd)]
 #![feature(prelude_import)]
 #![feature(ptr_as_uninit)]
-#![feature(ptr_internals)]
 #![feature(raw_os_nonzero)]
 #![feature(rustc_attrs)]
-#![feature(rustc_private)]
 #![feature(saturating_int_impl)]
-#![feature(slice_concat_ext)]
 #![feature(slice_internals)]
 #![feature(slice_ptr_get)]
-#![feature(slice_ptr_len)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stdsimd)]
-#![feature(stmt_expr_attributes)]
 #![feature(str_internals)]
 #![feature(test)]
 #![feature(thread_local)]
 #![feature(trace_macros)]
 #![feature(try_blocks)]
 #![feature(try_reserve_kind)]
-#![feature(unboxed_closures)]
-#![feature(unwrap_infallible)]
 #![feature(vec_into_raw_parts)]
 // NB: the above list is sorted to minimize merge conflicts.
 #![default_lib_allocator]
index f676e0a04f000883760a3a141da84018273b1b18..9ed4a98f943cdb71f3a2a7131e52cb3e2ed71103 100644 (file)
 //! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting
 //!   with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`]
 //! * Other types are return or parameter types for various methods in this module
+//!
+//! Rust disables inheritance of socket objects to child processes by default when possible.  For
+//! example, through the use of the `CLOEXEC` flag in UNIX systems or the `HANDLE_FLAG_INHERIT`
+//! flag on Windows.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index c2061c1351262595cf9f9d804da9a87f1a606f0e..959fe6943f6ee6d982c28f8466e4748a742df053 100644 (file)
@@ -508,7 +508,6 @@ fn close_readwrite_smoke() {
 }
 
 #[test]
-#[cfg(unix)] // test doesn't work on Windows, see #31657
 fn close_read_wakes_up() {
     each_ip(&mut |addr| {
         let a = t!(TcpListener::bind(&addr));
index 31d1e3c1e42ee5b3af37470867aea9f20087fa89..f15baff59dbfb589b0dec2f68fd235b14822da03 100644 (file)
@@ -158,6 +158,7 @@ pub trait OpenOptionsExt {
     /// # Examples
     ///
     /// ```no_run
+    /// # #![allow(unexpected_cfgs)]
     /// # #[cfg(for_demonstration_only)]
     /// extern crate winapi;
     /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; }
@@ -195,6 +196,7 @@ pub trait OpenOptionsExt {
     /// # Examples
     ///
     /// ```no_run
+    /// # #![allow(unexpected_cfgs)]
     /// # #[cfg(for_demonstration_only)]
     /// extern crate winapi;
     /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; }
@@ -236,6 +238,7 @@ pub trait OpenOptionsExt {
     /// # Examples
     ///
     /// ```no_run
+    /// # #![allow(unexpected_cfgs)]
     /// # #[cfg(for_demonstration_only)]
     /// extern crate winapi;
     /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; }
index d378d591ba3a9f4c5508ba9c2c6c931ef02d25e8..14b94d8dcdf92e889d2921362eee551949229365 100644 (file)
@@ -59,6 +59,7 @@ pub struct BorrowedHandle<'handle> {
 /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
 ///
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
+#[repr(transparent)]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct OwnedHandle {
     handle: RawHandle,
index 8e51433094a6962d40eb3b7b442119d19ba343bf..6e863787b7f39bf1515c4217037acd43febff119 100644 (file)
@@ -1710,15 +1710,23 @@ fn test_unix_absolute() {
     let relative = "a/b";
     let mut expected = crate::env::current_dir().unwrap();
     expected.push(relative);
-    assert_eq!(absolute(relative).unwrap(), expected);
+    assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str());
 
     // Test how components are collected.
-    assert_eq!(absolute("/a/b/c").unwrap(), Path::new("/a/b/c"));
-    assert_eq!(absolute("/a//b/c").unwrap(), Path::new("/a/b/c"));
-    assert_eq!(absolute("//a/b/c").unwrap(), Path::new("//a/b/c"));
-    assert_eq!(absolute("///a/b/c").unwrap(), Path::new("/a/b/c"));
-    assert_eq!(absolute("/a/b/c/").unwrap(), Path::new("/a/b/c/"));
-    assert_eq!(absolute("/a/./b/../c/.././..").unwrap(), Path::new("/a/b/../c/../.."));
+    assert_eq!(absolute("/a/b/c").unwrap().as_os_str(), Path::new("/a/b/c").as_os_str());
+    assert_eq!(absolute("/a//b/c").unwrap().as_os_str(), Path::new("/a/b/c").as_os_str());
+    assert_eq!(absolute("//a/b/c").unwrap().as_os_str(), Path::new("//a/b/c").as_os_str());
+    assert_eq!(absolute("///a/b/c").unwrap().as_os_str(), Path::new("/a/b/c").as_os_str());
+    assert_eq!(absolute("/a/b/c/").unwrap().as_os_str(), Path::new("/a/b/c/").as_os_str());
+    assert_eq!(
+        absolute("/a/./b/../c/.././..").unwrap().as_os_str(),
+        Path::new("/a/b/../c/../..").as_os_str()
+    );
+
+    // Test leading `.` and `..` components
+    let curdir = crate::env::current_dir().unwrap();
+    assert_eq!(absolute("./a").unwrap().as_os_str(), curdir.join("a").as_os_str());
+    assert_eq!(absolute("../a").unwrap().as_os_str(), curdir.join("../a").as_os_str()); // return /pwd/../a
 }
 
 #[test]
index f76d0759561acdc5f6f8a321c3f7a821cc13eaa1..511de863dc51bae59f8eadf508225db02d6db31e 100644 (file)
@@ -256,6 +256,7 @@ pub const fn new() -> Once {
     ///
     /// [poison]: struct.Mutex.html#poisoning
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[track_caller]
     pub fn call_once<F>(&self, f: F)
     where
         F: FnOnce(),
@@ -390,6 +391,7 @@ pub fn is_completed(&self) -> bool {
     // currently no way to take an `FnOnce` and call it via virtual dispatch
     // without some allocation overhead.
     #[cold]
+    #[track_caller]
     fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&OnceState)) {
         let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire);
         loop {
index 8bd0b9b14afedb4cb14c7b23eb1abee90ffecaf2..a3e6b081936b67bb6f824b85b401edf3cf896c91 100644 (file)
@@ -228,23 +228,54 @@ pub struct ReadDir {
 unsafe impl Send for Dir {}
 unsafe impl Sync for Dir {}
 
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "solaris",
+    target_os = "illumos",
+    target_os = "fuchsia",
+    target_os = "redox"
+))]
 pub struct DirEntry {
-    entry: dirent64,
     dir: Arc<InnerReadDir>,
+    entry: dirent64_min,
     // We need to store an owned copy of the entry name on platforms that use
     // readdir() (not readdir_r()), because a) struct dirent may use a flexible
     // array to store the name, b) it lives only until the next readdir() call.
-    #[cfg(any(
-        target_os = "android",
-        target_os = "linux",
-        target_os = "solaris",
-        target_os = "illumos",
-        target_os = "fuchsia",
-        target_os = "redox"
-    ))]
     name: CString,
 }
 
+// Define a minimal subset of fields we need from `dirent64`, especially since
+// we're not using the immediate `d_name` on these targets. Keeping this as an
+// `entry` field in `DirEntry` helps reduce the `cfg` boilerplate elsewhere.
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "solaris",
+    target_os = "illumos",
+    target_os = "fuchsia",
+    target_os = "redox"
+))]
+struct dirent64_min {
+    d_ino: u64,
+    #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+    d_type: u8,
+}
+
+#[cfg(not(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "solaris",
+    target_os = "illumos",
+    target_os = "fuchsia",
+    target_os = "redox"
+)))]
+pub struct DirEntry {
+    dir: Arc<InnerReadDir>,
+    // The full entry includes a fixed-length `d_name`.
+    entry: dirent64,
+}
+
 #[derive(Clone, Debug)]
 pub struct OpenOptions {
     // generic
@@ -491,11 +522,21 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
 
                 // Only d_reclen bytes of *entry_ptr are valid, so we can't just copy the
                 // whole thing (#93384).  Instead, copy everything except the name.
+                let mut copy: dirent64 = mem::zeroed();
+                // Can't dereference entry_ptr, so use the local entry to get
+                // offsetof(struct dirent, d_name)
+                let copy_bytes = &mut copy as *mut _ as *mut u8;
+                let copy_name = &mut copy.d_name as *mut _ as *mut u8;
+                let name_offset = copy_name.offset_from(copy_bytes) as usize;
                 let entry_bytes = entry_ptr as *const u8;
-                let entry_name = ptr::addr_of!((*entry_ptr).d_name) as *const u8;
-                let name_offset = entry_name.offset_from(entry_bytes) as usize;
-                let mut entry: dirent64 = mem::zeroed();
-                ptr::copy_nonoverlapping(entry_bytes, &mut entry as *mut _ as *mut u8, name_offset);
+                let entry_name = entry_bytes.add(name_offset);
+                ptr::copy_nonoverlapping(entry_bytes, copy_bytes, name_offset);
+
+                let entry = dirent64_min {
+                    d_ino: copy.d_ino as u64,
+                    #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+                    d_type: copy.d_type as u8,
+                };
 
                 let ret = DirEntry {
                     entry,
@@ -1482,140 +1523,60 @@ mod remove_dir_impl {
     pub use crate::sys_common::fs::remove_dir_all;
 }
 
-// Dynamically choose implementation Macos x86-64: modern for 10.10+, fallback for older versions
-#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+// Modern implementation using openat(), unlinkat() and fdopendir()
+#[cfg(not(any(target_os = "redox", target_os = "espidf")))]
 mod remove_dir_impl {
-    use super::{cstr, lstat, Dir, InnerReadDir, ReadDir};
+    use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir};
     use crate::ffi::CStr;
     use crate::io;
     use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
     use crate::os::unix::prelude::{OwnedFd, RawFd};
     use crate::path::{Path, PathBuf};
     use crate::sync::Arc;
-    use crate::sys::weak::weak;
     use crate::sys::{cvt, cvt_r};
-    use libc::{c_char, c_int, DIR};
 
-    pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
-        weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
-        let fd = cvt_r(|| unsafe {
-            openat.get().unwrap()(
-                parent_fd.unwrap_or(libc::AT_FDCWD),
-                p.as_ptr(),
-                libc::O_CLOEXEC | libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_DIRECTORY,
-            )
-        })?;
-        Ok(unsafe { OwnedFd::from_raw_fd(fd) })
-    }
-
-    fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> {
-        weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64");
-        let ptr = unsafe { fdopendir.get().unwrap()(dir_fd.as_raw_fd()) };
-        if ptr.is_null() {
-            return Err(io::Error::last_os_error());
-        }
-        let dirp = Dir(ptr);
-        // file descriptor is automatically closed by libc::closedir() now, so give up ownership
-        let new_parent_fd = dir_fd.into_raw_fd();
-        // a valid root is not needed because we do not call any functions involving the full path
-        // of the DirEntrys.
-        let dummy_root = PathBuf::new();
-        Ok((
-            ReadDir {
-                inner: Arc::new(InnerReadDir { dirp, root: dummy_root }),
-                end_of_stream: false,
-            },
-            new_parent_fd,
-        ))
-    }
-
-    fn remove_dir_all_recursive(parent_fd: Option<RawFd>, p: &Path) -> io::Result<()> {
-        weak!(fn unlinkat(c_int, *const c_char, c_int) -> c_int);
+    #[cfg(not(all(target_os = "macos", target_arch = "x86_64"),))]
+    use libc::{fdopendir, openat, unlinkat};
+    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+    use macos_weak::{fdopendir, openat, unlinkat};
 
-        let pcstr = cstr(p)?;
+    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+    mod macos_weak {
+        use crate::sys::weak::weak;
+        use libc::{c_char, c_int, DIR};
 
-        // entry is expected to be a directory, open as such
-        let fd = openat_nofollow_dironly(parent_fd, &pcstr)?;
+        fn get_openat_fn() -> Option<unsafe extern "C" fn(c_int, *const c_char, c_int) -> c_int> {
+            weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
+            openat.get()
+        }
 
-        // open the directory passing ownership of the fd
-        let (dir, fd) = fdreaddir(fd)?;
-        for child in dir {
-            let child = child?;
-            match child.entry.d_type {
-                libc::DT_DIR => {
-                    remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
-                }
-                libc::DT_UNKNOWN => {
-                    match cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) })
-                    {
-                        // type unknown - try to unlink
-                        Err(err) if err.raw_os_error() == Some(libc::EPERM) => {
-                            // if the file is a directory unlink fails with EPERM
-                            remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
-                        }
-                        result => {
-                            result?;
-                        }
-                    }
-                }
-                _ => {
-                    // not a directory -> unlink
-                    cvt(unsafe { unlinkat.get().unwrap()(fd, child.name_cstr().as_ptr(), 0) })?;
-                }
-            }
+        pub fn has_openat() -> bool {
+            get_openat_fn().is_some()
         }
 
-        // unlink the directory after removing its contents
-        cvt(unsafe {
-            unlinkat.get().unwrap()(
-                parent_fd.unwrap_or(libc::AT_FDCWD),
-                pcstr.as_ptr(),
-                libc::AT_REMOVEDIR,
-            )
-        })?;
-        Ok(())
-    }
+        pub unsafe fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int {
+            get_openat_fn().map(|openat| openat(dirfd, pathname, flags)).unwrap_or_else(|| {
+                crate::sys::unix::os::set_errno(libc::ENOSYS);
+                -1
+            })
+        }
 
-    fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
-        // We cannot just call remove_dir_all_recursive() here because that would not delete a passed
-        // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
-        // into symlinks.
-        let attr = lstat(p)?;
-        if attr.file_type().is_symlink() {
-            crate::fs::remove_file(p)
-        } else {
-            remove_dir_all_recursive(None, p)
+        pub unsafe fn fdopendir(fd: c_int) -> *mut DIR {
+            weak!(fn fdopendir(c_int) -> *mut DIR, "fdopendir$INODE64");
+            fdopendir.get().map(|fdopendir| fdopendir(fd)).unwrap_or_else(|| {
+                crate::sys::unix::os::set_errno(libc::ENOSYS);
+                crate::ptr::null_mut()
+            })
         }
-    }
 
-    pub fn remove_dir_all(p: &Path) -> io::Result<()> {
-        weak!(fn openat(c_int, *const c_char, c_int) -> c_int);
-        if openat.get().is_some() {
-            // openat() is available with macOS 10.10+, just like unlinkat() and fdopendir()
-            remove_dir_all_modern(p)
-        } else {
-            // fall back to classic implementation
-            crate::sys_common::fs::remove_dir_all(p)
+        pub unsafe fn unlinkat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int {
+            weak!(fn unlinkat(c_int, *const c_char, c_int) -> c_int);
+            unlinkat.get().map(|unlinkat| unlinkat(dirfd, pathname, flags)).unwrap_or_else(|| {
+                crate::sys::unix::os::set_errno(libc::ENOSYS);
+                -1
+            })
         }
     }
-}
-
-// Modern implementation using openat(), unlinkat() and fdopendir()
-#[cfg(not(any(
-    all(target_os = "macos", target_arch = "x86_64"),
-    target_os = "redox",
-    target_os = "espidf"
-)))]
-mod remove_dir_impl {
-    use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir};
-    use crate::ffi::CStr;
-    use crate::io;
-    use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
-    use crate::os::unix::prelude::{OwnedFd, RawFd};
-    use crate::path::{Path, PathBuf};
-    use crate::sync::Arc;
-    use crate::sys::{cvt, cvt_r};
-    use libc::{fdopendir, openat, unlinkat};
 
     pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
         let fd = cvt_r(|| unsafe {
@@ -1680,47 +1641,53 @@ fn is_dir(ent: &DirEntry) -> Option<bool> {
         }
     }
 
-    fn remove_dir_all_recursive(parent_fd: Option<RawFd>, p: &Path) -> io::Result<()> {
-        let pcstr = cstr(p)?;
-
-        // entry is expected to be a directory, open as such
-        let fd = openat_nofollow_dironly(parent_fd, &pcstr)?;
+    fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result<()> {
+        // try opening as directory
+        let fd = match openat_nofollow_dironly(parent_fd, &path) {
+            Err(err) if err.raw_os_error() == Some(libc::ENOTDIR) => {
+                // not a directory - don't traverse further
+                return match parent_fd {
+                    // unlink...
+                    Some(parent_fd) => {
+                        cvt(unsafe { unlinkat(parent_fd, path.as_ptr(), 0) }).map(drop)
+                    }
+                    // ...unless this was supposed to be the deletion root directory
+                    None => Err(err),
+                };
+            }
+            result => result?,
+        };
 
         // open the directory passing ownership of the fd
         let (dir, fd) = fdreaddir(fd)?;
         for child in dir {
             let child = child?;
+            let child_name = child.name_cstr();
             match is_dir(&child) {
                 Some(true) => {
-                    remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
+                    remove_dir_all_recursive(Some(fd), child_name)?;
                 }
                 Some(false) => {
-                    cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) })?;
+                    cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?;
+                }
+                None => {
+                    // POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed
+                    // if the process has the appropriate privileges. This however can causing orphaned
+                    // directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing
+                    // into it first instead of trying to unlink() it.
+                    remove_dir_all_recursive(Some(fd), child_name)?;
                 }
-                None => match cvt(unsafe { unlinkat(fd, child.name_cstr().as_ptr(), 0) }) {
-                    // type unknown - try to unlink
-                    Err(err)
-                        if err.raw_os_error() == Some(libc::EISDIR)
-                            || err.raw_os_error() == Some(libc::EPERM) =>
-                    {
-                        // if the file is a directory unlink fails with EISDIR on Linux and EPERM everyhwere else
-                        remove_dir_all_recursive(Some(fd), Path::new(&child.file_name()))?;
-                    }
-                    result => {
-                        result?;
-                    }
-                },
             }
         }
 
         // unlink the directory after removing its contents
         cvt(unsafe {
-            unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), pcstr.as_ptr(), libc::AT_REMOVEDIR)
+            unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), path.as_ptr(), libc::AT_REMOVEDIR)
         })?;
         Ok(())
     }
 
-    pub fn remove_dir_all(p: &Path) -> io::Result<()> {
+    fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
         // We cannot just call remove_dir_all_recursive() here because that would not delete a passed
         // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
         // into symlinks.
@@ -1728,7 +1695,23 @@ pub fn remove_dir_all(p: &Path) -> io::Result<()> {
         if attr.file_type().is_symlink() {
             crate::fs::remove_file(p)
         } else {
-            remove_dir_all_recursive(None, p)
+            remove_dir_all_recursive(None, &cstr(p)?)
+        }
+    }
+
+    #[cfg(not(all(target_os = "macos", target_arch = "x86_64")))]
+    pub fn remove_dir_all(p: &Path) -> io::Result<()> {
+        remove_dir_all_modern(p)
+    }
+
+    #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
+    pub fn remove_dir_all(p: &Path) -> io::Result<()> {
+        if macos_weak::has_openat() {
+            // openat() is available with macOS 10.10+, just like unlinkat() and fdopendir()
+            remove_dir_all_modern(p)
+        } else {
+            // fall back to classic implementation
+            crate::sys_common::fs::remove_dir_all(p)
         }
     }
 }
index 6d6f4c8b8dc63f4581f1823bf04adfe7cb953ecd..a98a69e2db8e12b49564f2f69bf399836b5e5cbe 100644 (file)
@@ -28,7 +28,8 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
     // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017
     // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
 
-    let mut components = path.components();
+    // Get the components, skipping the redundant leading "." component if it exists.
+    let mut components = path.strip_prefix(".").unwrap_or(path).components();
     let path_os = path.as_os_str().bytes();
 
     let mut normalized = if path.is_absolute() {
index b1faf12c2261452e1b191c8a91f3b2810ae0a3ff..1318c5b8e3a6104d98607672b91339d62e223924 100644 (file)
@@ -48,9 +48,9 @@ pub unsafe fn read(&self) {
             }
             panic!("rwlock read lock would result in deadlock");
         } else {
-            // According to POSIX, for a properly initialized rwlock this can only
-            // return EAGAIN or EDEADLK or 0. We rely on that.
-            debug_assert_eq!(r, 0);
+            // POSIX does not make guarantees about all the errors that may be returned.
+            // See issue #94705 for more details.
+            assert_eq!(r, 0, "unexpected error during rwlock read lock: {:?}", r);
             self.num_readers.fetch_add(1, Ordering::Relaxed);
         }
     }
index cf8cf5ad49f73d03f3122f7a81a318928d8e23d5..2d5d306ed62bbb7017db8845389d65d4cd79dee1 100644 (file)
@@ -279,10 +279,15 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
         ))] {
             #[cfg(any(target_os = "android", target_os = "linux"))]
             {
+                let quota = cgroup2_quota().max(1);
                 let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
-                if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
-                    let count = unsafe { libc::CPU_COUNT(&set) };
-                    return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) });
+                unsafe {
+                    if libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) == 0 {
+                        let count = libc::CPU_COUNT(&set) as usize;
+                        let count = count.min(quota);
+                        // SAFETY: affinity mask can't be empty and the quota gets clamped to a minimum of 1
+                        return Ok(NonZeroUsize::new_unchecked(count));
+                    }
                 }
             }
             match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
@@ -368,6 +373,85 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
     }
 }
 
+/// Returns cgroup CPU quota in core-equivalents, rounded down, or usize::MAX if the quota cannot
+/// be determined or is not set.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+fn cgroup2_quota() -> usize {
+    use crate::ffi::OsString;
+    use crate::fs::{try_exists, File};
+    use crate::io::Read;
+    use crate::os::unix::ffi::OsStringExt;
+    use crate::path::PathBuf;
+
+    let mut quota = usize::MAX;
+    if cfg!(miri) {
+        // Attempting to open a file fails under default flags due to isolation.
+        // And Miri does not have parallelism anyway.
+        return quota;
+    }
+
+    let _: Option<()> = try {
+        let mut buf = Vec::with_capacity(128);
+        // find our place in the cgroup hierarchy
+        File::open("/proc/self/cgroup").ok()?.read_to_end(&mut buf).ok()?;
+        let cgroup_path = buf
+            .split(|&c| c == b'\n')
+            .filter_map(|line| {
+                let mut fields = line.splitn(3, |&c| c == b':');
+                // expect cgroupv2 which has an empty 2nd field
+                if fields.nth(1) != Some(b"") {
+                    return None;
+                }
+                let path = fields.last()?;
+                // skip leading slash
+                Some(path[1..].to_owned())
+            })
+            .next()?;
+        let cgroup_path = PathBuf::from(OsString::from_vec(cgroup_path));
+
+        let mut path = PathBuf::with_capacity(128);
+        let mut read_buf = String::with_capacity(20);
+
+        let cgroup_mount = "/sys/fs/cgroup";
+
+        path.push(cgroup_mount);
+        path.push(&cgroup_path);
+
+        path.push("cgroup.controllers");
+
+        // skip if we're not looking at cgroup2
+        if matches!(try_exists(&path), Err(_) | Ok(false)) {
+            return usize::MAX;
+        };
+
+        path.pop();
+
+        while path.starts_with(cgroup_mount) {
+            path.push("cpu.max");
+
+            read_buf.clear();
+
+            if File::open(&path).and_then(|mut f| f.read_to_string(&mut read_buf)).is_ok() {
+                let raw_quota = read_buf.lines().next()?;
+                let mut raw_quota = raw_quota.split(' ');
+                let limit = raw_quota.next()?;
+                let period = raw_quota.next()?;
+                match (limit.parse::<usize>(), period.parse::<usize>()) {
+                    (Ok(limit), Ok(period)) => {
+                        quota = quota.min(limit / period);
+                    }
+                    _ => {}
+                }
+            }
+
+            path.pop(); // pop filename
+            path.pop(); // pop dir
+        }
+    };
+
+    quota
+}
+
 #[cfg(all(
     not(target_os = "linux"),
     not(target_os = "freebsd"),
index 2affd7e75b03082b3f49d2a2f2e4dcb1c9007932..9b61b2476d5bbdd55c811b00d9493b098215cb5b 100644 (file)
@@ -6,6 +6,7 @@
 
 use crate::mem;
 use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
+use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull};
 use crate::ptr;
 use core::ffi::NonZero_c_ulong;
 
@@ -886,7 +887,7 @@ pub fn CreateThread(
         lpParameter: LPVOID,
         dwCreationFlags: DWORD,
         lpThreadId: LPDWORD,
-    ) -> HANDLE;
+    ) -> HandleOrNull;
     pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
     pub fn SwitchToThread() -> BOOL;
     pub fn Sleep(dwMilliseconds: DWORD);
@@ -950,14 +951,14 @@ pub fn DuplicateHandle(
         dwOptions: DWORD,
     ) -> BOOL;
     pub fn ReadFile(
-        hFile: HANDLE,
+        hFile: BorrowedHandle<'_>,
         lpBuffer: LPVOID,
         nNumberOfBytesToRead: DWORD,
         lpNumberOfBytesRead: LPDWORD,
         lpOverlapped: LPOVERLAPPED,
     ) -> BOOL;
     pub fn WriteFile(
-        hFile: HANDLE,
+        hFile: BorrowedHandle<'_>,
         lpBuffer: LPVOID,
         nNumberOfBytesToWrite: DWORD,
         lpNumberOfBytesWritten: LPDWORD,
@@ -981,7 +982,7 @@ pub fn CreateFileW(
         dwCreationDisposition: DWORD,
         dwFlagsAndAttributes: DWORD,
         hTemplateFile: HANDLE,
-    ) -> HANDLE;
+    ) -> HandleOrInvalid;
 
     pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE;
     pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL;
index cb83ee2469a1c685f204f704550ca8be42d398de..d6c40a15329a96a9091aa9c6936d1fed7e1ad79c 100644 (file)
@@ -1,5 +1,6 @@
 use crate::os::windows::prelude::*;
 
+use crate::convert::TryInto;
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
@@ -294,10 +295,10 @@ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
                 ptr::null_mut(),
             )
         };
-        if handle == c::INVALID_HANDLE_VALUE {
-            Err(Error::last_os_error())
+        if let Ok(handle) = handle.try_into() {
+            Ok(File { handle: Handle::from_inner(handle) })
         } else {
-            unsafe { Ok(File { handle: Handle::from_raw_handle(handle) }) }
+            Err(Error::last_os_error())
         }
     }
 
index daab39bb00cbcd9a0c556d935bbfc66b7b697953..e5c9567957bc1db5c5e52c9eb0bd5fde8de807aa 100644 (file)
@@ -78,7 +78,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         let res = cvt(unsafe {
             c::ReadFile(
-                self.as_raw_handle(),
+                self.as_handle(),
                 buf.as_mut_ptr() as c::LPVOID,
                 len,
                 &mut read,
@@ -116,7 +116,7 @@ pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
             overlapped.Offset = offset as u32;
             overlapped.OffsetHigh = (offset >> 32) as u32;
             cvt(c::ReadFile(
-                self.as_raw_handle(),
+                self.as_handle(),
                 buf.as_mut_ptr() as c::LPVOID,
                 len,
                 &mut read,
@@ -135,7 +135,7 @@ pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
         let len = cmp::min(buf.remaining(), <c::DWORD>::MAX as usize) as c::DWORD;
         let res = cvt(unsafe {
             c::ReadFile(
-                self.as_raw_handle(),
+                self.as_handle(),
                 buf.unfilled_mut().as_mut_ptr() as c::LPVOID,
                 len,
                 &mut read,
@@ -171,7 +171,7 @@ pub unsafe fn read_overlapped(
         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         let mut amt = 0;
         let res = cvt(c::ReadFile(
-            self.as_raw_handle(),
+            self.as_handle(),
             buf.as_ptr() as c::LPVOID,
             len,
             &mut amt,
@@ -225,7 +225,7 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         cvt(unsafe {
             c::WriteFile(
-                self.as_raw_handle(),
+                self.as_handle(),
                 buf.as_ptr() as c::LPVOID,
                 len,
                 &mut amt,
@@ -252,7 +252,7 @@ pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
             overlapped.Offset = offset as u32;
             overlapped.OffsetHigh = (offset >> 32) as u32;
             cvt(c::WriteFile(
-                self.as_raw_handle(),
+                self.as_handle(),
                 buf.as_ptr() as c::LPVOID,
                 len,
                 &mut written,
index dc288176346bcb4dfe4413836e031478060b6f30..6097e628768479b44c86b31d45d047cc390c8be2 100644 (file)
@@ -224,8 +224,14 @@ fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
             } as usize;
             if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
                 n *= 2;
-            } else if k >= n {
+            } else if k > n {
                 n = k;
+            } else if k == n {
+                // It is impossible to reach this point.
+                // On success, k is the returned string length excluding the null.
+                // On failure, k is the required buffer length including the null.
+                // Therefore k never equals n.
+                unreachable!();
             } else {
                 return Ok(f2(&buf[..k]));
             }
index e4bba9255d23e774849196a88f09ee882638be2c..2f469513eb4fd63ac50c2b9f022ea1eab90ec30e 100644 (file)
@@ -1,11 +1,13 @@
+use crate::convert::TryInto;
 use crate::ffi::CStr;
 use crate::io;
 use crate::num::NonZeroUsize;
-use crate::os::windows::io::{AsRawHandle, FromRawHandle};
+use crate::os::windows::io::AsRawHandle;
 use crate::ptr;
 use crate::sys::c;
 use crate::sys::handle::Handle;
 use crate::sys::stack_overflow;
+use crate::sys_common::FromInner;
 use crate::time::Duration;
 
 use libc::c_void;
@@ -28,25 +30,22 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
         // just that below a certain threshold you can't do anything useful.
         // That threshold is application and architecture-specific, however.
-        // Round up to the next 64 kB because that's what the NT kernel does,
-        // might as well make it explicit.
-        let stack_size = (stack + 0xfffe) & (!0xfffe);
         let ret = c::CreateThread(
             ptr::null_mut(),
-            stack_size,
+            stack,
             thread_start,
             p as *mut _,
             c::STACK_SIZE_PARAM_IS_A_RESERVATION,
             ptr::null_mut(),
         );
 
-        return if ret as usize == 0 {
+        return if let Ok(handle) = ret.try_into() {
+            Ok(Thread { handle: Handle::from_inner(handle) })
+        } else {
             // 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::last_os_error())
-        } else {
-            Ok(Thread { handle: Handle::from_raw_handle(ret) })
         };
 
         extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
index 2464a0e2e473cee1b8cfe36ba8c11a2f7d5effcf..a100444f04968b9ff653991d03556445451a218d 100644 (file)
@@ -8,6 +8,7 @@
 #[cfg(test)]
 mod dynamic_tests;
 
+use crate::cell::{Cell, RefCell};
 use crate::error::Error;
 use crate::fmt;
 
@@ -108,7 +109,7 @@ pub struct LocalKey<T: 'static> {
     // trivially devirtualizable by LLVM because the value of `inner` never
     // changes and the constant should be readonly within a crate. This mainly
     // only runs into problems when TLS statics are exported across crates.
-    inner: unsafe fn() -> Option<&'static T>,
+    inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -178,7 +179,9 @@ macro_rules! __thread_local_inner {
     // used to generate the `LocalKey` value for const-initialized thread locals
     (@key $t:ty, const $init:expr) => {{
         #[cfg_attr(not(windows), inline(always))] // see comments below
-        unsafe fn __getit() -> $crate::option::Option<&'static $t> {
+        unsafe fn __getit(
+            _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
+        ) -> $crate::option::Option<&'static $t> {
             const INIT_EXPR: $t = $init;
 
             // wasm without atomics maps directly to `static mut`, and dtors
@@ -260,7 +263,18 @@ const fn __init() -> $t { INIT_EXPR }
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
                 #[allow(unused_unsafe)]
-                unsafe { __KEY.get(__init) }
+                unsafe {
+                    __KEY.get(move || {
+                        if let $crate::option::Option::Some(init) = _init {
+                            if let $crate::option::Option::Some(value) = init.take() {
+                                return value;
+                            } else if $crate::cfg!(debug_assertions) {
+                                unreachable!("missing initial value");
+                            }
+                        }
+                        __init()
+                    })
+                }
             }
         }
 
@@ -298,7 +312,9 @@ fn __init() -> $t { $init }
             //
             // The issue of "should enable on Windows sometimes" is #84933
             #[cfg_attr(not(windows), inline(always))]
-            unsafe fn __getit() -> $crate::option::Option<&'static $t> {
+            unsafe fn __getit(
+                init: $crate::option::Option<&mut $crate::option::Option<$t>>,
+            ) -> $crate::option::Option<&'static $t> {
                 #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
                     $crate::thread::__StaticLocalKeyInner::new();
@@ -322,7 +338,18 @@ unsafe fn __getit() -> $crate::option::Option<&'static $t> {
                 // raise warning for missing/extraneous unsafe blocks anymore.
                 // See https://github.com/rust-lang/rust/issues/74838.
                 #[allow(unused_unsafe)]
-                unsafe { __KEY.get(__init) }
+                unsafe {
+                    __KEY.get(move || {
+                        if let $crate::option::Option::Some(init) = init {
+                            if let $crate::option::Option::Some(value) = init.take() {
+                                return value;
+                            } else if $crate::cfg!(debug_assertions) {
+                                unreachable!("missing default value");
+                            }
+                        }
+                        __init()
+                    })
+                }
             }
 
             unsafe {
@@ -367,7 +394,9 @@ impl<T: 'static> LocalKey<T> {
         issue = "none"
     )]
     #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
-    pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey<T> {
+    pub const unsafe fn new(
+        inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
+    ) -> LocalKey<T> {
         LocalKey { inner }
     }
 
@@ -409,10 +438,342 @@ pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
         F: FnOnce(&T) -> R,
     {
         unsafe {
-            let thread_local = (self.inner)().ok_or(AccessError)?;
+            let thread_local = (self.inner)(None).ok_or(AccessError)?;
             Ok(f(thread_local))
         }
     }
+
+    /// Acquires a reference to the value in this TLS key, initializing it with
+    /// `init` if it wasn't already initialized on this thread.
+    ///
+    /// If `init` was used to initialize the thread local variable, `None` is
+    /// passed as the first argument to `f`. If it was already initialized,
+    /// `Some(init)` is passed to `f`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the key currently has its destructor
+    /// running, and it **may** panic if the destructor has previously been run
+    /// for this thread.
+    fn initialize_with<F, R>(&'static self, init: T, f: F) -> R
+    where
+        F: FnOnce(Option<T>, &T) -> R,
+    {
+        unsafe {
+            let mut init = Some(init);
+            let reference = (self.inner)(Some(&mut init)).expect(
+                "cannot access a Thread Local Storage value \
+                 during or after destruction",
+            );
+            f(init, reference)
+        }
+    }
+}
+
+impl<T: 'static> LocalKey<Cell<T>> {
+    /// Sets or initializes the contained value.
+    ///
+    /// Unlike the other methods, this will *not* run the lazy initializer of
+    /// the thread local. Instead, it will be directly initialized with the
+    /// given value if it wasn't initialized yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::Cell;
+    ///
+    /// thread_local! {
+    ///     static X: Cell<i32> = panic!("!");
+    /// }
+    ///
+    /// // Calling X.get() here would result in a panic.
+    ///
+    /// X.set(123); // But X.set() is fine, as it skips the initializer above.
+    ///
+    /// assert_eq!(X.get(), 123);
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn set(&'static self, value: T) {
+        self.initialize_with(Cell::new(value), |value, cell| {
+            if let Some(value) = value {
+                // The cell was already initialized, so `value` wasn't used to
+                // initialize it. So we overwrite the current value with the
+                // new one instead.
+                cell.set(value.into_inner());
+            }
+        });
+    }
+
+    /// Returns a copy of the contained value.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::Cell;
+    ///
+    /// thread_local! {
+    ///     static X: Cell<i32> = Cell::new(1);
+    /// }
+    ///
+    /// assert_eq!(X.get(), 1);
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn get(&'static self) -> T
+    where
+        T: Copy,
+    {
+        self.with(|cell| cell.get())
+    }
+
+    /// Takes the contained value, leaving `Default::default()` in its place.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::Cell;
+    ///
+    /// thread_local! {
+    ///     static X: Cell<Option<i32>> = Cell::new(Some(1));
+    /// }
+    ///
+    /// assert_eq!(X.take(), Some(1));
+    /// assert_eq!(X.take(), None);
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn take(&'static self) -> T
+    where
+        T: Default,
+    {
+        self.with(|cell| cell.take())
+    }
+
+    /// Replaces the contained value, returning the old value.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::Cell;
+    ///
+    /// thread_local! {
+    ///     static X: Cell<i32> = Cell::new(1);
+    /// }
+    ///
+    /// assert_eq!(X.replace(2), 1);
+    /// assert_eq!(X.replace(3), 2);
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn replace(&'static self, value: T) -> T {
+        self.with(|cell| cell.replace(value))
+    }
+}
+
+impl<T: 'static> LocalKey<RefCell<T>> {
+    /// Acquires a reference to the contained value.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the value is currently mutably borrowed.
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::RefCell;
+    ///
+    /// thread_local! {
+    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
+    /// }
+    ///
+    /// X.with_borrow(|v| assert!(v.is_empty()));
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn with_borrow<F, R>(&'static self, f: F) -> R
+    where
+        F: FnOnce(&T) -> R,
+    {
+        self.with(|cell| f(&cell.borrow()))
+    }
+
+    /// Acquires a mutable reference to the contained value.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the value is currently borrowed.
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::RefCell;
+    ///
+    /// thread_local! {
+    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
+    /// }
+    ///
+    /// X.with_borrow_mut(|v| v.push(1));
+    ///
+    /// X.with_borrow(|v| assert_eq!(*v, vec![1]));
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn with_borrow_mut<F, R>(&'static self, f: F) -> R
+    where
+        F: FnOnce(&mut T) -> R,
+    {
+        self.with(|cell| f(&mut cell.borrow_mut()))
+    }
+
+    /// Sets or initializes the contained value.
+    ///
+    /// Unlike the other methods, this will *not* run the lazy initializer of
+    /// the thread local. Instead, it will be directly initialized with the
+    /// given value if it wasn't initialized yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the value is currently borrowed.
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::RefCell;
+    ///
+    /// thread_local! {
+    ///     static X: RefCell<Vec<i32>> = panic!("!");
+    /// }
+    ///
+    /// // Calling X.with() here would result in a panic.
+    ///
+    /// X.set(vec![1, 2, 3]); // But X.set() is fine, as it skips the initializer above.
+    ///
+    /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn set(&'static self, value: T) {
+        self.initialize_with(RefCell::new(value), |value, cell| {
+            if let Some(value) = value {
+                // The cell was already initialized, so `value` wasn't used to
+                // initialize it. So we overwrite the current value with the
+                // new one instead.
+                *cell.borrow_mut() = value.into_inner();
+            }
+        });
+    }
+
+    /// Takes the contained value, leaving `Default::default()` in its place.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the value is currently borrowed.
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::RefCell;
+    ///
+    /// thread_local! {
+    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
+    /// }
+    ///
+    /// X.with_borrow_mut(|v| v.push(1));
+    ///
+    /// let a = X.take();
+    ///
+    /// assert_eq!(a, vec![1]);
+    ///
+    /// X.with_borrow(|v| assert!(v.is_empty()));
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn take(&'static self) -> T
+    where
+        T: Default,
+    {
+        self.with(|cell| cell.take())
+    }
+
+    /// Replaces the contained value, returning the old value.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the value is currently borrowed.
+    ///
+    /// Panics if the key currently has its destructor running,
+    /// and it **may** panic if the destructor has previously been run for this thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(local_key_cell_methods)]
+    /// use std::cell::RefCell;
+    ///
+    /// thread_local! {
+    ///     static X: RefCell<Vec<i32>> = RefCell::new(Vec::new());
+    /// }
+    ///
+    /// let prev = X.replace(vec![1, 2, 3]);
+    /// assert!(prev.is_empty());
+    ///
+    /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
+    /// ```
+    #[unstable(feature = "local_key_cell_methods", issue = "92122")]
+    pub fn replace(&'static self, value: T) -> T {
+        self.with(|cell| cell.replace(value))
+    }
 }
 
 mod lazy {
@@ -518,7 +879,7 @@ pub const fn new() -> Key<T> {
             Key { inner: LazyKeyInner::new() }
         }
 
-        pub unsafe fn get(&self, init: fn() -> T) -> Option<&'static T> {
+        pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> {
             // SAFETY: The caller must ensure no reference is ever handed out to
             // the inner cell nor mutable reference to the Option<T> inside said
             // cell. This make it safe to hand a reference, though the lifetime
@@ -707,7 +1068,7 @@ pub const fn new() -> Key<T> {
 
         /// It is a requirement for the caller to ensure that no mutable
         /// reference is active when this method is called.
-        pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> {
+        pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
             // SAFETY: See the documentation for this method.
             let ptr = unsafe { self.os.get() as *mut Value<T> };
             if ptr as usize > 1 {
@@ -725,7 +1086,7 @@ pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> {
         // `try_initialize` is only called once per os thread local variable,
         // except in corner cases where thread_local dtors reference other
         // thread_local's, or it is being recursively initialized.
-        unsafe fn try_initialize(&'static self, init: fn() -> T) -> Option<&'static T> {
+        unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
             // SAFETY: No mutable references are ever handed out meaning getting
             // the value is ok.
             let ptr = unsafe { self.os.get() as *mut Value<T> };
index beb606099341e7b3bede77ecaffd6c5d5e75fed0..5ffc86b4560fc9221a2111dfb530ed26fe1f7549 100644 (file)
@@ -1443,13 +1443,18 @@ pub fn join(self) -> Result<T> {
         self.0.join()
     }
 
-    /// Checks if the associated thread is still running its main function.
+    /// Checks if the associated thread has finished running its main function.
     ///
-    /// This might return `false` for a brief moment after the thread's main
+    /// This might return `true` for a brief moment after the thread's main
     /// function has returned, but before the thread itself has stopped running.
+    /// However, once this returns `true`, [`join`][Self::join] can be expected
+    /// to return quickly, without blocking for any significant amount of time.
+    ///
+    /// This function does not block. To block while waiting on the thread to finish,
+    /// use [`join`][Self::join].
     #[unstable(feature = "thread_is_running", issue = "90470")]
-    pub fn is_running(&self) -> bool {
-        Arc::strong_count(&self.0.packet) > 1
+    pub fn is_finished(&self) -> bool {
+        Arc::strong_count(&self.0.packet) == 1
     }
 }
 
@@ -1524,7 +1529,10 @@ fn _assert_both<T: Send + Sync>() {}
 ///
 /// On Linux:
 /// - It may overcount the amount of parallelism available when limited by a
-///   process-wide affinity mask, or when affected by cgroup limits.
+///   process-wide affinity mask or cgroup quotas and cgroup2 fs or `sched_getaffinity()` can't be
+///   queried, e.g. due to sandboxing.
+/// - It may undercount the amount of parallelism if the current thread's affinity mask
+///   does not reflect the process' cpuset, e.g. due to pinned threads.
 ///
 /// On all targets:
 /// - It may overcount the amount of parallelism available when running in a VM
index 9dd7c15fc592236e1c66337ba2223d757ad56dac..4af58f1a3807533b9ba4e143a63326122002a8ba 100644 (file)
@@ -9,23 +9,24 @@
 /// A scope to spawn scoped threads in.
 ///
 /// See [`scope`] for details.
-pub struct Scope<'env> {
+pub struct Scope<'scope, 'env: 'scope> {
     data: ScopeData,
-    /// Invariance over 'env, to make sure 'env cannot shrink,
+    /// Invariance over 'scope, to make sure 'scope cannot shrink,
     /// which is necessary for soundness.
     ///
     /// Without invariance, this would compile fine but be unsound:
     ///
-    /// ```compile_fail
+    /// ```compile_fail,E0373
     /// #![feature(scoped_threads)]
     ///
     /// std::thread::scope(|s| {
-    ///     s.spawn(|s| {
+    ///     s.spawn(|| {
     ///         let a = String::from("abcd");
-    ///         s.spawn(|_| println!("{:?}", a)); // might run after `a` is dropped
+    ///         s.spawn(|| println!("{:?}", a)); // might run after `a` is dropped
     ///     });
     /// });
     /// ```
+    scope: PhantomData<&'scope mut &'scope ()>,
     env: PhantomData<&'env mut &'env ()>,
 }
 
@@ -88,12 +89,12 @@ pub(super) fn decrement_num_running_threads(&self, panic: bool) {
 /// let mut x = 0;
 ///
 /// thread::scope(|s| {
-///     s.spawn(|_| {
+///     s.spawn(|| {
 ///         println!("hello from the first scoped thread");
 ///         // We can borrow `a` here.
 ///         dbg!(&a);
 ///     });
-///     s.spawn(|_| {
+///     s.spawn(|| {
 ///         println!("hello from the second scoped thread");
 ///         // We can even mutably borrow `x` here,
 ///         // because no other threads are using it.
@@ -109,7 +110,7 @@ pub(super) fn decrement_num_running_threads(&self, panic: bool) {
 #[track_caller]
 pub fn scope<'env, F, T>(f: F) -> T
 where
-    F: FnOnce(&Scope<'env>) -> T,
+    F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
 {
     let scope = Scope {
         data: ScopeData {
@@ -118,6 +119,7 @@ pub fn scope<'env, F, T>(f: F) -> T
             a_thread_panicked: AtomicBool::new(false),
         },
         env: PhantomData,
+        scope: PhantomData,
     };
 
     // Run `f`, but catch panics so we can make sure to wait for all the threads to join.
@@ -138,7 +140,7 @@ pub fn scope<'env, F, T>(f: F) -> T
     }
 }
 
-impl<'env> Scope<'env> {
+impl<'scope, 'env> Scope<'scope, 'env> {
     /// Spawns a new thread within a scope, returning a [`ScopedJoinHandle`] for it.
     ///
     /// Unlike non-scoped threads, threads spawned with this function may
@@ -163,10 +165,10 @@ impl<'env> Scope<'env> {
     /// to recover from such errors.
     ///
     /// [`join`]: ScopedJoinHandle::join
-    pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
+    pub fn spawn<F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
     where
-        F: FnOnce(&Scope<'env>) -> T + Send + 'env,
-        T: Send + 'env,
+        F: FnOnce() -> T + Send + 'scope,
+        T: Send + 'scope,
     {
         Builder::new().spawn_scoped(self, f).expect("failed to spawn thread")
     }
@@ -196,7 +198,7 @@ impl Builder {
     /// thread::scope(|s| {
     ///     thread::Builder::new()
     ///         .name("first".to_string())
-    ///         .spawn_scoped(s, |_|
+    ///         .spawn_scoped(s, ||
     ///     {
     ///         println!("hello from the {:?} scoped thread", thread::current().name());
     ///         // We can borrow `a` here.
@@ -205,7 +207,7 @@ impl Builder {
     ///     .unwrap();
     ///     thread::Builder::new()
     ///         .name("second".to_string())
-    ///         .spawn_scoped(s, |_|
+    ///         .spawn_scoped(s, ||
     ///     {
     ///         println!("hello from the {:?} scoped thread", thread::current().name());
     ///         // We can even mutably borrow `x` here,
@@ -222,14 +224,14 @@ impl Builder {
     /// ```
     pub fn spawn_scoped<'scope, 'env, F, T>(
         self,
-        scope: &'scope Scope<'env>,
+        scope: &'scope Scope<'scope, 'env>,
         f: F,
     ) -> io::Result<ScopedJoinHandle<'scope, T>>
     where
-        F: FnOnce(&Scope<'env>) -> T + Send + 'env,
-        T: Send + 'env,
+        F: FnOnce() -> T + Send + 'scope,
+        T: Send + 'scope,
     {
-        Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(|| f(scope), Some(&scope.data)) }?))
+        Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(&scope.data)) }?))
     }
 }
 
@@ -240,12 +242,11 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
     ///
     /// ```
     /// #![feature(scoped_threads)]
-    /// #![feature(thread_is_running)]
     ///
     /// use std::thread;
     ///
     /// thread::scope(|s| {
-    ///     let t = s.spawn(|_| {
+    ///     let t = s.spawn(|| {
     ///         println!("hello");
     ///     });
     ///     println!("thread id: {:?}", t.thread().id());
@@ -274,12 +275,11 @@ pub fn thread(&self) -> &Thread {
     ///
     /// ```
     /// #![feature(scoped_threads)]
-    /// #![feature(thread_is_running)]
     ///
     /// use std::thread;
     ///
     /// thread::scope(|s| {
-    ///     let t = s.spawn(|_| {
+    ///     let t = s.spawn(|| {
     ///         panic!("oh no");
     ///     });
     ///     assert!(t.join().is_err());
@@ -289,17 +289,22 @@ pub fn join(self) -> Result<T> {
         self.0.join()
     }
 
-    /// Checks if the associated thread is still running its main function.
+    /// Checks if the associated thread has finished running its main function.
     ///
-    /// This might return `false` for a brief moment after the thread's main
+    /// This might return `true` for a brief moment after the thread's main
     /// function has returned, but before the thread itself has stopped running.
+    /// However, once this returns `true`, [`join`][Self::join] can be expected
+    /// to return quickly, without blocking for any significant amount of time.
+    ///
+    /// This function does not block. To block while waiting on the thread to finish,
+    /// use [`join`][Self::join].
     #[unstable(feature = "thread_is_running", issue = "90470")]
-    pub fn is_running(&self) -> bool {
-        Arc::strong_count(&self.0.packet) > 1
+    pub fn is_finished(&self) -> bool {
+        Arc::strong_count(&self.0.packet) == 1
     }
 }
 
-impl<'env> fmt::Debug for Scope<'env> {
+impl fmt::Debug for Scope<'_, '_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Scope")
             .field("num_running_threads", &self.data.num_running_threads.load(Ordering::Relaxed))
index 4f2c81731a335fd3c163bc849adb1dc1e2e21e80..3323ba36bf31091798f939babdc64cb2ae932a6b 100644 (file)
@@ -52,7 +52,7 @@ fn test_run_basic() {
 }
 
 #[test]
-fn test_is_running() {
+fn test_is_finished() {
     let b = Arc::new(Barrier::new(2));
     let t = thread::spawn({
         let b = b.clone();
@@ -63,14 +63,14 @@ fn test_is_running() {
     });
 
     // Thread is definitely running here, since it's still waiting for the barrier.
-    assert_eq!(t.is_running(), true);
+    assert_eq!(t.is_finished(), false);
 
     // Unblock the barrier.
     b.wait();
 
-    // Now check that t.is_running() becomes false within a reasonable time.
+    // Now check that t.is_finished() becomes true within a reasonable time.
     let start = Instant::now();
-    while t.is_running() {
+    while !t.is_finished() {
         assert!(start.elapsed() < Duration::from_secs(2));
         thread::sleep(Duration::from_millis(15));
     }
index c8c5528b104ebeb24e6e76592f3d0137ec9cda96..432628613f586e0480d06dc45a7aa3397cfa36a5 100644 (file)
@@ -249,6 +249,10 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
     extern "C-unwind" {
         pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
     }
+    #[cfg_attr(
+        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        link(name = "unwind", kind = "static", modifiers = "-bundle")
+    )]
     extern "C" {
         pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                  trace_argument: *mut c_void)
index 592a137e379dea7a77e041124fd319d0d7d73cba..4c32547f0590b6178241808a0cd70440fab63598 100644 (file)
@@ -3,6 +3,7 @@ name = "bootstrap"
 version = "0.0.0"
 edition = "2021"
 build = "build.rs"
+default-run = "bootstrap"
 
 [lib]
 path = "lib.rs"
@@ -34,10 +35,8 @@ path = "bin/llvm-config-wrapper.rs"
 test = false
 
 [dependencies]
-build_helper = { path = "../build_helper" }
 cmake = "0.1.38"
 filetime = "0.2"
-num_cpus = "1.0"
 getopts = "0.2.19"
 cc = "1.0.69"
 libc = "0.2"
index 6c1128b393fed9207bb2662cdc5beeffa0f69260..1777dae594f8e3fa7595e74bbc7f67ca6b018e6e 100644 (file)
@@ -1267,7 +1267,7 @@ def bootstrap(help_triggered):
     build.check_vendored_status()
 
     build_dir = build.get_toml('build-dir', 'build') or 'build'
-    build.build_dir = os.path.abspath(build_dir.replace("$ROOT", build.rust_root))
+    build.build_dir = os.path.abspath(build_dir)
 
     with open(os.path.join(build.rust_root, "src", "stage0.json")) as f:
         data = json.load(f)
@@ -1302,10 +1302,7 @@ def bootstrap(help_triggered):
     env = os.environ.copy()
     env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
     env["BOOTSTRAP_PYTHON"] = sys.executable
-    env["BUILD_DIR"] = build.build_dir
     env["RUSTC_BOOTSTRAP"] = '1'
-    if toml_path:
-        env["BOOTSTRAP_CONFIG"] = toml_path
     if build.rustc_commit is not None:
         env["BOOTSTRAP_DOWNLOAD_RUSTC"] = '1'
     run(args, env=env, verbose=build.verbose, is_bootstrap=True)
index 4f88b5854b69293b73c1eead19264e184487992a..1903f0baef1fae4d71a8f0ce3210e3a7e334965b 100644 (file)
@@ -11,8 +11,6 @@
 use std::process::Command;
 use std::time::{Duration, Instant};
 
-use build_helper::{output, t};
-
 use crate::cache::{Cache, Interned, INTERNER};
 use crate::check;
 use crate::compile;
@@ -25,8 +23,9 @@
 use crate::run;
 use crate::test;
 use crate::tool::{self, SourceType};
-use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir};
-use crate::{Build, DocTests, GitRepo, Mode};
+use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
+use crate::EXTRA_CHECK_CFGS;
+use crate::{Build, CLang, DocTests, GitRepo, Mode};
 
 pub use crate::Compiler;
 // FIXME: replace with std::lazy after it gets stabilized and reaches beta
@@ -884,7 +883,7 @@ pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
     }
 
     pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command {
-        let mut cmd = Command::new(&self.out.join("bootstrap/debug/rustdoc"));
+        let mut cmd = Command::new(&self.bootstrap_out.join("rustdoc"));
         cmd.env("RUSTC_STAGE", compiler.stage.to_string())
             .env("RUSTC_SYSROOT", self.sysroot(compiler))
             // Note that this is *not* the sysroot_libdir because rustdoc must be linked
@@ -1095,6 +1094,33 @@ pub fn cargo(
             rustflags.arg("-Zunstable-options");
         }
 
+        // #[cfg(not(bootstrap)]
+        if stage != 0 {
+            // Enable cfg checking of cargo features
+            // FIXME: De-comment this when cargo beta get support for it
+            // cargo.arg("-Zcheck-cfg-features");
+
+            // Enable cfg checking of rustc well-known names
+            rustflags.arg("-Zunstable-options").arg("--check-cfg=names()");
+
+            // Add extra cfg not defined in rustc
+            for (restricted_mode, name, values) in EXTRA_CHECK_CFGS {
+                if *restricted_mode == None || *restricted_mode == Some(mode) {
+                    // Creating a string of the values by concatenating each value:
+                    // ',"tvos","watchos"' or '' (nothing) when there are no values
+                    let values = match values {
+                        Some(values) => values
+                            .iter()
+                            .map(|val| [",", "\"", val, "\""])
+                            .flatten()
+                            .collect::<String>(),
+                        None => String::new(),
+                    };
+                    rustflags.arg(&format!("--check-cfg=values({name}{values})"));
+                }
+            }
+        }
+
         // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`,
         // but this breaks CI. At the very least, stage0 `rustdoc` needs `--cfg bootstrap`. See
         // #71458.
@@ -1223,7 +1249,7 @@ pub fn cargo(
             .env("RUSTC_STAGE", stage.to_string())
             .env("RUSTC_SYSROOT", &sysroot)
             .env("RUSTC_LIBDIR", &libdir)
-            .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
+            .env("RUSTDOC", self.bootstrap_out.join("rustdoc"))
             .env(
                 "RUSTDOC_REAL",
                 if cmd == "doc" || cmd == "rustdoc" || (cmd == "test" && want_rustdoc) {
@@ -1237,7 +1263,7 @@ pub fn cargo(
         // Clippy support is a hack and uses the default `cargo-clippy` in path.
         // Don't override RUSTC so that the `cargo-clippy` in path will be run.
         if cmd != "clippy" {
-            cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc"));
+            cargo.env("RUSTC", self.bootstrap_out.join("rustc"));
         }
 
         // Dealing with rpath here is a little special, so let's go into some
@@ -1511,7 +1537,7 @@ pub fn cargo(
             let cc = ccacheify(&self.cc(target));
             cargo.env(format!("CC_{}", target.triple), &cc);
 
-            let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
+            let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" ");
             cargo.env(format!("CFLAGS_{}", target.triple), &cflags);
 
             if let Some(ar) = self.ar(target) {
@@ -1523,9 +1549,10 @@ pub fn cargo(
 
             if let Ok(cxx) = self.cxx(target) {
                 let cxx = ccacheify(&cxx);
+                let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" ");
                 cargo
                     .env(format!("CXX_{}", target.triple), &cxx)
-                    .env(format!("CXXFLAGS_{}", target.triple), cflags);
+                    .env(format!("CXXFLAGS_{}", target.triple), cxxflags);
             }
         }
 
index bc71034496968ff3fad5a502309b39e65ae72408..b76bb569852cdb9806b1f8664b619a258cf5c28f 100644 (file)
@@ -8,10 +8,10 @@ fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
     config.save_toolstates = None;
     config.dry_run = true;
     config.ninja_in_file = false;
-    // try to avoid spurious failures in dist where we create/delete each others file
     config.out = PathBuf::from(env::var_os("BOOTSTRAP_OUTPUT_DIRECTORY").unwrap());
     config.initial_rustc = PathBuf::from(env::var_os("RUSTC").unwrap());
     config.initial_cargo = PathBuf::from(env::var_os("BOOTSTRAP_INITIAL_CARGO").unwrap());
+    // try to avoid spurious failures in dist where we create/delete each others file
     let dir = config
         .out
         .join("tmp-rustbuild-tests")
index e750c2963dddcc403282ccd892255074d93582da..7ce446876118af13244c4c914dc2dfcdf1ca525a 100644 (file)
 use std::process::Command;
 use std::{env, iter};
 
-use build_helper::output;
-
 use crate::config::{Target, TargetSelection};
-use crate::{Build, GitRepo};
+use crate::util::output;
+use crate::{Build, CLang, GitRepo};
 
 // The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
 // so use some simplified logic here. First we respect the environment variable `AR`, then
@@ -109,7 +108,7 @@ pub fn find(build: &mut Build) {
         };
 
         build.cc.insert(target, compiler.clone());
-        let cflags = build.cflags(target, GitRepo::Rustc);
+        let cflags = build.cflags(target, GitRepo::Rustc, CLang::C);
 
         // If we use llvm-libunwind, we will need a C++ compiler as well for all targets
         // We'll need one anyways if the target triple is also a host triple
@@ -142,8 +141,9 @@ pub fn find(build: &mut Build) {
         build.verbose(&format!("CC_{} = {:?}", &target.triple, build.cc(target)));
         build.verbose(&format!("CFLAGS_{} = {:?}", &target.triple, cflags));
         if let Ok(cxx) = build.cxx(target) {
+            let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
             build.verbose(&format!("CXX_{} = {:?}", &target.triple, cxx));
-            build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cflags));
+            build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags));
         }
         if let Some(ar) = ar {
             build.verbose(&format!("AR_{} = {:?}", &target.triple, ar));
index 6478578c3c402cd3ab6625d8cb60729aa50b7c4a..1932a0017ee255e5539b8901401c6ecd2efd9350 100644 (file)
@@ -8,8 +8,7 @@
 use std::path::Path;
 use std::process::Command;
 
-use build_helper::output;
-
+use crate::util::output;
 use crate::Build;
 
 pub enum GitInfo {
index 3b73dc1c7df74bb5ade409e9dfb74cb47a0fef7b..069f3d6acf158937d278a13a277bec4e90c762c6 100644 (file)
@@ -9,8 +9,7 @@
 use std::io::{self, ErrorKind};
 use std::path::Path;
 
-use build_helper::t;
-
+use crate::util::t;
 use crate::Build;
 
 pub fn clean(build: &Build, all: bool) {
index b4c6210b3881487916fcbab32617ad10573605ec..9cfd9f92aa7cdb05021bd52027866660b480f171 100644 (file)
@@ -16,7 +16,6 @@
 use std::process::{exit, Command, Stdio};
 use std::str;
 
-use build_helper::{output, t, up_to_date};
 use serde::Deserialize;
 
 use crate::builder::Cargo;
@@ -26,9 +25,9 @@
 use crate::dist;
 use crate::native;
 use crate::tool::SourceType;
-use crate::util::{exe, is_debug_info, is_dylib, symlink_dir};
+use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date};
 use crate::LLVM_TOOLS;
-use crate::{Compiler, DependencyType, GitRepo, Mode};
+use crate::{CLang, Compiler, DependencyType, GitRepo, Mode};
 
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
@@ -249,7 +248,7 @@ fn copy_self_contained_objects(
         }
     } else if target.contains("windows-gnu") {
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
-            let src = compiler_file(builder, builder.cc(target), target, obj);
+            let src = compiler_file(builder, builder.cc(target), target, CLang::C, obj);
             let target = libdir_self_contained.join(obj);
             builder.copy(&src, &target);
             target_deps.push((target, DependencyType::TargetSelfContained));
@@ -727,7 +726,13 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
             && !target.contains("msvc")
             && !target.contains("apple")
         {
-            let file = compiler_file(builder, builder.cxx(target).unwrap(), target, "libstdc++.a");
+            let file = compiler_file(
+                builder,
+                builder.cxx(target).unwrap(),
+                target,
+                CLang::Cxx,
+                "libstdc++.a",
+            );
             cargo.env("LLVM_STATIC_STDCPP", file);
         }
         if builder.config.llvm_link_shared {
@@ -948,10 +953,11 @@ pub fn compiler_file(
     builder: &Builder<'_>,
     compiler: &Path,
     target: TargetSelection,
+    c: CLang,
     file: &str,
 ) -> PathBuf {
     let mut cmd = Command::new(compiler);
-    cmd.args(builder.cflags(target, GitRepo::Rustc));
+    cmd.args(builder.cflags(target, GitRepo::Rustc, c));
     cmd.arg(format!("-print-file-name={}", file));
     let out = output(&mut cmd);
     PathBuf::from(out.trim())
index d6f77fe6cd6d0c06e54ea744d7a7d746044a1dc9..73a855ae4d72aa38660d475725987524be3ac2e4 100644 (file)
@@ -6,7 +6,6 @@
 use std::cmp;
 use std::collections::{HashMap, HashSet};
 use std::env;
-use std::ffi::OsString;
 use std::fmt;
 use std::fs;
 use std::path::{Path, PathBuf};
@@ -17,8 +16,7 @@
 use crate::channel::GitInfo;
 pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags};
-use crate::util::exe;
-use build_helper::t;
+use crate::util::{exe, t};
 use serde::Deserialize;
 
 macro_rules! check_ci_llvm {
@@ -387,13 +385,12 @@ fn merge(&mut self, other: Self) {
 
 derive_merge! {
     /// TOML representation of various global build decisions.
-    #[derive(Deserialize, Default, Clone)]
+    #[derive(Deserialize, Default)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Build {
         build: Option<String>,
         host: Option<Vec<String>>,
         target: Option<Vec<String>>,
-        // This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable
         build_dir: Option<String>,
         cargo: Option<String>,
         rustc: Option<String>,
@@ -434,7 +431,7 @@ struct Build {
 
 derive_merge! {
     /// TOML representation of various global install decisions.
-    #[derive(Deserialize, Default, Clone)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Install {
         prefix: Option<String>,
@@ -449,7 +446,7 @@ struct Install {
 
 derive_merge! {
     /// TOML representation of how the LLVM build is configured.
-    #[derive(Deserialize, Default)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Llvm {
         skip_rebuild: Option<bool>,
@@ -483,7 +480,7 @@ struct Llvm {
 }
 
 derive_merge! {
-    #[derive(Deserialize, Default, Clone)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Dist {
         sign_folder: Option<String>,
@@ -510,7 +507,7 @@ fn default() -> StringOrBool {
 
 derive_merge! {
     /// TOML representation of how the Rust build is configured.
-    #[derive(Deserialize, Default)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct Rust {
         optimize: Option<bool>,
@@ -565,7 +562,7 @@ struct Rust {
 
 derive_merge! {
     /// TOML representation of how each build target is configured.
-    #[derive(Deserialize, Default)]
+    #[derive(Deserialize)]
     #[serde(deny_unknown_fields, rename_all = "kebab-case")]
     struct TomlTarget {
         cc: Option<String>,
@@ -589,18 +586,6 @@ struct TomlTarget {
 }
 
 impl Config {
-    fn path_from_python(var_key: &str) -> PathBuf {
-        match env::var_os(var_key) {
-            Some(var_val) => Self::normalize_python_path(var_val),
-            _ => panic!("expected '{}' to be set", var_key),
-        }
-    }
-
-    /// Normalizes paths from Python slightly. We don't trust paths from Python (#49785).
-    fn normalize_python_path(path: OsString) -> PathBuf {
-        Path::new(&path).components().collect()
-    }
-
     pub fn default_opts() -> Config {
         let mut config = Config::default();
         config.llvm_optimize = true;
@@ -626,7 +611,7 @@ pub fn default_opts() -> Config {
         let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
         // Undo `src/bootstrap`
         config.src = manifest_dir.parent().unwrap().parent().unwrap().to_owned();
-        config.out = Config::path_from_python("BUILD_DIR");
+        config.out = PathBuf::from("build");
 
         config.initial_cargo = PathBuf::from(env!("CARGO"));
         config.initial_rustc = PathBuf::from(env!("RUSTC"));
@@ -656,12 +641,6 @@ pub fn parse(args: &[String]) -> Config {
         config.llvm_profile_use = flags.llvm_profile_use;
         config.llvm_profile_generate = flags.llvm_profile_generate;
 
-        if config.dry_run {
-            let dir = config.out.join("tmp-dry-run");
-            t!(fs::create_dir_all(&dir));
-            config.out = dir;
-        }
-
         #[cfg(test)]
         let get_toml = |_| TomlConfig::default();
         #[cfg(not(test))]
@@ -678,7 +657,15 @@ pub fn parse(args: &[String]) -> Config {
             }
         };
 
-        let mut toml = flags.config.as_deref().map(get_toml).unwrap_or_else(TomlConfig::default);
+        // check --config first, then `$RUST_BOOTSTRAP_CONFIG` first, then `config.toml`
+        let toml_path = flags
+            .config
+            .clone()
+            .or_else(|| env::var_os("RUST_BOOTSTRAP_CONFIG").map(PathBuf::from))
+            .unwrap_or_else(|| PathBuf::from("config.toml"));
+        let mut toml =
+            if toml_path.exists() { get_toml(&toml_path) } else { TomlConfig::default() };
+
         if let Some(include) = &toml.profile {
             let mut include_path = config.src.clone();
             include_path.push("src");
@@ -690,12 +677,25 @@ pub fn parse(args: &[String]) -> Config {
         }
 
         config.changelog_seen = toml.changelog_seen;
-        if let Some(cfg) = flags.config {
-            config.config = cfg;
-        }
+        config.config = toml_path;
 
         let build = toml.build.unwrap_or_default();
 
+        set(&mut config.initial_rustc, build.rustc.map(PathBuf::from));
+        set(&mut config.out, build.build_dir.map(PathBuf::from));
+        // NOTE: Bootstrap spawns various commands with different working directories.
+        // To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
+        if !config.out.is_absolute() {
+            // `canonicalize` requires the path to already exist. Use our vendored copy of `absolute` instead.
+            config.out = crate::util::absolute(&config.out);
+        }
+
+        if config.dry_run {
+            let dir = config.out.join("tmp-dry-run");
+            t!(fs::create_dir_all(&dir));
+            config.out = dir;
+        }
+
         config.hosts = if let Some(arg_host) = flags.host {
             arg_host
         } else if let Some(file_host) = build.host {
@@ -1187,7 +1187,7 @@ fn set<T>(field: &mut T, val: Option<T>) {
 
 fn threads_from_config(v: u32) -> u32 {
     match v {
-        0 => num_cpus::get() as u32,
+        0 => std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32,
         n => n,
     }
 }
index 8693e85e4742f5e41ba3e50244a9475c84f3b46d..5f92cc2ca6faddd2c004fffe8b3b1262c7529ce8 100644 (file)
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use build_helper::{output, t};
-
 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::tool::{self, Tool};
-use crate::util::{exe, is_dylib, timeit};
+use crate::util::{exe, is_dylib, output, t, timeit};
 use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
 
 pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
@@ -635,14 +633,6 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
             &[],
             &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
         );
-        // This particular crate is used as a build dependency of the above.
-        copy_src_dirs(
-            builder,
-            &builder.src,
-            &["src/build_helper"],
-            &[],
-            &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
-        );
         for file in src_files {
             tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
         }
index 23b5ddcd47a0ecbc02ac7760e652684726b5b8cc..be55871b56a2801468606afae5fe615c50c52d1e 100644 (file)
 use std::io;
 use std::path::{Path, PathBuf};
 
-use crate::Mode;
-use build_helper::{t, up_to_date};
-
 use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
 use crate::compile;
 use crate::config::{Config, TargetSelection};
 use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
-use crate::util::symlink_dir;
+use crate::util::{symlink_dir, t, up_to_date};
+use crate::Mode;
 
 macro_rules! submodule_helper {
     ($path:expr, submodule) => {
index 9180c5f03af6810974234c15d830d8d9881fe148..1a4e6a9688803b544295aa7d1c7ba0d5d2d9c2d0 100644 (file)
@@ -3,16 +3,15 @@
 //! This module implements the command-line parsing of the build system which
 //! has various flags to configure how it's run.
 
-use std::env;
 use std::path::PathBuf;
 use std::process;
 
-use build_helper::t;
 use getopts::Options;
 
 use crate::builder::Builder;
 use crate::config::{Config, TargetSelection};
 use crate::setup::Profile;
+use crate::util::t;
 use crate::{Build, DocTests};
 
 pub enum Color {
@@ -208,7 +207,7 @@ pub fn parse(args: &[String]) -> Flags {
         let j_msg = format!(
             "number of jobs to run in parallel; \
              defaults to {} (this host's logical CPU count)",
-            num_cpus::get()
+            std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
         );
         opts.optopt("j", "jobs", &j_msg, "JOBS");
         opts.optflag("h", "help", "print this help message");
@@ -541,7 +540,6 @@ pub fn parse(args: &[String]) -> Flags {
         // Get any optional paths which occur after the subcommand
         let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
 
-        let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
         let verbose = matches.opt_present("verbose");
 
         // User passed in -h/--help?
@@ -671,7 +669,7 @@ pub fn parse(args: &[String]) -> Flags {
             } else {
                 None
             },
-            config: cfg_file,
+            config: matches.opt_str("config").map(PathBuf::from),
             jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")),
             cmd,
             incremental: matches.opt_present("incremental"),
index 30fe6a7a44695d834255483dc52bc1ec072f8202..10b846e6db2087e67181242b2346663c09b4548e 100644 (file)
@@ -1,7 +1,7 @@
 //! Runs rustfmt on the repository.
 
+use crate::util::{output, t};
 use crate::Build;
-use build_helper::{output, t};
 use ignore::WalkBuilder;
 use std::collections::VecDeque;
 use std::path::{Path, PathBuf};
@@ -97,7 +97,12 @@ pub fn format(build: &Build, check: bool, paths: &[PathBuf]) {
                 });
             for untracked_path in untracked_paths {
                 eprintln!("skip untracked path {} during rustfmt invocations", untracked_path);
-                ignore_fmt.add(&format!("!{}", untracked_path)).expect(&untracked_path);
+                // The leading `/` makes it an exact match against the
+                // repository root, rather than a glob. Without that, if you
+                // have `foo.rs` in the repository root it will also match
+                // against anything like `compiler/rustc_foo/src/foo.rs`,
+                // preventing the latter from being formatted.
+                ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path);
             }
         } else {
             eprintln!("Not in git tree. Skipping git-aware format checks");
index 06acf1a9a008367bc2f85cabb20db0090ad06619..27b9196d9868e10d23deb5cfb8682ef03f788397 100644 (file)
@@ -8,7 +8,7 @@
 use std::path::{Component, PathBuf};
 use std::process::Command;
 
-use build_helper::t;
+use crate::util::t;
 
 use crate::dist::{self, sanitize_sh};
 use crate::tarball::GeneratedTarball;
index 86339c8d7f88d2992458fcc197c0b2d8eb2aa35f..2ae63858ff610bfba465b9e79b4ed80b660d7d82 100644 (file)
 #[cfg(windows)]
 use std::os::windows::fs::symlink_file;
 
-use build_helper::{mtime, output, run, run_suppressed, t, try_run, try_run_suppressed};
 use filetime::FileTime;
 
 use crate::builder::Kind;
 use crate::config::{LlvmLibunwind, TargetSelection};
-use crate::util::{exe, libdir, CiEnv};
+use crate::util::{
+    exe, libdir, mtime, output, run, run_suppressed, t, try_run, try_run_suppressed, CiEnv,
+};
 
 mod builder;
 mod cache;
@@ -186,6 +187,34 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
 
 pub const VERSION: usize = 2;
 
+/// Extra --check-cfg to add when building
+/// (Mode restriction, config name, config values (if any))
+const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)] = &[
+    (None, "bootstrap", None),
+    (Some(Mode::Rustc), "parallel_compiler", None),
+    (Some(Mode::ToolRustc), "parallel_compiler", None),
+    (Some(Mode::Std), "miri", None),
+    (Some(Mode::Std), "stdarch_intel_sde", None),
+    (Some(Mode::Std), "no_fp_fmt_parse", None),
+    (Some(Mode::Std), "no_global_oom_handling", None),
+    (Some(Mode::Std), "freebsd12", None),
+    (Some(Mode::Std), "backtrace_in_libstd", None),
+    // FIXME: Used by rustfmt is their test but is invalid (neither cargo nor bootstrap ever set
+    // this config) should probably by removed or use a allow attribute.
+    (Some(Mode::ToolRustc), "release", None),
+    // FIXME: Used by stdarch in their test, should use a allow attribute instead.
+    (Some(Mode::Std), "dont_compile_me", None),
+    // FIXME: Used by serde_json, but we should not be triggering on external dependencies.
+    (Some(Mode::Rustc), "no_btreemap_remove_entry", None),
+    (Some(Mode::ToolRustc), "no_btreemap_remove_entry", None),
+    // FIXME: Used by crossbeam-utils, but we should not be triggering on external dependencies.
+    (Some(Mode::Rustc), "crossbeam_loom", None),
+    (Some(Mode::ToolRustc), "crossbeam_loom", None),
+    // FIXME: Used by proc-macro2, but we should not be triggering on external dependencies.
+    (Some(Mode::Rustc), "span_locations", None),
+    (Some(Mode::ToolRustc), "span_locations", None),
+];
+
 /// A structure representing a Rust compiler.
 ///
 /// Each compiler has a `stage` that it is associated with and a `host` that
@@ -232,6 +261,7 @@ pub struct Build {
     // Properties derived from the above configuration
     src: PathBuf,
     out: PathBuf,
+    bootstrap_out: PathBuf,
     rust_info: channel::GitInfo,
     cargo_info: channel::GitInfo,
     rls_info: channel::GitInfo,
@@ -339,6 +369,11 @@ pub fn must_support_dlopen(&self) -> bool {
     }
 }
 
+pub enum CLang {
+    C,
+    Cxx,
+}
+
 impl Build {
     /// Creates a new set of build configuration from the `flags` on the command
     /// line and the filesystem `config`.
@@ -401,6 +436,20 @@ pub fn new(config: Config) -> Build {
             .expect("failed to read src/version");
         let version = version.trim();
 
+        let bootstrap_out = if std::env::var("BOOTSTRAP_PYTHON").is_ok() {
+            out.join("bootstrap").join("debug")
+        } else {
+            let workspace_target_dir = std::env::var("CARGO_TARGET_DIR")
+                .map(PathBuf::from)
+                .unwrap_or_else(|_| src.join("target"));
+            let bootstrap_out = workspace_target_dir.join("debug");
+            if !bootstrap_out.join("rustc").exists() {
+                // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented
+                panic!("run `cargo build --bins` before `cargo run`")
+            }
+            bootstrap_out
+        };
+
         let mut build = Build {
             initial_rustc: config.initial_rustc.clone(),
             initial_cargo: config.initial_cargo.clone(),
@@ -419,6 +468,7 @@ pub fn new(config: Config) -> Build {
             version: version.to_string(),
             src,
             out,
+            bootstrap_out,
 
             rust_info,
             cargo_info,
@@ -595,7 +645,7 @@ pub fn build(&mut self) {
         }
 
         if let Subcommand::Setup { profile } = &self.config.cmd {
-            return setup::setup(&self.config.src, *profile);
+            return setup::setup(&self.config, *profile);
         }
 
         {
@@ -917,7 +967,9 @@ fn info(&self, msg: &str) {
     /// Returns the number of parallel jobs that have been configured for this
     /// build.
     fn jobs(&self) -> u32 {
-        self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32)
+        self.config.jobs.unwrap_or_else(|| {
+            std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
+        })
     }
 
     fn debuginfo_map_to(&self, which: GitRepo) -> Option<String> {
@@ -941,10 +993,15 @@ fn cc(&self, target: TargetSelection) -> &Path {
 
     /// Returns a list of flags to pass to the C compiler for the target
     /// specified.
-    fn cflags(&self, target: TargetSelection, which: GitRepo) -> Vec<String> {
+    fn cflags(&self, target: TargetSelection, which: GitRepo, c: CLang) -> Vec<String> {
+        let base = match c {
+            CLang::C => &self.cc[&target],
+            CLang::Cxx => &self.cxx[&target],
+        };
+
         // Filter out -O and /O (the optimization flags) that we picked up from
         // cc-rs because the build scripts will determine that for themselves.
-        let mut base = self.cc[&target]
+        let mut base = base
             .args()
             .iter()
             .map(|s| s.to_string_lossy().into_owned())
@@ -1261,13 +1318,10 @@ fn in_tree_crates(&self, root: &str, target: Option<TargetSelection>) -> Vec<&Cr
                 }
                 // Don't include optional deps if their features are not
                 // enabled. Ideally this would be computed from `cargo
-                // metadata --features â€¦`, but that is somewhat slow. Just
-                // skip `build_helper` since there aren't any operations we
-                // want to perform on it. In the future, we may want to
-                // consider just filtering all build and dev dependencies in
-                // metadata::build.
+                // metadata --features â€¦`, but that is somewhat slow. In
+                // the future, we may want to consider just filtering all
+                // build and dev dependencies in metadata::build.
                 if visited.insert(dep)
-                    && dep != "build_helper"
                     && (dep != "profiler_builtins"
                         || target
                             .map(|t| self.config.profiler_enabled(t))
index 65e229697dc87aba4e5627c09f4d6352b344a5df..59dc50be47f0685e6b89fcf7cc70e514f67ac1d1 100644 (file)
@@ -1,10 +1,10 @@
 use std::path::PathBuf;
 use std::process::Command;
 
-use build_helper::output;
 use serde::Deserialize;
 
 use crate::cache::INTERNER;
+use crate::util::output;
 use crate::{Build, Crate};
 
 #[derive(Deserialize)]
index f00875239040db8b67d298b0019bcf4939952c11..f00c5ce5aa6f03fff9885a022260c1d4df076014 100644 (file)
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use build_helper::{output, t};
-
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::config::TargetSelection;
-use crate::util::{self, exe};
-use crate::GitRepo;
-use build_helper::up_to_date;
+use crate::util::{self, exe, output, t, up_to_date};
+use crate::{CLang, GitRepo};
 
 pub struct Meta {
     stamp: HashStamp,
@@ -529,7 +526,7 @@ fn configure_cmake(
     }
 
     cfg.build_arg("-j").build_arg(builder.jobs().to_string());
-    let mut cflags: OsString = builder.cflags(target, GitRepo::Llvm).join(" ").into();
+    let mut cflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::C).join(" ").into();
     if let Some(ref s) = builder.config.llvm_cflags {
         cflags.push(" ");
         cflags.push(s);
@@ -545,12 +542,8 @@ fn configure_cmake(
     if builder.config.llvm_clang_cl.is_some() {
         cflags.push(&format!(" --target={}", target));
     }
-    if let Some(flags) = env::var_os("CFLAGS") {
-        cflags.push(" ");
-        cflags.push(flags);
-    }
     cfg.define("CMAKE_C_FLAGS", cflags);
-    let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm).join(" ").into();
+    let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::Cxx).join(" ").into();
     if let Some(ref s) = builder.config.llvm_cxxflags {
         cxxflags.push(" ");
         cxxflags.push(s);
@@ -558,10 +551,6 @@ fn configure_cmake(
     if builder.config.llvm_clang_cl.is_some() {
         cxxflags.push(&format!(" --target={}", target));
     }
-    if let Some(flags) = env::var_os("CXXFLAGS") {
-        cxxflags.push(" ");
-        cxxflags.push(flags);
-    }
     cfg.define("CMAKE_CXX_FLAGS", cxxflags);
     if let Some(ar) = builder.ar(target) {
         if ar.is_absolute() {
@@ -583,7 +572,7 @@ fn configure_cmake(
         ldflags.push_all(flags);
     }
 
-    if let Some(flags) = env::var_os("LDFLAGS") {
+    if let Some(flags) = get_var("LDFLAGS", &builder.config.build.triple, &target.triple) {
         ldflags.push_all(&flags);
     }
 
@@ -596,6 +585,16 @@ fn configure_cmake(
     }
 }
 
+// Adapted from https://github.com/alexcrichton/cc-rs/blob/fba7feded71ee4f63cfe885673ead6d7b4f2f454/src/lib.rs#L2347-L2365
+fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
+    let kind = if host == target { "HOST" } else { "TARGET" };
+    let target_u = target.replace("-", "_");
+    env::var_os(&format!("{}_{}", var_base, target))
+        .or_else(|| env::var_os(&format!("{}_{}", var_base, target_u)))
+        .or_else(|| env::var_os(&format!("{}_{}", kind, var_base)))
+        .or_else(|| env::var_os(var_base))
+}
+
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Lld {
     pub target: TargetSelection,
@@ -651,8 +650,16 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         // there's probably a lot of reasons you can't do that other than this.
         let llvm_config_shim = env::current_exe().unwrap().with_file_name("llvm-config-wrapper");
 
+        // Re-use the same flags as llvm to control the level of debug information
+        // generated for lld.
+        let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
+            (false, _) => "Debug",
+            (true, false) => "Release",
+            (true, true) => "RelWithDebInfo",
+        };
+
         cfg.out_dir(&out_dir)
-            .profile("Release")
+            .profile(profile)
             .env("LLVM_CONFIG_REAL", &llvm_config)
             .define("LLVM_CONFIG_PATH", llvm_config_shim)
             .define("LLVM_INCLUDE_TESTS", "OFF");
index 11b393857e74c281b3dd4fb14f2366d8b3103d2d..25abe7a72fdc8d5b6512106406771b66bce3dd20 100644 (file)
@@ -1,7 +1,7 @@
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::dist::distdir;
 use crate::tool::Tool;
-use build_helper::output;
+use crate::util::output;
 use std::process::Command;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
index d7db2cef24f2be27323779d047afcd1a99e9617c..8c2899c1ac01e251d5178af6c401a8d3c985940b 100644 (file)
 use std::path::PathBuf;
 use std::process::Command;
 
-use build_helper::output;
-
 use crate::cache::INTERNER;
 use crate::config::Target;
+use crate::util::output;
 use crate::Build;
 
 pub struct Finder {
index 9a9ef0b76955d503127bc64bd7b6be057b575be7..e1235829b3aeff524b6997bf24ebd5f66312b050 100644 (file)
@@ -1,5 +1,5 @@
-use crate::TargetSelection;
 use crate::{t, VERSION};
+use crate::{Config, TargetSelection};
 use std::env::consts::EXE_SUFFIX;
 use std::fmt::Write as _;
 use std::fs::File;
@@ -81,24 +81,22 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-pub fn setup(src_path: &Path, profile: Profile) {
-    let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
+pub fn setup(config: &Config, profile: Profile) {
+    let path = &config.config;
 
-    if cfg_file.as_ref().map_or(false, |f| f.exists()) {
-        let file = cfg_file.unwrap();
+    if path.exists() {
         println!(
             "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
-            file.display()
+            path.display()
         );
-        println!("help: try adding `profile = \"{}\"` at the top of {}", profile, file.display());
+        println!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
         println!(
             "note: this will use the configuration in {}",
-            profile.include_path(src_path).display()
+            profile.include_path(&config.src).display()
         );
         std::process::exit(1);
     }
 
-    let path = cfg_file.unwrap_or_else(|| "config.toml".into());
     let settings = format!(
         "# Includes one of the default files in src/bootstrap/defaults\n\
     profile = \"{}\"\n\
@@ -107,7 +105,7 @@ pub fn setup(src_path: &Path, profile: Profile) {
     );
     t!(fs::write(path, settings));
 
-    let include_path = profile.include_path(src_path);
+    let include_path = profile.include_path(&config.src);
     println!("`x.py` will now use the configuration at {}", include_path.display());
 
     let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
@@ -138,7 +136,7 @@ pub fn setup(src_path: &Path, profile: Profile) {
 
     println!();
 
-    t!(install_git_hook_maybe(src_path));
+    t!(install_git_hook_maybe(&config.src));
 
     println!();
 
index 9ff5c2327e0f77a66ac9e72a6ed61b123776ac75..c743c5188e7545f47d7f858b74005107e731c01e 100644 (file)
@@ -3,9 +3,8 @@
     process::Command,
 };
 
-use build_helper::t;
-
 use crate::builder::Builder;
+use crate::util::t;
 
 #[derive(Copy, Clone)]
 pub(crate) enum OverlayKind {
index 176c06114e01df5de5a0401cec8c631604fc3d6b..58b73ebed5000118365eb8cbab5ce2ae3ff8f425 100644 (file)
@@ -11,8 +11,6 @@
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 
-use build_helper::{self, output, t};
-
 use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::Interned;
 use crate::compile;
@@ -22,9 +20,9 @@
 use crate::native;
 use crate::tool::{self, SourceType, Tool};
 use crate::toolstate::ToolState;
-use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var};
+use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t};
 use crate::Crate as CargoCrate;
-use crate::{envify, DocTests, GitRepo, Mode};
+use crate::{envify, CLang, DocTests, GitRepo, Mode};
 
 const ADB_TEST_DIR: &str = "/data/tmp/work";
 
@@ -732,7 +730,7 @@ fn make_run(run: RunConfig<'_>) {
     }
 
     fn run(self, builder: &Builder<'_>) {
-        let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
+        let rustdoc = builder.bootstrap_out.join("rustdoc");
         let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
         cmd.arg(rustdoc.to_str().unwrap())
             .arg(builder.src.join("src/librustdoc/html/static/css/themes").to_str().unwrap())
@@ -1509,7 +1507,9 @@ fn run(self, builder: &Builder<'_>) {
                 .arg("--cxx")
                 .arg(builder.cxx(target).unwrap())
                 .arg("--cflags")
-                .arg(builder.cflags(target, GitRepo::Rustc).join(" "));
+                .arg(builder.cflags(target, GitRepo::Rustc, CLang::C).join(" "))
+                .arg("--cxxflags")
+                .arg(builder.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "));
             copts_passed = true;
             if let Some(ar) = builder.ar(target) {
                 cmd.arg("--ar").arg(ar);
@@ -1520,7 +1520,14 @@ fn run(self, builder: &Builder<'_>) {
             cmd.arg("--llvm-components").arg("");
         }
         if !copts_passed {
-            cmd.arg("--cc").arg("").arg("--cxx").arg("").arg("--cflags").arg("");
+            cmd.arg("--cc")
+                .arg("")
+                .arg("--cxx")
+                .arg("")
+                .arg("--cflags")
+                .arg("")
+                .arg("--cxxflags")
+                .arg("");
         }
 
         if builder.remote_tested(target) {
@@ -2297,9 +2304,7 @@ fn run(self, builder: &Builder<'_>) {
                 .current_dir(&dir),
         );
         builder.run(
-            Command::new(build_helper::make(&builder.config.build.triple))
-                .arg("check")
-                .current_dir(&dir),
+            Command::new(util::make(&builder.config.build.triple)).arg("check").current_dir(&dir),
         );
 
         // Now make sure that rust-src has all of libstd's dependencies
@@ -2341,6 +2346,8 @@ fn run(self, builder: &Builder<'_>) {
             .current_dir(builder.src.join("src/bootstrap"))
             .env("RUSTFLAGS", "-Cdebuginfo=2")
             .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
+            // HACK: bootstrap's tests want to know the output directory, but there's no way to set
+            // it except through config.toml. Set it through an env variable instead.
             .env("BOOTSTRAP_OUTPUT_DIRECTORY", &builder.config.out)
             .env("BOOTSTRAP_INITIAL_CARGO", &builder.config.initial_cargo)
             .env("RUSTC_BOOTSTRAP", "1")
index 1317c3f9839757432106992f801522b25519fe3c..2ae4d830721e8ad2f22ab900cc998d62d7297fa4 100644 (file)
@@ -4,14 +4,12 @@
 use std::path::{Path, PathBuf};
 use std::process::{exit, Command};
 
-use build_helper::t;
-
 use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
 use crate::channel::GitInfo;
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::toolstate::ToolState;
-use crate::util::{add_dylib_path, exe};
+use crate::util::{add_dylib_path, exe, t};
 use crate::Compiler;
 use crate::Mode;
 
index 2394c5e020d2be3d85e2c103e2cd40d86283e5b2..c7ea254c5b1d7ac6a242493b56ebcc5bb4c5fad1 100644 (file)
@@ -1,5 +1,5 @@
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
-use build_helper::t;
+use crate::util::t;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 use std::env;
@@ -24,7 +24,7 @@
 
 type ToolstateData = HashMap<Box<str>, ToolState>;
 
-#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
+#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd)]
 #[serde(rename_all = "kebab-case")]
 /// Whether a tool can be compiled, tested or neither
 pub enum ToolState {
@@ -50,13 +50,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl Default for ToolState {
-    fn default() -> Self {
-        // err on the safe side
-        ToolState::BuildFail
-    }
-}
-
 /// Number of days after the last promotion of beta.
 /// Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens.
 /// The Wednesday after this has value 0.
@@ -466,13 +459,11 @@ fn publish_test_results(current_toolstate: &ToolstateData) {
     t!(fs::write(&history_path, file));
 }
 
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Deserialize)]
 struct RepoState {
     tool: String,
     windows: ToolState,
     linux: ToolState,
-    commit: String,
-    datetime: String,
 }
 
 impl RepoState {
index 2c78ceb1e5bec5b21386ecc70ee8d2d96310634a..30d9665dd0f4ad98f2974c4796bf877b33db18fd 100644 (file)
@@ -7,15 +7,38 @@
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::process::{Command, Stdio};
 use std::str;
-use std::time::Instant;
-
-use build_helper::t;
+use std::time::{Instant, SystemTime, UNIX_EPOCH};
 
 use crate::builder::Builder;
 use crate::config::{Config, TargetSelection};
 
+/// A helper macro to `unwrap` a result except also print out details like:
+///
+/// * The file/line of the panic
+/// * The expression that failed
+/// * The error itself
+///
+/// This is currently used judiciously throughout the build system rather than
+/// using a `Result` with `try!`, but this may change one day...
+macro_rules! t {
+    ($e:expr) => {
+        match $e {
+            Ok(e) => e,
+            Err(e) => panic!("{} failed with {}", stringify!($e), e),
+        }
+    };
+    // it can show extra info in the second parameter
+    ($e:expr, $extra:expr) => {
+        match $e {
+            Ok(e) => e,
+            Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra),
+        }
+    };
+}
+pub(crate) use t;
+
 /// Given an executable called `name`, return the filename for the
 /// executable for a particular target.
 pub fn exe(name: &str, target: TargetSelection) -> String {
@@ -301,3 +324,228 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
         _ => None,
     }
 }
+
+pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
+    if !try_run(cmd, print_cmd_on_fail) {
+        std::process::exit(1);
+    }
+}
+
+pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+    let status = match cmd.status() {
+        Ok(status) => status,
+        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
+    };
+    if !status.success() && print_cmd_on_fail {
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n",
+            cmd, status
+        );
+    }
+    status.success()
+}
+
+pub fn run_suppressed(cmd: &mut Command) {
+    if !try_run_suppressed(cmd) {
+        std::process::exit(1);
+    }
+}
+
+pub fn try_run_suppressed(cmd: &mut Command) -> bool {
+    let output = match cmd.output() {
+        Ok(status) => status,
+        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
+    };
+    if !output.status.success() {
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n\
+             stdout ----\n{}\n\
+             stderr ----\n{}\n\n",
+            cmd,
+            output.status,
+            String::from_utf8_lossy(&output.stdout),
+            String::from_utf8_lossy(&output.stderr)
+        );
+    }
+    output.status.success()
+}
+
+pub fn make(host: &str) -> PathBuf {
+    if host.contains("dragonfly")
+        || host.contains("freebsd")
+        || host.contains("netbsd")
+        || host.contains("openbsd")
+    {
+        PathBuf::from("gmake")
+    } else {
+        PathBuf::from("make")
+    }
+}
+
+#[track_caller]
+pub fn output(cmd: &mut Command) -> String {
+    let output = match cmd.stderr(Stdio::inherit()).output() {
+        Ok(status) => status,
+        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
+    };
+    if !output.status.success() {
+        panic!(
+            "command did not execute successfully: {:?}\n\
+             expected success, got: {}",
+            cmd, output.status
+        );
+    }
+    String::from_utf8(output.stdout).unwrap()
+}
+
+/// Returns the last-modified time for `path`, or zero if it doesn't exist.
+pub fn mtime(path: &Path) -> SystemTime {
+    fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
+}
+
+/// Returns `true` if `dst` is up to date given that the file or files in `src`
+/// are used to generate it.
+///
+/// Uses last-modified time checks to verify this.
+pub fn up_to_date(src: &Path, dst: &Path) -> bool {
+    if !dst.exists() {
+        return false;
+    }
+    let threshold = mtime(dst);
+    let meta = match fs::metadata(src) {
+        Ok(meta) => meta,
+        Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
+    };
+    if meta.is_dir() {
+        dir_up_to_date(src, threshold)
+    } else {
+        meta.modified().unwrap_or(UNIX_EPOCH) <= threshold
+    }
+}
+
+fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
+    t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
+        let meta = t!(e.metadata());
+        if meta.is_dir() {
+            dir_up_to_date(&e.path(), threshold)
+        } else {
+            meta.modified().unwrap_or(UNIX_EPOCH) < threshold
+        }
+    })
+}
+
+fn fail(s: &str) -> ! {
+    println!("\n\n{}\n\n", s);
+    std::process::exit(1);
+}
+
+/// Copied from `std::path::absolute` until it stabilizes.
+///
+/// FIXME: this shouldn't exist.
+pub(crate) fn absolute(path: &Path) -> PathBuf {
+    if path.as_os_str().is_empty() {
+        panic!("can't make empty path absolute");
+    }
+    #[cfg(unix)]
+    {
+        t!(absolute_unix(path), format!("could not make path absolute: {}", path.display()))
+    }
+    #[cfg(windows)]
+    {
+        t!(absolute_windows(path), format!("could not make path absolute: {}", path.display()))
+    }
+    #[cfg(not(any(unix, windows)))]
+    {
+        println!("warning: bootstrap is not supported on non-unix platforms");
+        t!(std::fs::canonicalize(t!(std::env::current_dir()))).join(path)
+    }
+}
+
+#[cfg(unix)]
+/// Make a POSIX path absolute without changing its semantics.
+fn absolute_unix(path: &Path) -> io::Result<PathBuf> {
+    // This is mostly a wrapper around collecting `Path::components`, with
+    // exceptions made where this conflicts with the POSIX specification.
+    // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017
+    // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
+
+    use std::os::unix::prelude::OsStrExt;
+    let mut components = path.components();
+    let path_os = path.as_os_str().as_bytes();
+
+    let mut normalized = if path.is_absolute() {
+        // "If a pathname begins with two successive <slash> characters, the
+        // first component following the leading <slash> characters may be
+        // interpreted in an implementation-defined manner, although more than
+        // two leading <slash> characters shall be treated as a single <slash>
+        // character."
+        if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
+            components.next();
+            PathBuf::from("//")
+        } else {
+            PathBuf::new()
+        }
+    } else {
+        env::current_dir()?
+    };
+    normalized.extend(components);
+
+    // "Interfaces using pathname resolution may specify additional constraints
+    // when a pathname that does not name an existing directory contains at
+    // least one non- <slash> character and contains one or more trailing
+    // <slash> characters".
+    // A trailing <slash> is also meaningful if "a symbolic link is
+    // encountered during pathname resolution".
+
+    if path_os.ends_with(b"/") {
+        normalized.push("");
+    }
+
+    Ok(normalized)
+}
+
+#[cfg(windows)]
+fn absolute_windows(path: &std::path::Path) -> std::io::Result<std::path::PathBuf> {
+    use std::ffi::OsString;
+    use std::io::Error;
+    use std::os::windows::ffi::{OsStrExt, OsStringExt};
+    use std::ptr::null_mut;
+    #[link(name = "kernel32")]
+    extern "system" {
+        fn GetFullPathNameW(
+            lpFileName: *const u16,
+            nBufferLength: u32,
+            lpBuffer: *mut u16,
+            lpFilePart: *mut *const u16,
+        ) -> u32;
+    }
+
+    unsafe {
+        // encode the path as UTF-16
+        let path: Vec<u16> = path.as_os_str().encode_wide().chain([0]).collect();
+        let mut buffer = Vec::new();
+        // Loop until either success or failure.
+        loop {
+            // Try to get the absolute path
+            let len = GetFullPathNameW(
+                path.as_ptr(),
+                buffer.len().try_into().unwrap(),
+                buffer.as_mut_ptr(),
+                null_mut(),
+            );
+            match len as usize {
+                // Failure
+                0 => return Err(Error::last_os_error()),
+                // Buffer is too small, resize.
+                len if len > buffer.len() => buffer.resize(len, 0),
+                // Success!
+                len => {
+                    buffer.truncate(len);
+                    return Ok(OsString::from_wide(&buffer).into());
+                }
+            }
+        }
+    }
+}
diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml
deleted file mode 100644 (file)
index d88df0e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-[package]
-name = "build_helper"
-version = "0.1.0"
-edition = "2021"
-
-[lib]
-path = "lib.rs"
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
deleted file mode 100644 (file)
index 24aded5..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-use std::ffi::{OsStr, OsString};
-use std::fmt::Display;
-use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
-use std::time::{SystemTime, UNIX_EPOCH};
-use std::{env, fs};
-
-/// A helper macro to `unwrap` a result except also print out details like:
-///
-/// * The file/line of the panic
-/// * The expression that failed
-/// * The error itself
-///
-/// This is currently used judiciously throughout the build system rather than
-/// using a `Result` with `try!`, but this may change one day...
-#[macro_export]
-macro_rules! t {
-    ($e:expr) => {
-        match $e {
-            Ok(e) => e,
-            Err(e) => panic!("{} failed with {}", stringify!($e), e),
-        }
-    };
-    // it can show extra info in the second parameter
-    ($e:expr, $extra:expr) => {
-        match $e {
-            Ok(e) => e,
-            Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra),
-        }
-    };
-}
-
-/// Reads an environment variable and adds it to dependencies.
-/// Supposed to be used for all variables except those set for build scripts by cargo
-/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
-pub fn tracked_env_var_os<K: AsRef<OsStr> + Display>(key: K) -> Option<OsString> {
-    println!("cargo:rerun-if-env-changed={}", key);
-    env::var_os(key)
-}
-
-// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
-// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
-// shared library, which means that when our freshly built llvm-config goes to load it's
-// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
-// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
-// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
-// perfect -- we might actually want to see something from Cargo's added library paths -- but
-// for now it works.
-pub fn restore_library_path() {
-    let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
-    if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") {
-        env::set_var(&key, &env);
-    } else {
-        env::remove_var(&key);
-    }
-}
-
-pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
-    if !try_run(cmd, print_cmd_on_fail) {
-        std::process::exit(1);
-    }
-}
-
-pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
-    let status = match cmd.status() {
-        Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
-    };
-    if !status.success() && print_cmd_on_fail {
-        println!(
-            "\n\ncommand did not execute successfully: {:?}\n\
-             expected success, got: {}\n\n",
-            cmd, status
-        );
-    }
-    status.success()
-}
-
-pub fn run_suppressed(cmd: &mut Command) {
-    if !try_run_suppressed(cmd) {
-        std::process::exit(1);
-    }
-}
-
-pub fn try_run_suppressed(cmd: &mut Command) -> bool {
-    let output = match cmd.output() {
-        Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
-    };
-    if !output.status.success() {
-        println!(
-            "\n\ncommand did not execute successfully: {:?}\n\
-             expected success, got: {}\n\n\
-             stdout ----\n{}\n\
-             stderr ----\n{}\n\n",
-            cmd,
-            output.status,
-            String::from_utf8_lossy(&output.stdout),
-            String::from_utf8_lossy(&output.stderr)
-        );
-    }
-    output.status.success()
-}
-
-pub fn make(host: &str) -> PathBuf {
-    if host.contains("dragonfly")
-        || host.contains("freebsd")
-        || host.contains("netbsd")
-        || host.contains("openbsd")
-    {
-        PathBuf::from("gmake")
-    } else {
-        PathBuf::from("make")
-    }
-}
-
-#[track_caller]
-pub fn output(cmd: &mut Command) -> String {
-    let output = match cmd.stderr(Stdio::inherit()).output() {
-        Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
-    };
-    if !output.status.success() {
-        panic!(
-            "command did not execute successfully: {:?}\n\
-             expected success, got: {}",
-            cmd, output.status
-        );
-    }
-    String::from_utf8(output.stdout).unwrap()
-}
-
-pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
-    let mut stack = dir
-        .read_dir()
-        .unwrap()
-        .map(|e| e.unwrap())
-        .filter(|e| &*e.file_name() != ".git")
-        .collect::<Vec<_>>();
-    while let Some(entry) = stack.pop() {
-        let path = entry.path();
-        if entry.file_type().unwrap().is_dir() {
-            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
-        } else {
-            println!("cargo:rerun-if-changed={}", path.display());
-        }
-    }
-}
-
-/// Returns the last-modified time for `path`, or zero if it doesn't exist.
-pub fn mtime(path: &Path) -> SystemTime {
-    fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
-}
-
-/// Returns `true` if `dst` is up to date given that the file or files in `src`
-/// are used to generate it.
-///
-/// Uses last-modified time checks to verify this.
-pub fn up_to_date(src: &Path, dst: &Path) -> bool {
-    if !dst.exists() {
-        return false;
-    }
-    let threshold = mtime(dst);
-    let meta = match fs::metadata(src) {
-        Ok(meta) => meta,
-        Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
-    };
-    if meta.is_dir() {
-        dir_up_to_date(src, threshold)
-    } else {
-        meta.modified().unwrap_or(UNIX_EPOCH) <= threshold
-    }
-}
-
-fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
-    t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
-        let meta = t!(e.metadata());
-        if meta.is_dir() {
-            dir_up_to_date(&e.path(), threshold)
-        } else {
-            meta.modified().unwrap_or(UNIX_EPOCH) < threshold
-        }
-    })
-}
-
-fn fail(s: &str) -> ! {
-    println!("\n\n{}\n\n", s);
-    std::process::exit(1);
-}
index 8f881657bdc1a1965140ab4941436a06bee2f3ba..9c330685209beb2faa0a31a517ddabe901c3ca78 100644 (file)
@@ -1 +1 @@
-<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">
+<link rel="icon" href="https://www.rust-lang.org/favicon.ico">
index 33e3860c2a4340ba428e789a980bafeeb7982b02..2fb44be014515b28bbaf8b8b38af7c299902b1aa 100644 (file)
@@ -1,2 +1,2 @@
 <meta name="robots" content="noindex,follow">
-<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">
+<link rel="icon" href="https://www.rust-lang.org/favicon.ico">
index 4c05818440b09a504699cd36a35d1230e157e52e..7a00b048a9b18c2b52fdfe0f2ec36f56aa58ee4c 100644 (file)
@@ -73,7 +73,8 @@ Tier Policy.
 
 All tier 2 targets with host tools support the full standard library.
 
-**NOTE:** Tier 2 targets currently do not build the `rust-docs` component.
+**NOTE:** The `rust-docs` component is not usually built for tier 2 targets,
+so Rustup may install the documentation for a similar tier 1 target instead.
 
 target | notes
 -------|-------
@@ -114,7 +115,8 @@ The `std` column in the table below has the following meanings:
 
 [`no_std`]: https://rust-embedded.github.io/book/intro/no-std.html
 
-**NOTE:** Tier 2 targets currently do not build the `rust-docs` component.
+**NOTE:** The `rust-docs` component is not usually built for tier 2 targets,
+so Rustup may install the documentation for a similar tier 1 target instead.
 
 target | std | notes
 -------|:---:|-------
index a75b6d3893128a6205907b856b614968718c6616..c5cc84022e389db657b14b5cfea0e0ad63796a59 100644 (file)
@@ -59,7 +59,7 @@ This form of the `doc` attribute lets you control the favicon of your docs.
 #![doc(html_favicon_url = "https://example.com/favicon.ico")]
 ```
 
-This will put `<link rel="shortcut icon" href="{}">` into your docs, where
+This will put `<link rel="icon" href="{}">` into your docs, where
 the string for the attribute goes into the `{}`.
 
 If you don't use this attribute, there will be no favicon.
index 9e7968d906fbf5ff62a3824b764c43a690bd1644..001c1bfa9ec03080e0686e1e013d54269a3643a4 100644 (file)
@@ -7,7 +7,7 @@ The tracking issue for this feature is: [#44930]
 ------------------------
 
 The `c_variadic` language feature enables C-variadic functions to be
-defined in Rust. The may be called both from within Rust and via FFI.
+defined in Rust. They may be called both from within Rust and via FFI.
 
 ## Examples
 
index 4371a914b48041c932114de3d477d758ec8ddd9b..cc5c583bea8e25d81dda1b114b6e96a04dffeedf 100644 (file)
@@ -11,13 +11,13 @@ arrayvec = { version = "0.7", default-features = false }
 askama = { version = "0.11", default-features = false, features = ["config"] }
 atty = "0.2"
 pulldown-cmark = { version = "0.9", default-features = false }
-minifier = "0.0.42"
+minifier = "0.0.43"
 rayon = "1.5.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 smallvec = "1.6.1"
 tempfile = "3"
-itertools = "0.10"
+itertools = "0.10.1"
 regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
 tracing = "0.1"
index a3154d8f03bf82ee752993d13839e2ff8ebaf20d..62f3527525e0e49bf2bbf32841683d6e2bb2028a 100644 (file)
@@ -546,11 +546,11 @@ fn param_env_to_generics(
                 }
                 WherePredicate::EqPredicate { lhs, rhs } => {
                     match lhs {
-                        Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
+                        Type::QPath { ref assoc, ref self_type, ref trait_, .. } => {
                             let ty = &*self_type;
                             let mut new_trait = trait_.clone();
 
-                            if self.is_fn_trait(trait_) && left_name == sym::Output {
+                            if self.is_fn_trait(trait_) && assoc.name == sym::Output {
                                 ty_to_fn
                                     .entry(*ty.clone())
                                     .and_modify(|e| {
@@ -571,7 +571,7 @@ fn param_env_to_generics(
                                 // to 'T: Iterator<Item=u8>'
                                 GenericArgs::AngleBracketed { ref mut bindings, .. } => {
                                     bindings.push(TypeBinding {
-                                        name: left_name,
+                                        assoc: *assoc.clone(),
                                         kind: TypeBindingKind::Equality { term: rhs },
                                     });
                                 }
index 3ae1df51695b7f1d28b0163e9289b81d83ee3402..2e66db425d611298ac38ef5291e4d6d3fd5ddb9f 100644 (file)
@@ -636,7 +636,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
 
     g.where_predicates.retain(|pred| match pred {
         clean::WherePredicate::BoundPredicate {
-            ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. },
+            ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, .. },
             bounds,
             ..
         } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
index 8fad625973fb814f7bf5fe14fc8b38c4a623f4e2..29c11c7b28a5f43431c15b54f8a3b0906a5f4698 100644 (file)
@@ -388,7 +388,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         let trait_ = lifted.trait_ref(cx.tcx).clean(cx);
         let self_type = self.self_ty().clean(cx);
         Type::QPath {
-            name: cx.tcx.associated_item(self.item_def_id).name,
+            assoc: Box::new(projection_to_path_segment(*self, cx)),
             self_def_id: self_type.def_id(&cx.cache),
             self_type: box self_type,
             trait_,
@@ -396,6 +396,18 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
     }
 }
 
+fn projection_to_path_segment(ty: ty::ProjectionTy<'_>, cx: &mut DocContext<'_>) -> PathSegment {
+    let item = cx.tcx.associated_item(ty.item_def_id);
+    let generics = cx.tcx.generics_of(ty.item_def_id);
+    PathSegment {
+        name: item.name,
+        args: GenericArgs::AngleBracketed {
+            args: substs_to_args(cx, &ty.substs[generics.parent_count..], false),
+            bindings: Default::default(),
+        },
+    }
+}
+
 impl Clean<GenericParamDef> for ty::GenericParamDef {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
         let (name, kind) = match self.kind {
@@ -430,7 +442,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
                     },
                 )
             }
-            ty::GenericParamDefKind::Const { has_default, .. } => (
+            ty::GenericParamDefKind::Const { has_default } => (
                 self.name,
                 GenericParamDefKind::Const {
                     did: self.def_id,
@@ -601,8 +613,8 @@ fn clean_ty_generics(
         })
         .collect::<Vec<GenericParamDef>>();
 
-    // param index -> [(DefId of trait, associated type name, type)]
-    let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, Symbol, Ty<'_>)>>::default();
+    // param index -> [(DefId of trait, associated type name and generics, type)]
+    let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>)>>::default();
 
     let where_predicates = preds
         .predicates
@@ -648,8 +660,9 @@ fn clean_ty_generics(
 
                     let proj = projection
                         .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term));
-                    if let Some(((_, trait_did, name), rhs)) =
-                        proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
+                    if let Some(((_, trait_did, name), rhs)) = proj
+                        .as_ref()
+                        .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
                     {
                         // FIXME(...): Remove this unwrap()
                         impl_trait_proj.entry(param_idx).or_default().push((
@@ -992,9 +1005,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                     TyMethodItem(t)
                 }
                 hir::TraitItemKind::Type(bounds, ref default) => {
+                    let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
                     let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
                     let default = default.map(|t| t.clean(cx));
-                    AssocTypeItem(bounds, default)
+                    AssocTypeItem(Box::new(generics), bounds, default)
                 }
             };
             let what_rustc_thinks =
@@ -1026,15 +1040,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                 }
                 hir::ImplItemKind::TyAlias(ref hir_ty) => {
                     let type_ = hir_ty.clean(cx);
+                    let generics = self.generics.clean(cx);
                     let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
-                    TypedefItem(
-                        Typedef {
-                            type_,
-                            generics: Generics::default(),
-                            item_type: Some(item_type),
-                        },
-                        true,
-                    )
+                    TypedefItem(Typedef { type_, generics, item_type: Some(item_type) }, true)
                 }
             };
 
@@ -1140,35 +1148,79 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
             ty::AssocKind::Type => {
                 let my_name = self.name;
 
+                fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
+                    match (&param.kind, arg) {
+                        (GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
+                            if *ty == param.name =>
+                        {
+                            true
+                        }
+                        (
+                            GenericParamDefKind::Lifetime { .. },
+                            GenericArg::Lifetime(Lifetime(lt)),
+                        ) if *lt == param.name => true,
+                        (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => {
+                            match &c.kind {
+                                ConstantKind::TyConst { expr } => expr == param.name.as_str(),
+                                _ => false,
+                            }
+                        }
+                        _ => false,
+                    }
+                }
+
                 if let ty::TraitContainer(_) = self.container {
                     let bounds = tcx.explicit_item_bounds(self.def_id);
                     let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
-                    let generics = clean_ty_generics(cx, tcx.generics_of(self.def_id), predicates);
+                    let mut generics =
+                        clean_ty_generics(cx, tcx.generics_of(self.def_id), predicates);
+                    // Filter out the bounds that are (likely?) directly attached to the associated type,
+                    // as opposed to being located in the where clause.
                     let mut bounds = generics
                         .where_predicates
-                        .iter()
-                        .filter_map(|pred| {
-                            let (name, self_type, trait_, bounds) = match *pred {
-                                WherePredicate::BoundPredicate {
-                                    ty: QPath { ref name, ref self_type, ref trait_, .. },
-                                    ref bounds,
-                                    ..
-                                } => (name, self_type, trait_, bounds),
-                                _ => return None,
-                            };
-                            if *name != my_name {
-                                return None;
-                            }
-                            if trait_.def_id() != self.container.id() {
-                                return None;
+                        .drain_filter(|pred| match *pred {
+                            WherePredicate::BoundPredicate {
+                                ty: QPath { ref assoc, ref self_type, ref trait_, .. },
+                                ..
+                            } => {
+                                if assoc.name != my_name {
+                                    return false;
+                                }
+                                if trait_.def_id() != self.container.id() {
+                                    return false;
+                                }
+                                match **self_type {
+                                    Generic(ref s) if *s == kw::SelfUpper => {}
+                                    _ => return false,
+                                }
+                                match &assoc.args {
+                                    GenericArgs::AngleBracketed { args, bindings } => {
+                                        if !bindings.is_empty()
+                                            || generics
+                                                .params
+                                                .iter()
+                                                .zip(args)
+                                                .any(|(param, arg)| !param_eq_arg(param, arg))
+                                        {
+                                            return false;
+                                        }
+                                    }
+                                    GenericArgs::Parenthesized { .. } => {
+                                        // The only time this happens is if we're inside the rustdoc for Fn(),
+                                        // which only has one associated type, which is not a GAT, so whatever.
+                                    }
+                                }
+                                true
                             }
-                            match **self_type {
-                                Generic(ref s) if *s == kw::SelfUpper => {}
-                                _ => return None,
+                            _ => false,
+                        })
+                        .flat_map(|pred| {
+                            if let WherePredicate::BoundPredicate { bounds, .. } = pred {
+                                bounds
+                            } else {
+                                unreachable!()
                             }
-                            Some(bounds)
                         })
-                        .flat_map(|i| i.iter().cloned())
                         .collect::<Vec<_>>();
                     // Our Sized/?Sized bound didn't get handled when creating the generics
                     // because we didn't actually get our whole set of bounds until just now
@@ -1188,7 +1240,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                         None
                     };
 
-                    AssocTypeItem(bounds, ty.map(|t| t.clean(cx)))
+                    AssocTypeItem(Box::new(generics), bounds, ty.map(|t| t.clean(cx)))
                 } else {
                     // FIXME: when could this happen? Associated items in inherent impls?
                     let type_ = tcx.type_of(self.def_id).clean(cx);
@@ -1259,7 +1311,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
             };
             register_res(cx, trait_.res);
             Type::QPath {
-                name: p.segments.last().expect("segments were empty").ident.name,
+                assoc: Box::new(p.segments.last().expect("segments were empty").clean(cx)),
                 self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
                 self_type: box qself.clean(cx),
                 trait_,
@@ -1276,7 +1328,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
             let trait_ = hir::Path { span, res, segments: &[] }.clean(cx);
             register_res(cx, trait_.res);
             Type::QPath {
-                name: segment.ident.name,
+                assoc: Box::new(segment.clean(cx)),
                 self_def_id: res.opt_def_id(),
                 self_type: box qself.clean(cx),
                 trait_,
@@ -1318,11 +1370,7 @@ fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>
                 });
                 if let Some(lt) = lifetime.cloned() {
                     let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                    let cleaned = if !lt.is_elided() {
-                        lt.clean(cx)
-                    } else {
-                        self::types::Lifetime::elided()
-                    };
+                    let cleaned = if !lt.is_elided() { lt.clean(cx) } else { Lifetime::elided() };
                     substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
                 }
                 indices.lifetimes += 1;
@@ -1548,7 +1596,16 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 let mut bindings = vec![];
                 for pb in obj.projection_bounds() {
                     bindings.push(TypeBinding {
-                        name: cx.tcx.associated_item(pb.item_def_id()).name,
+                        assoc: projection_to_path_segment(
+                            pb.skip_binder()
+                                .lift_to_tcx(cx.tcx)
+                                .unwrap()
+                                // HACK(compiler-errors): Doesn't actually matter what self
+                                // type we put here, because we're only using the GAT's substs.
+                                .with_self_ty(cx.tcx, cx.tcx.types.self_param)
+                                .projection_ty,
+                            cx,
+                        ),
                         kind: TypeBindingKind::Equality { term: pb.skip_binder().term.clean(cx) },
                     });
                 }
@@ -1614,10 +1671,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                                         == trait_ref.skip_binder()
                                     {
                                         Some(TypeBinding {
-                                            name: cx
-                                                .tcx
-                                                .associated_item(proj.projection_ty.item_def_id)
-                                                .name,
+                                            assoc: projection_to_path_segment(
+                                                proj.projection_ty,
+                                                cx,
+                                            ),
                                             kind: TypeBindingKind::Equality {
                                                 term: proj.term.clean(cx),
                                             },
@@ -2160,7 +2217,10 @@ fn clean_maybe_renamed_foreign_item(
 
 impl Clean<TypeBinding> for hir::TypeBinding<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
-        TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) }
+        TypeBinding {
+            assoc: PathSegment { name: self.ident.name, args: self.gen_args.clean(cx) },
+            kind: self.kind.clean(cx),
+        }
     }
 }
 
index ea18d915deb7a96e5fb97c4c0cf6067e9203f271..dd8e1132572fc6a1c728fd430fafafe08a35d6b9 100644 (file)
@@ -89,7 +89,7 @@
     cx: &clean::DocContext<'_>,
     bounds: &mut Vec<clean::GenericBound>,
     trait_did: DefId,
-    name: Symbol,
+    assoc: clean::PathSegment,
     rhs: &clean::Term,
 ) -> bool {
     !bounds.iter_mut().any(|b| {
         match last.args {
             PP::AngleBracketed { ref mut bindings, .. } => {
                 bindings.push(clean::TypeBinding {
-                    name,
+                    assoc: assoc.clone(),
                     kind: clean::TypeBindingKind::Equality { term: rhs.clone() },
                 });
             }
index 467a6940628e7b74f20b959e48d977fdb9836198..c0e7cd0b1f58016e0968015174f04ac22992a92c 100644 (file)
@@ -683,7 +683,7 @@ impl Item {
     ///
     /// The bounds may be non-empty if there is a `where` clause.
     /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
-    AssocTypeItem(Vec<GenericBound>, Option<Type>),
+    AssocTypeItem(Box<Generics>, Vec<GenericBound>, Option<Type>),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemKind>),
     KeywordItem(Symbol),
@@ -721,7 +721,7 @@ impl ItemKind {
             | ProcMacroItem(_)
             | PrimitiveItem(_)
             | AssocConstItem(_, _)
-            | AssocTypeItem(_, _)
+            | AssocTypeItem(..)
             | StrippedItem(_)
             | KeywordItem(_) => [].iter(),
         }
@@ -1397,7 +1397,7 @@ impl FnRetTy {
 
     /// A qualified path to an associated item: `<Type as Trait>::Name`
     QPath {
-        name: Symbol,
+        assoc: Box<PathSegment>,
         self_type: Box<Type>,
         /// FIXME: This is a hack that should be removed; see [this discussion][1].
         ///
@@ -1415,7 +1415,7 @@ impl FnRetTy {
 
 // `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Type, 72);
+rustc_data_structures::static_assert_size!(Type, 80);
 
 impl Type {
     /// When comparing types for equality, it can help to ignore `&` wrapping.
@@ -1505,12 +1505,12 @@ impl Type {
         self.primitive_type().is_some()
     }
 
-    crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
-        let (self_, trait_, name) = match self {
-            QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
-            _ => return None,
-        };
-        Some((&self_, trait_.def_id(), *name))
+    crate fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
+        if let QPath { self_type, trait_, assoc, .. } = self {
+            Some((&self_type, trait_.def_id(), *assoc.clone()))
+        } else {
+            None
+        }
     }
 
     fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
@@ -2018,7 +2018,7 @@ impl Path {
 // `GenericArg` can occur many times in a single `Path`, so make sure it
 // doesn't increase in size unexpectedly.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(GenericArg, 80);
+rustc_data_structures::static_assert_size!(GenericArg, 88);
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate enum GenericArgs {
@@ -2256,7 +2256,7 @@ impl Import {
 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate struct TypeBinding {
-    crate name: Symbol,
+    crate assoc: PathSegment,
     crate kind: TypeBindingKind,
 }
 
index 20eea32560b27fdb5f00c5a0e87d2f7a441f9fc0..7861b915e9627668edd0e9be6f388f4270f229b7 100644 (file)
     Crate { module, primitives, external_traits: cx.external_traits.clone() }
 }
 
-fn external_generic_args(
+crate fn substs_to_args(
     cx: &mut DocContext<'_>,
-    did: DefId,
-    has_self: bool,
-    bindings: Vec<TypeBinding>,
-    substs: SubstsRef<'_>,
-) -> GenericArgs {
-    let mut skip_self = has_self;
-    let mut ty_kind = None;
-    let args: Vec<_> = substs
+    substs: &[ty::subst::GenericArg<'_>],
+    mut skip_first: bool,
+) -> Vec<GenericArg> {
+    substs
         .iter()
         .filter_map(|kind| match kind.unpack() {
             GenericArgKind::Lifetime(lt) => match *lt {
@@ -95,23 +91,32 @@ fn external_generic_args(
                 }
                 _ => lt.clean(cx).map(GenericArg::Lifetime),
             },
-            GenericArgKind::Type(_) if skip_self => {
-                skip_self = false;
+            GenericArgKind::Type(_) if skip_first => {
+                skip_first = false;
                 None
             }
-            GenericArgKind::Type(ty) => {
-                ty_kind = Some(ty.kind());
-                Some(GenericArg::Type(ty.clean(cx)))
-            }
+            GenericArgKind::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
             GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(ct.clean(cx)))),
         })
-        .collect();
+        .collect()
+}
+
+fn external_generic_args(
+    cx: &mut DocContext<'_>,
+    did: DefId,
+    has_self: bool,
+    bindings: Vec<TypeBinding>,
+    substs: SubstsRef<'_>,
+) -> GenericArgs {
+    let args = substs_to_args(cx, &substs, has_self);
 
     if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
-        let inputs = match ty_kind.unwrap() {
-            ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(),
-            _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() },
-        };
+        let inputs =
+            // The trait's first substitution is the one after self, if there is one.
+            match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
+                ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(),
+                _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() },
+            };
         let output = None;
         // FIXME(#20299) return type comes from a projection now
         // match types[1].kind {
index cd0f44e5696fec3e2038dcb5d5a76f24b8fbfbb5..fbb8b572ea43025a54fba2e5a71debace19f275f 100644 (file)
@@ -86,7 +86,7 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
             | ProcMacroItem(_)
             | PrimitiveItem(_)
             | AssocConstItem(_, _)
-            | AssocTypeItem(_, _)
+            | AssocTypeItem(..)
             | KeywordItem(_) => kind,
         }
     }
index c0115bfc6d4fab3d0c4716f9d273e1806150e9a3..a2f48c164652df4c5d351127be6ff6d931e8cf77 100644 (file)
@@ -143,11 +143,14 @@ impl Buffer {
     }
 }
 
-fn comma_sep<T: fmt::Display>(items: impl Iterator<Item = T>) -> impl fmt::Display {
+fn comma_sep<T: fmt::Display>(
+    items: impl Iterator<Item = T>,
+    space_after_comma: bool,
+) -> impl fmt::Display {
     display_fn(move |f| {
         for (i, item) in items.enumerate() {
             if i != 0 {
-                write!(f, ", ")?;
+                write!(f, ",{}", if space_after_comma { " " } else { "" })?;
             }
             fmt::Display::fmt(&item, f)?;
         }
@@ -248,9 +251,9 @@ impl clean::Generics {
             }
 
             if f.alternate() {
-                write!(f, "<{:#}>", comma_sep(real_params.map(|g| g.print(cx))))
+                write!(f, "<{:#}>", comma_sep(real_params.map(|g| g.print(cx)), true))
             } else {
-                write!(f, "&lt;{}&gt;", comma_sep(real_params.map(|g| g.print(cx))))
+                write!(f, "&lt;{}&gt;", comma_sep(real_params.map(|g| g.print(cx)), true))
             }
         })
     }
@@ -266,10 +269,80 @@ impl clean::Generics {
     end_newline: bool,
 ) -> impl fmt::Display + 'a + Captures<'tcx> {
     display_fn(move |f| {
-        if gens.where_predicates.is_empty() {
+        let mut where_predicates = gens.where_predicates.iter().filter(|pred| {
+            !matches!(pred, clean::WherePredicate::BoundPredicate { bounds, .. } if bounds.is_empty())
+        }).map(|pred| {
+            display_fn(move |f| {
+                if f.alternate() {
+                    f.write_str(" ")?;
+                } else {
+                    f.write_str("<br>")?;
+                }
+
+                match pred {
+                    clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
+                        let bounds = bounds;
+                        let for_prefix = if bound_params.is_empty() {
+                            String::new()
+                        } else if f.alternate() {
+                            format!(
+                                "for&lt;{:#}&gt; ",
+                                comma_sep(bound_params.iter().map(|lt| lt.print()), true)
+                            )
+                        } else {
+                            format!(
+                                "for&lt;{}&gt; ",
+                                comma_sep(bound_params.iter().map(|lt| lt.print()), true)
+                            )
+                        };
+
+                        if f.alternate() {
+                            write!(
+                                f,
+                                "{}{:#}: {:#}",
+                                for_prefix,
+                                ty.print(cx),
+                                print_generic_bounds(bounds, cx)
+                            )
+                        } else {
+                            write!(
+                                f,
+                                "{}{}: {}",
+                                for_prefix,
+                                ty.print(cx),
+                                print_generic_bounds(bounds, cx)
+                            )
+                        }
+                    }
+                    clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
+                        write!(
+                            f,
+                            "{}: {}",
+                            lifetime.print(),
+                            bounds
+                                .iter()
+                                .map(|b| b.print(cx).to_string())
+                                .collect::<Vec<_>>()
+                                .join(" + ")
+                        )
+                    }
+                    clean::WherePredicate::EqPredicate { lhs, rhs } => {
+                        if f.alternate() {
+                            write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx),)
+                        } else {
+                            write!(f, "{} == {}", lhs.print(cx), rhs.print(cx),)
+                        }
+                    }
+                }
+            })
+        }).peekable();
+
+        if where_predicates.peek().is_none() {
             return Ok(());
         }
+
         let mut clause = String::new();
+
         if f.alternate() {
             clause.push_str(" where");
         } else {
@@ -279,72 +352,11 @@ impl clean::Generics {
                 clause.push_str(" <span class=\"where\">where");
             }
         }
-        for (i, pred) in gens.where_predicates.iter().enumerate() {
-            if f.alternate() {
-                clause.push(' ');
-            } else {
-                clause.push_str("<br>");
-            }
 
-            match pred {
-                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&lt;{:#}&gt; ",
-                                comma_sep(bound_params.iter().map(|lt| lt.print()))
-                            )
-                        }
-                        _ => format!(
-                            "for&lt;{}&gt; ",
-                            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)
-                        ));
-                    }
-                }
-                clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
-                    clause.push_str(&format!(
-                        "{}: {}",
-                        lifetime.print(),
-                        bounds
-                            .iter()
-                            .map(|b| b.print(cx).to_string())
-                            .collect::<Vec<_>>()
-                            .join(" + ")
-                    ));
-                }
-                clean::WherePredicate::EqPredicate { lhs, rhs } => {
-                    if f.alternate() {
-                        clause.push_str(&format!("{:#} == {:#}", lhs.print(cx), rhs.print(cx),));
-                    } else {
-                        clause.push_str(&format!("{} == {}", lhs.print(cx), rhs.print(cx),));
-                    }
-                }
-            }
-
-            if i < gens.where_predicates.len() - 1 || end_newline {
-                clause.push(',');
-            }
-        }
+        clause.push_str(&comma_sep(where_predicates, false).to_string());
 
         if end_newline {
+            clause.push(',');
             // add a space so stripping <br> tags and breaking spaces still renders properly
             if f.alternate() {
                 clause.push(' ');
@@ -394,13 +406,13 @@ fn print<'a, 'tcx: 'a>(
                     write!(
                         f,
                         "for<{:#}> ",
-                        comma_sep(self.generic_params.iter().map(|g| g.print(cx)))
+                        comma_sep(self.generic_params.iter().map(|g| g.print(cx)), true)
                     )?;
                 } else {
                     write!(
                         f,
                         "for&lt;{}&gt; ",
-                        comma_sep(self.generic_params.iter().map(|g| g.print(cx)))
+                        comma_sep(self.generic_params.iter().map(|g| g.print(cx)), true)
                     )?;
                 }
             }
@@ -424,7 +436,8 @@ impl clean::GenericBound {
                 let modifier_str = match modifier {
                     hir::TraitBoundModifier::None => "",
                     hir::TraitBoundModifier::Maybe => "?",
-                    hir::TraitBoundModifier::MaybeConst => "~const",
+                    // ~const is experimental; do not display those bounds in rustdoc
+                    hir::TraitBoundModifier::MaybeConst => "",
                 };
                 if f.alternate() {
                     write!(f, "{}{:#}", modifier_str, ty.print(cx))
@@ -961,7 +974,7 @@ fn fmt_type<'cx>(
                 write!(f, "impl {}", print_generic_bounds(bounds, cx))
             }
         }
-        clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => {
+        clean::QPath { ref assoc, ref self_type, ref trait_, ref self_def_id } => {
             let should_show_cast = !trait_.segments.is_empty()
                 && self_def_id
                     .zip(Some(trait_.def_id()))
@@ -994,14 +1007,15 @@ fn fmt_type<'cx>(
                     write!(
                         f,
                         "<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
-                                    title=\"type {path}::{name}\">{name}</a>",
+                                    title=\"type {path}::{name}\">{name}</a>{args}",
                         url = url,
                         shortty = ItemType::AssocType,
-                        name = name,
+                        name = assoc.name,
                         path = join_with_double_colon(path),
+                        args = assoc.args.print(cx),
                     )?;
                 }
-                _ => write!(f, "{}", name)?,
+                _ => write!(f, "{}{:#}", assoc.name, assoc.args.print(cx))?,
             }
             Ok(())
         }
@@ -1110,7 +1124,7 @@ fn print_hrtb_with_space<'a, 'tcx: 'a>(
                 write!(
                     f,
                     "for&lt;{}&gt; ",
-                    comma_sep(self.generic_params.iter().map(|g| g.print(cx)))
+                    comma_sep(self.generic_params.iter().map(|g| g.print(cx)), true)
                 )
             } else {
                 Ok(())
@@ -1457,7 +1471,12 @@ impl clean::TypeBinding {
         cx: &'a Context<'tcx>,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
         display_fn(move |f| {
-            f.write_str(self.name.as_str())?;
+            f.write_str(self.assoc.name.as_str())?;
+            if f.alternate() {
+                write!(f, "{:#}", self.assoc.args.print(cx))?;
+            } else {
+                write!(f, "{}", self.assoc.args.print(cx))?;
+            }
             match self.kind {
                 clean::TypeBindingKind::Equality { ref term } => {
                     if f.alternate() {
index 3c1737c5e3f5f72df730496e3269340e73034b01..558dbb3b3965a5e6dd4b968e39c7e36f17cb65bd 100644 (file)
@@ -773,27 +773,115 @@ fn assoc_const(
 fn assoc_type(
     w: &mut Buffer,
     it: &clean::Item,
+    generics: &clean::Generics,
     bounds: &[clean::GenericBound],
     default: Option<&clean::Type>,
     link: AssocItemLink<'_>,
-    extra: &str,
+    indent: usize,
     cx: &Context<'_>,
 ) {
     write!(
         w,
-        "{}type <a href=\"{}\" class=\"associatedtype\">{}</a>",
-        extra,
-        naive_assoc_href(it, link, cx),
-        it.name.as_ref().unwrap()
+        "{indent}type <a href=\"{href}\" class=\"associatedtype\">{name}</a>{generics}",
+        indent = " ".repeat(indent),
+        href = naive_assoc_href(it, link, cx),
+        name = it.name.as_ref().unwrap(),
+        generics = generics.print(cx),
     );
     if !bounds.is_empty() {
         write!(w, ": {}", print_generic_bounds(bounds, cx))
     }
+    write!(w, "{}", print_where_clause(generics, cx, indent, false));
     if let Some(default) = default {
         write!(w, " = {}", default.print(cx))
     }
 }
 
+fn assoc_method(
+    w: &mut Buffer,
+    meth: &clean::Item,
+    header: hir::FnHeader,
+    g: &clean::Generics,
+    d: &clean::FnDecl,
+    link: AssocItemLink<'_>,
+    parent: ItemType,
+    cx: &Context<'_>,
+    render_mode: RenderMode,
+) {
+    let name = meth.name.as_ref().unwrap();
+    let href = match link {
+        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.
+            let ty =
+                if provided_methods.contains(name) { ItemType::Method } else { ItemType::TyMethod };
+
+            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();
+    // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
+    // this condition.
+    let constness = match render_mode {
+        RenderMode::Normal => {
+            print_constness_with_space(&header.constness, meth.const_stability(cx.tcx()))
+        }
+        RenderMode::ForDeref { .. } => "",
+    };
+    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()
+        + vis.len()
+        + constness.len()
+        + asyncness.len()
+        + unsafety.len()
+        + defaultness.len()
+        + abi.len()
+        + name.as_str().len()
+        + generics_len;
+
+    let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
+        header_len += 4;
+        let indent_str = "    ";
+        render_attributes_in_pre(w, meth, indent_str);
+        (4, indent_str, false)
+    } else {
+        render_attributes_in_code(w, meth);
+        (0, "", true)
+    };
+    w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
+    write!(
+        w,
+        "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a {href} class=\"fnname\">{name}</a>\
+         {generics}{decl}{notable_traits}{where_clause}",
+        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),
+        notable_traits = notable_traits_decl(d, cx),
+        where_clause = print_where_clause(g, cx, indent, end_newline),
+    )
+}
+
 /// Writes a span containing the versions at which an item became stable and/or const-stable. For
 /// example, if the item became stable at 1.0.0, and const-stable at 1.45.0, this function would
 /// write a span containing "1.0.0 (const: 1.45.0)".
@@ -875,111 +963,25 @@ fn render_assoc_item(
     cx: &Context<'_>,
     render_mode: RenderMode,
 ) {
-    fn method(
-        w: &mut Buffer,
-        meth: &clean::Item,
-        header: hir::FnHeader,
-        g: &clean::Generics,
-        d: &clean::FnDecl,
-        link: AssocItemLink<'_>,
-        parent: ItemType,
-        cx: &Context<'_>,
-        render_mode: RenderMode,
-    ) {
-        let name = meth.name.as_ref().unwrap();
-        let href = match link {
-            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.
-                let ty = if provided_methods.contains(name) {
-                    ItemType::Method
-                } else {
-                    ItemType::TyMethod
-                };
-
-                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();
-        // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
-        // this condition.
-        let constness = match render_mode {
-            RenderMode::Normal => {
-                print_constness_with_space(&header.constness, meth.const_stability(cx.tcx()))
-            }
-            RenderMode::ForDeref { .. } => "",
-        };
-        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()
-            + vis.len()
-            + constness.len()
-            + asyncness.len()
-            + unsafety.len()
-            + defaultness.len()
-            + abi.len()
-            + name.as_str().len()
-            + generics_len;
-
-        let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
-            header_len += 4;
-            let indent_str = "    ";
-            render_attributes_in_pre(w, meth, indent_str);
-            (4, indent_str, false)
-        } else {
-            render_attributes_in_code(w, meth);
-            (0, "", true)
-        };
-        w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
-        write!(
-            w,
-            "{indent}{vis}{constness}{asyncness}{unsafety}{defaultness}{abi}fn <a {href} class=\"fnname\">{name}</a>\
-             {generics}{decl}{notable_traits}{where_clause}",
-            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),
-            notable_traits = notable_traits_decl(d, cx),
-            where_clause = print_where_clause(g, cx, indent, end_newline),
-        )
-    }
     match *item.kind {
         clean::StrippedItem(..) => {}
         clean::TyMethodItem(ref m) => {
-            method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
+            assoc_method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
         }
         clean::MethodItem(ref m, _) => {
-            method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
+            assoc_method(w, item, m.header, &m.generics, &m.decl, link, parent, cx, render_mode)
         }
         clean::AssocConstItem(ref ty, _) => {
             assoc_const(w, item, ty, link, if parent == ItemType::Trait { "    " } else { "" }, cx)
         }
-        clean::AssocTypeItem(ref bounds, ref default) => assoc_type(
+        clean::AssocTypeItem(ref generics, ref bounds, ref default) => assoc_type(
             w,
             item,
+            generics,
             bounds,
             default.as_ref(),
             link,
-            if parent == ItemType::Trait { "    " } else { "" },
+            if parent == ItemType::Trait { 4 } else { 0 },
             cx,
         ),
         _ => panic!("render_assoc_item called on non-associated-item"),
@@ -1283,7 +1285,16 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
                                 let empty_set = FxHashSet::default();
                                 let src_link =
                                     AssocItemLink::GotoSource(trait_did.into(), &empty_set);
-                                assoc_type(&mut out, it, &[], Some(&tydef.type_), src_link, "", cx);
+                                assoc_type(
+                                    &mut out,
+                                    it,
+                                    &tydef.generics,
+                                    &[],
+                                    Some(&tydef.type_),
+                                    src_link,
+                                    0,
+                                    cx,
+                                );
                                 out.push_str(";</span>");
                             }
                         }
@@ -1462,10 +1473,11 @@ fn doc_impl_item(
                 assoc_type(
                     w,
                     item,
-                    &Vec::new(),
+                    &tydef.generics,
+                    &[],
                     Some(&tydef.type_),
                     link.anchor(if trait_.is_some() { &source_id } else { &id }),
-                    "",
+                    0,
                     cx,
                 );
                 w.write_str("</h4>");
@@ -1493,7 +1505,7 @@ fn doc_impl_item(
                 w.write_str("</h4>");
                 w.write_str("</section>");
             }
-            clean::AssocTypeItem(ref bounds, ref default) => {
+            clean::AssocTypeItem(ref generics, ref bounds, ref default) => {
                 let source_id = format!("{}.{}", item_type, name);
                 let id = cx.derive_id(source_id.clone());
                 write!(w, "<section id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class,);
@@ -1502,10 +1514,11 @@ fn doc_impl_item(
                 assoc_type(
                     w,
                     item,
+                    generics,
                     bounds,
                     default.as_ref(),
                     link.anchor(if trait_.is_some() { &source_id } else { &id }),
-                    "",
+                    0,
                     cx,
                 );
                 w.write_str("</h4>");
@@ -1726,7 +1739,16 @@ pub(crate) fn render_impl_summary(
             for it in &i.inner_impl().items {
                 if let clean::TypedefItem(ref tydef, _) = *it.kind {
                     w.write_str("<span class=\"where fmt-newline\">  ");
-                    assoc_type(w, it, &[], Some(&tydef.type_), AssocItemLink::Anchor(None), "", cx);
+                    assoc_type(
+                        w,
+                        it,
+                        &tydef.generics,
+                        &[],
+                        Some(&tydef.type_),
+                        AssocItemLink::Anchor(None),
+                        0,
+                        cx,
+                    );
                     w.write_str(";</span>");
                 }
             }
index e84dc6c72409f6ee2bc98089a3ad6144a8e77503..68644a017a4004001188eaf3c697e99dd1f9a0ac 100644 (file)
@@ -1710,11 +1710,11 @@ struct update syntax will not work.",
 }
 
 fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
-    fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
-        if layout.abi.is_unsized() {
+    fn write_size_of_layout(w: &mut Buffer, layout: Layout<'_>, tag_size: u64) {
+        if layout.abi().is_unsized() {
             write!(w, "(unsized)");
         } else {
-            let bytes = layout.size.bytes() - tag_size;
+            let bytes = layout.size().bytes() - tag_size;
             write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },);
         }
     }
@@ -1744,7 +1744,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
             write_size_of_layout(w, ty_layout.layout, 0);
             writeln!(w, "</p>");
             if let Variants::Multiple { variants, tag, tag_encoding, .. } =
-                &ty_layout.layout.variants
+                &ty_layout.layout.variants()
             {
                 if !variants.is_empty() {
                     w.write_str(
@@ -1767,7 +1767,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
                     for (index, layout) in variants.iter_enumerated() {
                         let name = adt.variants[index].name;
                         write!(w, "<li><code>{name}</code>: ", name = name);
-                        write_size_of_layout(w, layout, tag_size);
+                        write_size_of_layout(w, *layout, tag_size);
                         writeln!(w, "</li>");
                     }
                     w.write_str("</ul>");
index bae04f2095a3d079d63a6a09636953c3c592292b..9fba6e911628229f8ed8632581ea9916ba96a56c 100644 (file)
@@ -272,22 +272,16 @@ fn emit_source(
 ) {
     let lines = s.lines().count();
     let mut line_numbers = Buffer::empty_from(buf);
-    let mut cols = 0;
-    let mut tmp = lines;
-    while tmp > 0 {
-        cols += 1;
-        tmp /= 10;
-    }
     line_numbers.write_str("<pre class=\"line-numbers\">");
     match source_context {
         SourceContext::Standalone => {
             for line in 1..=lines {
-                writeln!(line_numbers, "<span id=\"{0}\">{0:1$}</span>", line, cols)
+                writeln!(line_numbers, "<span id=\"{0}\">{0}</span>", line)
             }
         }
         SourceContext::Embedded { offset } => {
             for line in 1..=lines {
-                writeln!(line_numbers, "<span>{0:1$}</span>", line + offset, cols)
+                writeln!(line_numbers, "<span>{0}</span>", line + offset)
             }
         }
     }
index f1e0a89883ab8d2915c862304aa0ed126ee2c3d5..9a4b382a304ff9b899dafbb83719dc5763ea7ba9 100644 (file)
@@ -541,6 +541,9 @@ h2.location a {
        text-decoration: underline;
 }
 
+.line-numbers {
+       text-align: right;
+}
 .rustdoc:not(.source) .example-wrap > pre:not(.line-number) {
        width: 100%;
        overflow-x: auto;
index 90490acccfdb5714a79994d19f8582e5febe2476..aa77e62ba5acb03e4a4527f248d9ff9f9a8f9cef 100644 (file)
@@ -149,7 +149,7 @@ function createSourceSidebar() {
 
 var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
 
-function highlightSourceLines(scrollTo, match) {
+function highlightSourceLines(match) {
     if (typeof match === "undefined") {
         match = window.location.hash.match(lineNumbersRegex);
     }
@@ -170,11 +170,9 @@ function highlightSourceLines(scrollTo, match) {
     if (!elem) {
         return;
     }
-    if (scrollTo) {
-        var x = document.getElementById(from);
-        if (x) {
-            x.scrollIntoView();
-        }
+    var x = document.getElementById(from);
+    if (x) {
+        x.scrollIntoView();
     }
     onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
         onEachLazy(e.getElementsByTagName("span"), function(i_e) {
@@ -198,7 +196,7 @@ var handleSourceHighlight = (function() {
             y = window.scrollY;
         if (searchState.browserSupportsHistoryApi()) {
             history.replaceState(null, null, "#" + name);
-            highlightSourceLines(true);
+            highlightSourceLines();
         } else {
             location.replace("#" + name);
         }
@@ -230,7 +228,7 @@ var handleSourceHighlight = (function() {
 window.addEventListener("hashchange", function() {
     var match = window.location.hash.match(lineNumbersRegex);
     if (match) {
-        return highlightSourceLines(false, match);
+        return highlightSourceLines(match);
     }
 });
 
@@ -238,7 +236,7 @@ onEachLazy(document.getElementsByClassName("line-numbers"), function(el) {
     el.addEventListener("click", handleSourceHighlight);
 });
 
-highlightSourceLines(true);
+highlightSourceLines();
 
 window.createSourceSidebar = createSourceSidebar;
 })();
index baadd3c27b446e884ec4ba5615c834ac490b8680..564731ab7354b1ad7ea7e25b5d130f2b485582da 100644 (file)
@@ -54,7 +54,7 @@
             href="{{static_root_path|safe}}theme{{page.resource_suffix}}.css"> {#- -#}
     {%- endif -%}
     {%- if !layout.favicon.is_empty() -%}
-        <link rel="shortcut icon" href="{{layout.favicon}}"> {#- -#}
+        <link rel="icon" href="{{layout.favicon}}"> {#- -#}
     {%- else -%}
         <link rel="alternate icon" type="image/png" {# -#}
             href="{{static_root_path|safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
index d4aedb41ddb18e8f459895d4f403b4be02080720..4358dc8980f2f6b322903d99a5bb7faf40f240b1 100644 (file)
@@ -154,7 +154,11 @@ fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self {
 
 impl FromWithTcx<clean::TypeBinding> for TypeBinding {
     fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self {
-        TypeBinding { name: binding.name.to_string(), binding: binding.kind.into_tcx(tcx) }
+        TypeBinding {
+            name: binding.assoc.name.to_string(),
+            args: binding.assoc.args.into_tcx(tcx),
+            binding: binding.kind.into_tcx(tcx),
+        }
     }
 }
 
@@ -222,8 +226,9 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
         AssocConstItem(ty, default) => {
             ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: default.map(|c| c.expr(tcx)) }
         }
-        AssocTypeItem(g, t) => ItemEnum::AssocType {
-            bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(),
+        AssocTypeItem(g, b, t) => ItemEnum::AssocType {
+            generics: (*g).into_tcx(tcx),
+            bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
             default: t.map(|x| x.into_tcx(tcx)),
         },
         // `convert_item` early returns `None` for striped items
@@ -444,11 +449,12 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
                 mutable: mutability == ast::Mutability::Mut,
                 type_: Box::new((*type_).into_tcx(tcx)),
             },
-            QPath { name, self_type, trait_, .. } => {
+            QPath { assoc, self_type, trait_, .. } => {
                 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
                 let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
                 Type::QualifiedPath {
-                    name: name.to_string(),
+                    name: assoc.name.to_string(),
+                    args: Box::new(assoc.args.clone().into_tcx(tcx)),
                     self_type: Box::new((*self_type).into_tcx(tcx)),
                     trait_: Box::new(trait_),
                 }
index 4d88a4da45f4477359c0561c155734917632ac30..f378915172a699ed1e14c659d58b6f6cb9356f97 100644 (file)
@@ -9,6 +9,7 @@
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(box_syntax)]
+#![feature(drain_filter)]
 #![feature(let_else)]
 #![feature(nll)]
 #![feature(test)]
index e8f8ff988c1f0233b7db810c0e1f045491880092..6cffb52bb875f794929c7570a52703a98e8b1546 100644 (file)
@@ -62,7 +62,7 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
             clean::StructFieldItem(_)
                 | clean::VariantItem(_)
                 | clean::AssocConstItem(_, _)
-                | clean::AssocTypeItem(_, _)
+                | clean::AssocTypeItem(..)
                 | clean::TypedefItem(_, _)
                 | clean::StaticItem(_)
                 | clean::ConstantItem(_)
index 3ebd28e83b1220689ae249b89e458fca6a343185..aa771a06f9c36e5593ed49e7dcc550fe8c2f584c 100644 (file)
@@ -26,7 +26,8 @@
 use std::mem;
 use std::ops::Range;
 
-use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
+use crate::clean::{self, utils::find_nearest_parent_module};
+use crate::clean::{Crate, Item, ItemId, ItemLink, PrimitiveType};
 use crate::core::DocContext;
 use crate::html::markdown::{markdown_links, MarkdownLink};
 use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
@@ -177,6 +178,8 @@ enum ResolutionFailure<'a> {
     /// The link failed to resolve. [`resolution_failure`] should look to see if there's
     /// a more helpful error that can be given.
     NotResolved {
+        /// Item on which the link is resolved, used for resolving `Self`.
+        item_id: ItemId,
         /// The scope the link was resolved in.
         module_id: DefId,
         /// If part of the link resolved, this has the `Res`.
@@ -343,6 +346,7 @@ fn from_assoc_item(item: &ty::AssocItem) -> Self {
 
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 struct ResolutionInfo {
+    item_id: ItemId,
     module_id: DefId,
     dis: Option<Disambiguator>,
     path_str: String,
@@ -384,10 +388,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
     fn variant_field<'path>(
         &self,
         path_str: &'path str,
+        item_id: ItemId,
         module_id: DefId,
     ) -> Result<(Res, Option<ItemFragment>), ErrorKind<'path>> {
         let tcx = self.cx.tcx;
         let no_res = || ResolutionFailure::NotResolved {
+            item_id,
             module_id,
             partial_res: None,
             unresolved: path_str.into(),
@@ -410,13 +416,7 @@ fn variant_field<'path>(
             // If there's no third component, we saw `[a::b]` before and it failed to resolve.
             // So there's no partial res.
             .ok_or_else(no_res)?;
-        let ty_res = self
-            .cx
-            .enter_resolver(|resolver| {
-                resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
-            })
-            .and_then(|(_, res)| res.try_into())
-            .map_err(|()| no_res())?;
+        let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?;
 
         match ty_res {
             Res::Def(DefKind::Enum, did) => {
@@ -437,6 +437,7 @@ fn variant_field<'path>(
                             Ok((ty_res, Some(ItemFragment(FragmentKind::VariantField, field.did))))
                         } else {
                             Err(ResolutionFailure::NotResolved {
+                                item_id,
                                 module_id,
                                 partial_res: Some(Res::Def(DefKind::Enum, def.did)),
                                 unresolved: variant_field_name.to_string().into(),
@@ -448,6 +449,7 @@ fn variant_field<'path>(
                 }
             }
             _ => Err(ResolutionFailure::NotResolved {
+                item_id,
                 module_id,
                 partial_res: Some(ty_res),
                 unresolved: variant_name.to_string().into(),
@@ -481,6 +483,7 @@ fn resolve_primitive_associated_item(
     fn resolve_macro(
         &self,
         path_str: &'a str,
+        item_id: ItemId,
         module_id: DefId,
     ) -> Result<Res, ResolutionFailure<'a>> {
         self.cx.enter_resolver(|resolver| {
@@ -499,6 +502,7 @@ fn resolve_macro(
                 return Ok(res.try_into().unwrap());
             }
             Err(ResolutionFailure::NotResolved {
+                item_id,
                 module_id,
                 partial_res: None,
                 unresolved: path_str.into(),
@@ -506,12 +510,52 @@ fn resolve_macro(
         })
     }
 
+    fn resolve_self_ty(&self, path_str: &str, ns: Namespace, item_id: ItemId) -> Option<Res> {
+        if ns != TypeNS || path_str != "Self" {
+            return None;
+        }
+
+        let tcx = self.cx.tcx;
+        item_id
+            .as_def_id()
+            .map(|def_id| match tcx.def_kind(def_id) {
+                def_kind @ (DefKind::AssocFn
+                | DefKind::AssocConst
+                | DefKind::AssocTy
+                | DefKind::Variant
+                | DefKind::Field) => {
+                    let parent_def_id = tcx.parent(def_id).expect("nested item has no parent");
+                    if def_kind == DefKind::Field && tcx.def_kind(parent_def_id) == DefKind::Variant
+                    {
+                        tcx.parent(parent_def_id).expect("variant has no parent")
+                    } else {
+                        parent_def_id
+                    }
+                }
+                _ => def_id,
+            })
+            .and_then(|self_id| match tcx.def_kind(self_id) {
+                DefKind::Impl => self.def_id_to_res(self_id),
+                def_kind => Some(Res::Def(def_kind, self_id)),
+            })
+    }
+
     /// Convenience wrapper around `resolve_str_path_error`.
     ///
     /// This also handles resolving `true` and `false` as booleans.
     /// NOTE: `resolve_str_path_error` knows only about paths, not about types.
     /// Associated items will never be resolved by this function.
-    fn resolve_path(&self, path_str: &str, ns: Namespace, module_id: DefId) -> Option<Res> {
+    fn resolve_path(
+        &self,
+        path_str: &str,
+        ns: Namespace,
+        item_id: ItemId,
+        module_id: DefId,
+    ) -> Option<Res> {
+        if let res @ Some(..) = self.resolve_self_ty(path_str, ns, item_id) {
+            return res;
+        }
+
         let result = self.cx.enter_resolver(|resolver| {
             resolver
                 .resolve_str_path_error(DUMMY_SP, path_str, ns, module_id)
@@ -532,10 +576,11 @@ fn resolve<'path>(
         &mut self,
         path_str: &'path str,
         ns: Namespace,
+        item_id: ItemId,
         module_id: DefId,
         user_fragment: &Option<String>,
     ) -> Result<(Res, Option<UrlFragment>), ErrorKind<'path>> {
-        let (res, rustdoc_fragment) = self.resolve_inner(path_str, ns, module_id)?;
+        let (res, rustdoc_fragment) = self.resolve_inner(path_str, ns, item_id, module_id)?;
         let chosen_fragment = match (user_fragment, rustdoc_fragment) {
             (Some(_), Some(r_frag)) => {
                 let diag_res = match r_frag {
@@ -555,9 +600,10 @@ fn resolve_inner<'path>(
         &mut self,
         path_str: &'path str,
         ns: Namespace,
+        item_id: ItemId,
         module_id: DefId,
     ) -> Result<(Res, Option<ItemFragment>), ErrorKind<'path>> {
-        if let Some(res) = self.resolve_path(path_str, ns, module_id) {
+        if let Some(res) = self.resolve_path(path_str, ns, item_id, module_id) {
             match res {
                 // FIXME(#76467): make this fallthrough to lookup the associated
                 // item a separate function.
@@ -585,6 +631,7 @@ fn resolve_inner<'path>(
             .ok_or_else(|| {
                 debug!("found no `::`, assumming {} was correctly not in scope", item_name);
                 ResolutionFailure::NotResolved {
+                    item_id,
                     module_id,
                     partial_res: None,
                     unresolved: item_str.into(),
@@ -596,7 +643,7 @@ fn resolve_inner<'path>(
         // error instead and special case *only* modules with `#[doc(primitive)]`, not all
         // primitives.
         resolve_primitive(&path_root, TypeNS)
-            .or_else(|| self.resolve_path(&path_root, TypeNS, module_id))
+            .or_else(|| self.resolve_path(&path_root, TypeNS, item_id, module_id))
             .and_then(|ty_res| {
                 let (res, fragment) =
                     self.resolve_associated_item(ty_res, item_name, ns, module_id)?;
@@ -605,9 +652,10 @@ fn resolve_inner<'path>(
             })
             .unwrap_or_else(|| {
                 if ns == Namespace::ValueNS {
-                    self.variant_field(path_str, module_id)
+                    self.variant_field(path_str, item_id, module_id)
                 } else {
                     Err(ResolutionFailure::NotResolved {
+                        item_id,
                         module_id,
                         partial_res: None,
                         unresolved: path_root.into(),
@@ -723,10 +771,27 @@ fn resolve_associated_item(
                 self.resolve_associated_item(res, item_name, ns, module_id)
             }
             Res::Def(
-                DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::ForeignTy,
+                def_kind @ (DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::ForeignTy),
                 did,
             ) => {
                 debug!("looking for associated item named {} for item {:?}", item_name, did);
+                // Checks if item_name is a variant of the `SomeItem` enum
+                if ns == TypeNS && def_kind == DefKind::Enum {
+                    match tcx.type_of(did).kind() {
+                        ty::Adt(adt_def, _) => {
+                            for variant in &adt_def.variants {
+                                if variant.name == item_name {
+                                    return Some((
+                                        root_res,
+                                        ItemFragment(FragmentKind::Variant, variant.def_id),
+                                    ));
+                                }
+                            }
+                        }
+                        _ => unreachable!(),
+                    }
+                }
+
                 // Checks if item_name belongs to `impl SomeItem`
                 let assoc_item = tcx
                     .inherent_impls(did)
@@ -813,17 +878,18 @@ fn check_full_res(
         &mut self,
         ns: Namespace,
         path_str: &str,
+        item_id: ItemId,
         module_id: DefId,
         extra_fragment: &Option<String>,
     ) -> Option<Res> {
         // resolve() can't be used for macro namespace
         let result = match ns {
             Namespace::MacroNS => self
-                .resolve_macro(path_str, module_id)
+                .resolve_macro(path_str, item_id, module_id)
                 .map(|res| (res, None))
                 .map_err(ErrorKind::from),
             Namespace::TypeNS | Namespace::ValueNS => {
-                self.resolve(path_str, ns, module_id, extra_fragment)
+                self.resolve(path_str, ns, item_id, module_id, extra_fragment)
             }
         };
 
@@ -970,53 +1036,6 @@ fn visit_item(&mut self, item: &Item) {
             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 = 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) => Some(did),
-        };
-
-        // FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
-        let self_name = self_id.and_then(|self_id| {
-            if matches!(self.cx.tcx.def_kind(self_id), DefKind::Impl) {
-                // using `ty.to_string()` (or any variant) has issues with raw idents
-                let ty = self.cx.tcx.type_of(self_id);
-                let name = match ty.kind() {
-                    ty::Adt(def, _) => Some(self.cx.tcx.item_name(def.did).to_string()),
-                    other if other.is_primitive() => Some(ty.to_string()),
-                    _ => None,
-                };
-                debug!("using type_of(): {:?}", name);
-                name
-            } else {
-                let name = self.cx.tcx.opt_item_name(self_id).map(|sym| sym.to_string());
-                debug!("using item_name(): {:?}", name);
-                name
-            }
-        });
-
         let inner_docs = item.inner_docs(self.cx.tcx);
 
         if item.is_mod() && inner_docs {
@@ -1038,7 +1057,7 @@ fn visit_item(&mut self, item: &Item) {
             // NOTE: if there are links that start in one crate and end in another, this will not resolve them.
             // This is a degenerate case and it's not supported by rustdoc.
             for md_link in markdown_links(&doc) {
-                let link = self.resolve_link(&item, &doc, &self_name, parent_node, krate, md_link);
+                let link = self.resolve_link(&item, &doc, parent_node, krate, md_link);
                 if let Some(link) = link {
                     self.cx.cache.intra_doc_links.entry(item.def_id).or_default().push(link);
                 }
@@ -1172,7 +1191,6 @@ fn resolve_link(
         &mut self,
         item: &Item,
         dox: &str,
-        self_name: &Option<String>,
         parent_node: Option<DefId>,
         krate: CrateNum,
         ori_link: MarkdownLink,
@@ -1240,19 +1258,8 @@ fn resolve_link(
         };
 
         let resolved_self;
-        // replace `Self` with suitable item's parent name
-        let is_lone_self = path_str == "Self";
         let is_lone_crate = path_str == "crate";
-        if path_str.starts_with("Self::") || is_lone_self {
-            if let Some(ref name) = self_name {
-                if is_lone_self {
-                    path_str = name;
-                } else {
-                    resolved_self = format!("{}::{}", name, &path_str[6..]);
-                    path_str = &resolved_self;
-                }
-            }
-        } else if path_str.starts_with("crate::") || is_lone_crate {
+        if path_str.starts_with("crate::") || is_lone_crate {
             use rustc_span::def_id::CRATE_DEF_INDEX;
 
             // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented.
@@ -1272,6 +1279,7 @@ fn resolve_link(
 
         let (mut res, fragment) = self.resolve_with_disambiguator_cached(
             ResolutionInfo {
+                item_id: item.def_id,
                 module_id,
                 dis: disambiguator,
                 path_str: path_str.to_owned(),
@@ -1514,12 +1522,13 @@ fn resolve_with_disambiguator(
     ) -> Option<(Res, Option<UrlFragment>)> {
         let disambiguator = key.dis;
         let path_str = &key.path_str;
+        let item_id = key.item_id;
         let base_node = key.module_id;
         let extra_fragment = &key.extra_fragment;
 
         match disambiguator.map(Disambiguator::ns) {
             Some(expected_ns @ (ValueNS | TypeNS)) => {
-                match self.resolve(path_str, expected_ns, base_node, extra_fragment) {
+                match self.resolve(path_str, expected_ns, item_id, base_node, extra_fragment) {
                     Ok(res) => Some(res),
                     Err(ErrorKind::Resolve(box mut kind)) => {
                         // We only looked in one namespace. Try to give a better error if possible.
@@ -1528,9 +1537,13 @@ fn resolve_with_disambiguator(
                             // 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] {
-                                if let Some(res) =
-                                    self.check_full_res(new_ns, path_str, base_node, extra_fragment)
-                                {
+                                if let Some(res) = self.check_full_res(
+                                    new_ns,
+                                    path_str,
+                                    item_id,
+                                    base_node,
+                                    extra_fragment,
+                                ) {
                                     kind = ResolutionFailure::WrongNamespace { res, expected_ns };
                                     break;
                                 }
@@ -1552,9 +1565,15 @@ fn resolve_with_disambiguator(
                 // Try everything!
                 let mut candidates = PerNS {
                     macro_ns: self
-                        .resolve_macro(path_str, base_node)
+                        .resolve_macro(path_str, item_id, base_node)
                         .map(|res| (res, extra_fragment.clone().map(UrlFragment::UserWritten))),
-                    type_ns: match self.resolve(path_str, TypeNS, base_node, extra_fragment) {
+                    type_ns: match self.resolve(
+                        path_str,
+                        TypeNS,
+                        item_id,
+                        base_node,
+                        extra_fragment,
+                    ) {
                         Ok(res) => {
                             debug!("got res in TypeNS: {:?}", res);
                             Ok(res)
@@ -1565,7 +1584,13 @@ fn resolve_with_disambiguator(
                         }
                         Err(ErrorKind::Resolve(box kind)) => Err(kind),
                     },
-                    value_ns: match self.resolve(path_str, ValueNS, base_node, extra_fragment) {
+                    value_ns: match self.resolve(
+                        path_str,
+                        ValueNS,
+                        item_id,
+                        base_node,
+                        extra_fragment,
+                    ) {
                         Ok(res) => Ok(res),
                         Err(ErrorKind::AnchorFailure(msg)) => {
                             anchor_failure(self.cx, diag, msg);
@@ -1624,14 +1649,18 @@ fn resolve_with_disambiguator(
                 }
             }
             Some(MacroNS) => {
-                match self.resolve_macro(path_str, base_node) {
+                match self.resolve_macro(path_str, item_id, base_node) {
                     Ok(res) => Some((res, extra_fragment.clone().map(UrlFragment::UserWritten))),
                     Err(mut kind) => {
                         // `resolve_macro` only looks in the macro namespace. Try to give a better error if possible.
                         for ns in [TypeNS, ValueNS] {
-                            if let Some(res) =
-                                self.check_full_res(ns, path_str, base_node, extra_fragment)
-                            {
+                            if let Some(res) = self.check_full_res(
+                                ns,
+                                path_str,
+                                item_id,
+                                base_node,
+                                extra_fragment,
+                            ) {
                                 kind =
                                     ResolutionFailure::WrongNamespace { res, expected_ns: MacroNS };
                                 break;
@@ -1958,11 +1987,16 @@ fn resolution_failure(
                 }
                 variants_seen.push(variant);
 
-                if let ResolutionFailure::NotResolved { module_id, partial_res, unresolved } =
-                    &mut failure
+                if let ResolutionFailure::NotResolved {
+                    item_id,
+                    module_id,
+                    partial_res,
+                    unresolved,
+                } = &mut failure
                 {
                     use DefKind::*;
 
+                    let item_id = *item_id;
                     let module_id = *module_id;
                     // FIXME(jynelson): this might conflict with my `Self` fix in #76467
                     // FIXME: maybe use itertools `collect_tuple` instead?
@@ -1984,7 +2018,8 @@ fn split(path: &str) -> Option<(&str, &str)> {
                         };
                         name = start;
                         for ns in [TypeNS, ValueNS, MacroNS] {
-                            if let Some(res) = collector.check_full_res(ns, start, module_id, &None)
+                            if let Some(res) =
+                                collector.check_full_res(ns, start, item_id, module_id, &None)
                             {
                                 debug!("found partial_res={:?}", res);
                                 *partial_res = Some(res);
index df4d1558ebdf42f31cb9bfd15cf13fcffc4d7147..b16cab1c646f13f6d642d661a92be507f34b606f 100644 (file)
@@ -41,7 +41,7 @@ fn visit_inner_recur(&mut self, kind: &ItemKind) {
             | ProcMacroItem(_)
             | PrimitiveItem(_)
             | AssocConstItem(_, _)
-            | AssocTypeItem(_, _)
+            | AssocTypeItem(..)
             | KeywordItem(_) => {}
         }
     }
index be9bbc7391d752a9d7a631a3f5e6308e853ac018..40b0de448293ac5fada8edd894b74104a65cf5c9 100644 (file)
@@ -9,7 +9,7 @@
 use serde::{Deserialize, Serialize};
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 11;
+pub const FORMAT_VERSION: u32 = 12;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -145,6 +145,7 @@ pub struct Constant {
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct TypeBinding {
     pub name: String,
+    pub args: GenericArgs,
     pub binding: TypeBindingKind,
 }
 
@@ -233,6 +234,7 @@ pub enum ItemEnum {
         default: Option<String>,
     },
     AssocType {
+        generics: Generics,
         bounds: Vec<GenericBound>,
         /// e.g. `type X = usize;`
         default: Option<Type>,
@@ -432,6 +434,7 @@ pub enum Type {
     /// `<Type as Trait>::Name` or associated types like `T::Item` where `T: Iterator`
     QualifiedPath {
         name: String,
+        args: Box<GenericArgs>,
         self_type: Box<Type>,
         #[serde(rename = "trait")]
         trait_: Box<Type>,
diff --git a/src/test/codegen/arg-return-value-in-reg.rs b/src/test/codegen/arg-return-value-in-reg.rs
deleted file mode 100644 (file)
index a69291d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-//! Check that types of up to 128 bits are passed and returned by-value instead of via pointer.
-
-// compile-flags: -C no-prepopulate-passes -O
-// only-x86_64
-
-#![crate_type = "lib"]
-
-pub struct S {
-    a: u64,
-    b: u32,
-    c: u32,
-}
-
-// CHECK: define i128 @modify(i128{{( %0)?}})
-#[no_mangle]
-pub fn modify(s: S) -> S {
-    S { a: s.a + s.a, b: s.b + s.b, c: s.c + s.c }
-}
-
-#[repr(packed)]
-pub struct TooBig {
-    a: u64,
-    b: u32,
-    c: u32,
-    d: u8,
-}
-
-// CHECK: define void @m_big(%TooBig* [[ATTRS:.*sret.*]], %TooBig* [[ATTRS2:.*]] %s)
-#[no_mangle]
-pub fn m_big(s: TooBig) -> TooBig {
-    TooBig { a: s.a + s.a, b: s.b + s.b, c: s.c + s.c, d: s.d + s.d }
-}
index fefc232b490409d1cb218fffdc8055cea3023a7e..8dce004b54a1b2d7d3b46044974efd03c0c4145f 100644 (file)
@@ -5,20 +5,20 @@
 
 // CHECK-LABEL: @array_eq_value
 #[no_mangle]
-pub fn array_eq_value(a: [u16; 6], b: [u16; 6]) -> bool {
+pub fn array_eq_value(a: [u16; 3], b: [u16; 3]) -> bool {
     // CHECK-NEXT: start:
-    // CHECK-NEXT: %2 = icmp eq i96 %0, %1
+    // CHECK-NEXT: %2 = icmp eq i48 %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 {
+pub fn array_eq_ref(a: &[u16; 3], b: &[u16; 3]) -> bool {
     // CHECK: start:
-    // CHECK: load i96, i96* %{{.+}}, align 2
-    // CHECK: load i96, i96* %{{.+}}, align 2
-    // CHECK: icmp eq i96
+    // CHECK: load i48, i48* %{{.+}}, align 2
+    // CHECK: load i48, i48* %{{.+}}, align 2
+    // CHECK: icmp eq i48
     // CHECK-NEXT: ret
     a == b
 }
     a == b
 }
 
-// CHECK-LABEL: @array_eq_zero(i128 %0)
+// CHECK-LABEL: @array_eq_zero_short(i48
 #[no_mangle]
-pub fn array_eq_zero(x: [u16; 8]) -> bool {
+pub fn array_eq_zero_short(x: [u16; 3]) -> bool {
     // CHECK-NEXT: start:
-    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i128 %0, 0
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i48 %0, 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [0; 3]
+}
+
+// CHECK-LABEL: @array_eq_zero_mid([8 x i16]*
+#[no_mangle]
+pub fn array_eq_zero_mid(x: [u16; 8]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: bitcast
+    // CHECK-NEXT: %[[LOAD:.+]] = load i128,
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i128 %[[LOAD]], 0
     // CHECK-NEXT: ret i1 %[[EQ]]
     x == [0; 8]
 }
+
+// CHECK-LABEL: @array_eq_zero_long([1234 x i16]*
+#[no_mangle]
+pub fn array_eq_zero_long(x: [u16; 1234]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NOT: alloca
+    // CHECK: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [0; 1234]
+}
diff --git a/src/test/codegen/autovectorize-f32x4.rs b/src/test/codegen/autovectorize-f32x4.rs
new file mode 100644 (file)
index 0000000..6b09c8f
--- /dev/null
@@ -0,0 +1,32 @@
+// compile-flags: -C opt-level=3
+// only-x86_64
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @auto_vectorize_direct
+#[no_mangle]
+pub fn auto_vectorize_direct(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
+// CHECK: load <4 x float>
+// CHECK: load <4 x float>
+// CHECK: fadd <4 x float>
+// CHECK: store <4 x float>
+    [
+        a[0] + b[0],
+        a[1] + b[1],
+        a[2] + b[2],
+        a[3] + b[3],
+    ]
+}
+
+// CHECK-LABEL: @auto_vectorize_loop
+#[no_mangle]
+pub fn auto_vectorize_loop(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
+// CHECK: load <4 x float>
+// CHECK: load <4 x float>
+// CHECK: fadd <4 x float>
+// CHECK: store <4 x float>
+    let mut c = [0.0; 4];
+    for i in 0..4 {
+        c[i] = a[i] + b[i];
+    }
+    c
+}
index 977175a4a621dffe17d7a6cc5c6bc61c286b9e48..c7444ce02fa2573c4daae2617b7e890ef543ee88 100644 (file)
@@ -18,21 +18,47 @@ pub enum MyBool {
     False,
 }
 
+#[repr(align(16))]
+pub struct Align16(u128);
+
+// CHECK: @ptr_alignment_helper({}** {{.*}}align [[PTR_ALIGNMENT:[0-9]+]]
+#[no_mangle]
+pub fn ptr_alignment_helper(x: &&()) {}
+
 // CHECK-LABEL: @load_ref
 #[no_mangle]
 pub fn load_ref<'a>(x: &&'a i32) -> &'a i32 {
-// Alignment of a reference itself is target dependent, so just match any alignment:
-// the main thing we care about here is !nonnull and !noundef.
-// CHECK: load i32*, i32** %x, align {{[0-9]+}}, !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}
+// CHECK: load i32*, i32** %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META:[0-9]+]], !noundef !{{[0-9]+}}
+    *x
+}
+
+// CHECK-LABEL: @load_ref_higher_alignment
+#[no_mangle]
+pub fn load_ref_higher_alignment<'a>(x: &&'a Align16) -> &'a Align16 {
+// CHECK: load {{%Align16|i128}}*, {{%Align16|i128}}** %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META:[0-9]+]], !noundef !{{[0-9]+}}
+    *x
+}
+
+// CHECK-LABEL: @load_scalar_pair
+#[no_mangle]
+pub fn load_scalar_pair<'a>(x: &(&'a i32, &'a Align16)) -> (&'a i32, &'a Align16) {
+// CHECK: load i32*, i32** %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
+// CHECK: load i64*, i64** %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META]], !noundef !{{[0-9]+}}
+    *x
+}
+
+// CHECK-LABEL: @load_raw_pointer
+#[no_mangle]
+pub fn load_raw_pointer<'a>(x: &*const i32) -> *const i32 {
+// loaded raw pointer should not have !nonnull, !align, or !noundef metadata
+// CHECK: load i32*, i32** %x, align [[PTR_ALIGNMENT]]{{$}}
     *x
 }
 
 // CHECK-LABEL: @load_box
 #[no_mangle]
 pub fn load_box<'a>(x: Box<Box<i32>>) -> Box<i32> {
-// Alignment of a box itself is target dependent, so just match any alignment:
-// the main thing we care about here is !nonnull and !noundef.
-// CHECK: load i32*, i32** %x, align {{[0-9]+}}, !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}
+// CHECK: load i32*, i32** %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
     *x
 }
 
@@ -120,5 +146,7 @@ pub fn small_struct_alignment(x: Bytes) -> Bytes {
     x
 }
 
-// CHECK: ![[BOOL_RANGE]] = !{i8 0, i8 2}
-// CHECK: ![[NONZEROU16_RANGE]] = !{i16 1, i16 0}
+// CHECK-DAG: ![[BOOL_RANGE]] = !{i8 0, i8 2}
+// CHECK-DAG: ![[NONZEROU16_RANGE]] = !{i16 1, i16 0}
+// CHECK-DAG: ![[ALIGN_4_META]] = !{i64 4}
+// CHECK-DAG: ![[ALIGN_16_META]] = !{i64 16}
index 2c19cfd8c220127f54212fd66d6a73534fffbb77..4be77e36e760bdf0a160bd2fb7f7fd6582165220 100644 (file)
@@ -29,7 +29,7 @@ pub unsafe fn apple() -> u32 {
     peach()
 }
 
-// target features same as global (not reflected or overriden in IR)
+// target features same as global
 #[no_mangle]
 pub unsafe fn banana() -> u32 {
 // CHECK-LABEL: @banana()
@@ -43,5 +43,5 @@ pub unsafe fn banana() -> u32 {
 // COMPAT-SAME: "target-features"="+avx2,+avx,+avx"
 // INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx"
 // CHECK: attributes [[BANANAATTRS]]
-// CHECK-NOT: target-features
-// CHECK-SAME: }
+// COMPAT-SAME: "target-features"="+avx2,+avx"
+// INCOMPAT-SAME: "target-features"="-avx2,-avx"
index 99576a5f57e90e3246bd9184a250c5c4d8cb2ed6..01f917b291094dcbdff7f00235b9327d4dfee06e 100644 (file)
@@ -63,16 +63,11 @@ pub union UnionU128{a:u128}
 #[no_mangle]
 pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }
 
-pub union UnionU128x2{a:(u128, u128)}
-// CHECK: define void @test_UnionU128x2(i128 %_1.0, i128 %_1.1)
-#[no_mangle]
-pub fn test_UnionU128x2(_: UnionU128x2) { loop {} }
-
 #[repr(C)]
-pub union CUnionU128x2{a:(u128, u128)}
-// CHECK: define void @test_CUnionU128x2(%CUnionU128x2* {{.*}} %_1)
+pub union CUnionU128{a:u128}
+// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %_1)
 #[no_mangle]
-pub fn test_CUnionU128x2(_: CUnionU128x2) { loop {} }
+pub fn test_CUnionU128(_: CUnionU128) { loop {} }
 
 pub union UnionBool { b:bool }
 // CHECK: define noundef zeroext i1 @test_UnionBool(i8 %b)
diff --git a/src/test/rustdoc-gui/source-anchor-scroll.goml b/src/test/rustdoc-gui/source-anchor-scroll.goml
new file mode 100644 (file)
index 0000000..4e51c8d
--- /dev/null
@@ -0,0 +1,20 @@
+// We check that when the anchor changes and is output of the displayed content,
+// the page is scrolled to it.
+goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html
+
+// We reduce the window size to make it easier to make an element "out of the page".
+size: (600, 800)
+// We check that the scroll is at the top first.
+assert-property: ("html", {"scrollTop": "0"})
+
+click: '//a[text() = "barbar"]'
+assert-property: ("html", {"scrollTop": "125"})
+click: '//a[text() = "bar"]'
+assert-property: ("html", {"scrollTop": "166"})
+click: '//a[text() = "sub_fn"]'
+assert-property: ("html", {"scrollTop": "53"})
+
+// We now check that clicking on lines doesn't change the scroll
+// Extra information: the "sub_fn" function header is on line 1.
+click: '//*[@id="6"]'
+assert-property: ("html", {"scrollTop": "53"})
index 375ff4878e5257e1262fe55ebb85953256a19168..ad7080c39b842cc44b7ae0827950634c8b0008f6 100644 (file)
@@ -14,3 +14,6 @@ assert-attribute: (".line-numbers > span:nth-child(6)", {"class": "line-highligh
 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 > code > span", ("y"))
+
+// Assert that the line numbers text is aligned to the right.
+assert-css: (".line-numbers", {"text-align": "right"})
index de9ee66a2bad08acd7ea8c562007f57d72540f54..419a9cceec5f3fe9bb5164d10e34558aacb22778 100644 (file)
@@ -1,6 +1,35 @@
+pub fn sub_fn() {
+    barbar();
+}
+fn barbar() {
+    bar(vec![], vec![], vec![], vec![], Bar { a: "a".into(), b: 0 });
+}
+
 pub struct Bar {
     pub a: String,
     pub b: u32,
 }
 
 pub fn foo(_b: &Bar) {}
+
+// The goal now is to add
+// a lot of lines so
+// that the next content
+// will be out of the screen
+// to allow us to test that
+// if the anchor changes to
+// something outside of the
+// current view, it'll
+// scroll to it as expected.
+
+// More filling content.
+
+pub fn bar(
+  _a: Vec<String>,
+  _b: Vec<String>,
+  _c: Vec<String>,
+  _d: Vec<String>,
+  _e: Bar,
+) {
+    sub_fn();
+}
diff --git a/src/test/rustdoc-json/generic-associated-types/gats.rs b/src/test/rustdoc-json/generic-associated-types/gats.rs
new file mode 100644 (file)
index 0000000..7adcd71
--- /dev/null
@@ -0,0 +1,42 @@
+// ignore-tidy-linelength
+
+#![no_core]
+#![feature(generic_associated_types, lang_items, no_core)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait Display {}
+
+// @has gats.json
+pub trait LendingIterator {
+    // @count - "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*]" 1
+    // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*].name" \"\'a\"
+    // @count - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*]" 1
+    // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.ty.inner" \"Self\"
+    // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
+    // @count - "$.index[*][?(@.name=='LendingItem')].inner.bounds[*]" 1
+    type LendingItem<'a>: Display where Self: 'a;
+
+    // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.kind" \"qualified_path\"
+    // @count - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 1
+    // @count - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
+    // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.self_type.inner" \"Self\"
+    // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.name" \"LendingItem\"
+    fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>;
+}
+
+// @has gats.json
+pub trait Iterator {
+    // @count - "$.index[*][?(@.name=='Item')].inner.generics.params[*]" 0
+    // @count - "$.index[*][?(@.name=='Item')].inner.generics.where_predicates[*]" 0
+    // @count - "$.index[*][?(@.name=='Item')].inner.bounds[*]" 1
+    type Item: Display;
+
+    // @is - "$.index[*][?(@.name=='next')].inner.decl.output.kind" \"qualified_path\"
+    // @count - "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 0
+    // @count - "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
+    // @is - "$.index[*][?(@.name=='next')].inner.decl.output.inner.self_type.inner" \"Self\"
+    // @is - "$.index[*][?(@.name=='next')].inner.decl.output.inner.name" \"Item\"
+    fn next<'a>(&'a self) -> Self::Item;
+}
index 35036a89360e2734b74de01489a9fcfd7953975a..215ee228eb857dfba2f05370de52b9390a767dc8 100644 (file)
@@ -3,5 +3,5 @@
 #![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<const N: usize> where [(); N + 1]: ;'
+//      'pub struct Ice<const N: usize>;'
 pub struct Ice<const N: usize> where [(); N + 1]:;
diff --git a/src/test/rustdoc/generic-associated-types/gats.rs b/src/test/rustdoc/generic-associated-types/gats.rs
new file mode 100644 (file)
index 0000000..ae981b9
--- /dev/null
@@ -0,0 +1,34 @@
+#![crate_name = "foo"]
+#![feature(generic_associated_types)]
+
+// @has foo/trait.LendingIterator.html
+pub trait LendingIterator {
+    // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a"
+    type Item<'a> where Self: 'a;
+
+    // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \
+    //      "fn next<'a>(&'a self) -> Self::Item<'a>"
+    // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]//a[@href="trait.LendingIterator.html#associatedtype.Item"]' \
+    //      "Item"
+    fn next<'a>(&'a self) -> Self::Item<'a>;
+}
+
+// @has foo/trait.LendingIterator.html
+// @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' "type Item<'a> = ()"
+impl LendingIterator for () {
+    type Item<'a> = ();
+
+    fn next<'a>(&self) -> () {}
+}
+
+pub struct Infinite<T>(T);
+
+// @has foo/trait.LendingIterator.html
+// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T"
+impl<T> LendingIterator for Infinite<T> {
+    type Item<'a> where Self: 'a = &'a T;
+
+    fn next<'a>(&'a self) -> Self::Item<'a> {
+        &self.0
+    }
+}
diff --git a/src/test/rustdoc/generic-associated-types/issue-94683.rs b/src/test/rustdoc/generic-associated-types/issue-94683.rs
new file mode 100644 (file)
index 0000000..38ecf52
--- /dev/null
@@ -0,0 +1,13 @@
+#![crate_name = "foo"]
+#![feature(generic_associated_types)]
+
+pub trait Trait {
+    type Gat<'a>;
+}
+
+// Make sure that the elided lifetime shows up
+
+// @has foo/type.T.html
+// @has - "pub type T = "
+// @has - "&lt;'_&gt;"
+pub type T = fn(&<() as Trait>::Gat<'_>);
index 9b70ea054ad754668828393621aadd95fa0e39a3..0b958eb8eac12b450f6b0d32ef13367f112d8fcf 100644 (file)
@@ -57,4 +57,12 @@ impl T2 for S {
     fn ambiguous_method() {}
 }
 
+// @has associated_items/enum.MyEnum.html '//a/@href' 'enum.MyEnum.html#variant.MyVariant'
+/// Link to [MyEnumAlias::MyVariant]
+pub enum MyEnum {
+    MyVariant,
+}
+
+pub type MyEnumAlias = MyEnum;
+
 fn main() {}
diff --git a/src/test/rustdoc/macro-higher-kinded-function.rs b/src/test/rustdoc/macro-higher-kinded-function.rs
new file mode 100644 (file)
index 0000000..02a4305
--- /dev/null
@@ -0,0 +1,21 @@
+#![crate_name = "foo"]
+
+pub struct TyCtxt<'tcx>(&'tcx u8);
+
+macro_rules! gen {
+    ($(($name:ident, $tcx:lifetime, [$k:ty], [$r:ty]))*) => {
+        pub struct Providers {
+            $(pub $name: for<$tcx> fn(TyCtxt<$tcx>, $k) -> $r,)*
+        }
+    }
+}
+
+// @has 'foo/struct.Providers.html'
+// @has - '//*[@class="docblock item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
+// @has - '//*[@class="docblock item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
+// @has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8"
+// @has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16"
+gen! {
+    (a, 'tcx, [u8], [i8])
+    (b, 'tcx, [u16], [i16])
+}
diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs
new file mode 100644 (file)
index 0000000..2adf69f
--- /dev/null
@@ -0,0 +1,60 @@
+// Test that we do not currently display `~const` in rustdoc
+// as that syntax is currently provisional; `~const Drop` has
+// no effect on stable code so it should be hidden as well.
+//
+// To future blessers: make sure that `const_trait_impl` is
+// stabilized when changing `@!has` to `@has`, and please do
+// not remove this test.
+#![feature(const_trait_impl)]
+#![crate_name = "foo"]
+
+pub struct S<T>(T);
+
+// @!has foo/trait.Tr.html '//pre[@class="rust trait"]/code/a[@class="trait"]' '~const'
+// @!has - '//pre[@class="rust trait"]/code/a[@class="trait"]' 'Drop'
+// @has - '//pre[@class="rust trait"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust trait"]/code/span[@class="where"]' '~const'
+// @!has - '//pre[@class="rust trait"]/code/span[@class="where"]' 'Drop'
+// @has - '//pre[@class="rust trait"]/code/span[@class="where"]' ': Clone'
+pub trait Tr<T> {
+    // @!has - '//div[@id="method.a"]/h4[@class="code-header"]' '~const'
+    // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Drop'
+    // @has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
+    // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const'
+    // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' 'Drop'
+    // @has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
+    #[default_method_body_is_const]
+    fn a<A: ~const Drop + ~const Clone>() where Option<A>: ~const Drop + ~const Clone {}
+}
+
+// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]' '~const'
+// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Drop'
+// @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone'
+// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const'
+// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' 'Drop'
+// @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone'
+impl<T: ~const Drop + ~const Clone> const Tr<T> for T where Option<T>: ~const Drop + ~const Clone {
+    fn a<A: ~const Drop + ~const Clone>() where Option<A>: ~const Drop + ~const Clone {}
+}
+
+// @!has foo/fn.foo.html '//pre[@class="rust fn"]/code/a[@class="trait"]' '~const'
+// @!has - '//pre[@class="rust fn"]/code/a[@class="trait"]' 'Drop'
+// @has - '//pre[@class="rust fn"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' '~const'
+// @!has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' 'Drop'
+// @has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' ': Clone'
+pub const fn foo<F: ~const Drop + ~const Clone>() where Option<F>: ~const Drop + ~const Clone {
+    F::a()
+}
+
+impl<T> S<T> {
+    // @!has foo/struct.S.html '//section[@id="method.foo"]/h4[@class="code-header"]' '~const'
+    // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Drop'
+    // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
+    // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const'
+    // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' 'Drop'
+    // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
+    pub const fn foo<B: ~const Drop + ~const Clone>() where B: ~const Drop + ~const Clone {
+        B::a()
+    }
+}
index 36041e4b8efde45b00e22309ba7bf5b721813155..41c9a265cd7bb64dfe1dc951cca96a5b1c374382 100644 (file)
@@ -1,6 +1,6 @@
 // compile-flags:-C panic=abort
 
-#![feature(alloc_error_handler, panic_handler)]
+#![feature(alloc_error_handler)]
 #![no_std]
 #![no_main]
 
index 009f6bce6d38fd9ad72d07d2b2701a8e295aa711..49ea3105fbd7abefa04b15f6d4e19d54b9131eb0 100644 (file)
@@ -1,6 +1,6 @@
 // compile-flags:-C panic=abort
 
-#![feature(alloc_error_handler, panic_handler)]
+#![feature(alloc_error_handler)]
 #![no_std]
 #![no_main]
 
index f2d884b7469706c0dfac1d8299ca76bb67230cda..321fd954db6d0a708392dab311503a6803b33c97 100644 (file)
@@ -1,6 +1,6 @@
 // compile-flags:-C panic=abort
 
-#![feature(alloc_error_handler, panic_handler)]
+#![feature(alloc_error_handler)]
 #![no_std]
 #![no_main]
 
index 5b4293972ea215e592277c85eda2960a289c580a..9c6e810dfce6d859517a0372306aa56d33b4406f 100644 (file)
@@ -4,7 +4,6 @@
 // ignore-wasm32
 
 #![feature(naked_functions)]
-#![feature(or_patterns)]
 #![feature(asm_const, asm_sym, asm_unwind)]
 #![crate_type = "lib"]
 
index c1dcc433db6c6b3ce7bae11fa679cff03d73e348..5520f815f3e5493931eb425f42e7b315869bace6 100644 (file)
@@ -1,35 +1,35 @@
 error: asm with the `pure` option must have at least one output
-  --> $DIR/naked-functions.rs:111:14
+  --> $DIR/naked-functions.rs:110:14
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:21:5
+  --> $DIR/naked-functions.rs:20:5
    |
 LL |     mut a: u32,
    |     ^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:23:5
+  --> $DIR/naked-functions.rs:22:5
    |
 LL |     &b: &i32,
    |     ^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:25:6
+  --> $DIR/naked-functions.rs:24:6
    |
 LL |     (None | Some(_)): Option<std::ptr::NonNull<u8>>,
    |      ^^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:27:5
+  --> $DIR/naked-functions.rs:26:5
    |
 LL |     P { x, y }: P,
    |     ^^^^^^^^^^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:36:5
+  --> $DIR/naked-functions.rs:35:5
    |
 LL |     a + 1
    |     ^
@@ -37,7 +37,7 @@ LL |     a + 1
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:34:1
+  --> $DIR/naked-functions.rs:33:1
    |
 LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
 LL | |
@@ -48,7 +48,7 @@ LL | | }
    | |_^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:42:31
+  --> $DIR/naked-functions.rs:41:31
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                               ^
@@ -56,13 +56,13 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:42:23
+  --> $DIR/naked-functions.rs:41:23
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                       ^^^^^^^^^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:48:1
+  --> $DIR/naked-functions.rs:47:1
    |
 LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
 LL | |
@@ -72,7 +72,7 @@ LL | | }
    | |_^
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:65:10
+  --> $DIR/naked-functions.rs:64:10
    |
 LL |          in(reg) a,
    |          ^^^^^^^^^
@@ -87,7 +87,7 @@ LL |          out(reg) e,
    |          ^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:63:5
+  --> $DIR/naked-functions.rs:62:5
    |
 LL | /     asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
 LL | |
@@ -99,7 +99,7 @@ LL | |     );
    | |_____^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:54:1
+  --> $DIR/naked-functions.rs:53:1
    |
 LL | / pub unsafe extern "C" fn unsupported_operands() {
 LL | |
@@ -119,7 +119,7 @@ LL | | }
    | |_^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:77:1
+  --> $DIR/naked-functions.rs:76:1
    |
 LL | / pub extern "C" fn missing_assembly() {
 LL | |
@@ -127,25 +127,25 @@ LL | | }
    | |_^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:84:5
+  --> $DIR/naked-functions.rs:83:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:86:5
+  --> $DIR/naked-functions.rs:85:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:88:5
+  --> $DIR/naked-functions.rs:87:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:82:1
+  --> $DIR/naked-functions.rs:81:1
    |
 LL | / pub extern "C" fn too_many_asm_blocks() {
 LL | |
@@ -163,7 +163,7 @@ LL | | }
    | |_^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:97:11
+  --> $DIR/naked-functions.rs:96:11
    |
 LL |         *&y
    |           ^
@@ -171,7 +171,7 @@ LL |         *&y
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:95:5
+  --> $DIR/naked-functions.rs:94:5
    |
 LL | /     pub extern "C" fn inner(y: usize) -> usize {
 LL | |
@@ -182,31 +182,31 @@ LL | |     }
    | |_____^
 
 error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
-  --> $DIR/naked-functions.rs:105:5
+  --> $DIR/naked-functions.rs:104:5
    |
 LL |     asm!("", options(nomem, preserves_flags, noreturn));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
-  --> $DIR/naked-functions.rs:111:5
+  --> $DIR/naked-functions.rs:110:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:111:5
+  --> $DIR/naked-functions.rs:110:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm options unsupported in naked functions: `may_unwind`
-  --> $DIR/naked-functions.rs:119:5
+  --> $DIR/naked-functions.rs:118:5
    |
 LL |     asm!("", options(noreturn, may_unwind));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:124:15
+  --> $DIR/naked-functions.rs:123:15
    |
 LL | pub unsafe fn default_abi() {
    |               ^^^^^^^^^^^
@@ -214,43 +214,43 @@ LL | pub unsafe fn default_abi() {
    = note: `#[warn(undefined_naked_function_abi)]` on by default
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:130:15
+  --> $DIR/naked-functions.rs:129:15
    |
 LL | pub unsafe fn rust_abi() {
    |               ^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:170:1
+  --> $DIR/naked-functions.rs:169:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:177:1
+  --> $DIR/naked-functions.rs:176:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:184:1
+  --> $DIR/naked-functions.rs:183:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:191:1
+  --> $DIR/naked-functions.rs:190:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:193:1
+  --> $DIR/naked-functions.rs:192:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:195:1
+  --> $DIR/naked-functions.rs:194:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
index f3024120df1f957a88e29f085f78c03f095945f6..cf5d5d859b6e4c0c52ffb8ba093933538e5037c3 100644 (file)
@@ -1,7 +1,5 @@
 // #29924
 
-#![feature(associated_consts)]
-
 trait Trait {
     const N: usize;
 }
index fc949f24948574619af48ab1e4a0ddd21541bea7..60bbe385c019b3268469e20ae549b52cd2cc50f5 100644 (file)
@@ -1,11 +1,11 @@
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/associated-const-in-trait.rs:9:6
+  --> $DIR/associated-const-in-trait.rs:7:6
    |
 LL | impl dyn Trait {
    |      ^^^^^^^^^ `Trait` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/associated-const-in-trait.rs:6:11
+  --> $DIR/associated-const-in-trait.rs:4:11
    |
 LL | trait Trait {
    |       ----- this trait cannot be made into an object...
index 9e68e9e77515bc6633b0ad3e8a603f98c765d587..162f9e00edd81a369cfe739569cd28af4c81afe1 100644 (file)
@@ -15,9 +15,9 @@ pub trait ThriftService<Bug: NotFoo>:
 {
     fn get_service(
     //~^ ERROR the trait bound `Bug: Foo` is not satisfied
-    //~| ERROR the trait bound `Bug: Foo` is not satisfied
         &self,
     ) -> Self::AssocType;
+    //~^ the trait bound `Bug: Foo` is not satisfied
 }
 
 fn with_factory<H>(factory: dyn ThriftService<()>) {}
index 2f430d3055e1938d3820856af3c291d0988d808a..45d2dfb53757b3347685633aab67c5d4951e5257 100644 (file)
@@ -6,7 +6,7 @@ LL | |
 LL | |
 LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
 ...  |
-LL | |     ) -> Self::AssocType;
+LL | |
 LL | | }
    | |_^ the trait `Foo` is not implemented for `Bug`
    |
@@ -23,7 +23,7 @@ LL | |
 LL | |
 LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
 ...  |
-LL | |     ) -> Self::AssocType;
+LL | |
 LL | | }
    | |_^ the trait `Foo` is not implemented for `Bug`
    |
@@ -37,7 +37,6 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied
    |
 LL | /     fn get_service(
 LL | |
-LL | |
 LL | |         &self,
 LL | |     ) -> Self::AssocType;
    | |_________________________^ the trait `Foo` is not implemented for `Bug`
@@ -48,10 +47,10 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
-  --> $DIR/issue-59324.rs:16:8
+  --> $DIR/issue-59324.rs:19:10
    |
-LL |     fn get_service(
-   |        ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
+LL |     ) -> Self::AssocType;
+   |          ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
    |
 help: consider further restricting this bound
    |
index a1a05c0acba479318c3ef5e540d52028677a42d5..d7f8d7ac546c052884c439298b52ff48e66e413b 100644 (file)
@@ -1,9 +1,5 @@
 // edition:2018
-// compile-flags: --crate-type lib
-
-// FIXME(eholk): temporarily disabled while drop range tracking is disabled
-// (see generator_interior.rs:27)
-// ignore-test
+// compile-flags: --crate-type lib -Zdrop-tracking
 
 use std::{cell::RefCell, fmt::Debug, rc::Rc};
 
diff --git a/src/test/ui/async-await/drop-and-assign.rs b/src/test/ui/async-await/drop-and-assign.rs
new file mode 100644 (file)
index 0000000..fa3f330
--- /dev/null
@@ -0,0 +1,19 @@
+// edition:2021
+// compile-flags: -Zdrop-tracking
+// build-pass
+
+struct A;
+impl Drop for A { fn drop(&mut self) {} }
+
+pub async fn f() {
+    let mut a = A;
+    a = A;
+    drop(a);
+    async {}.await;
+}
+
+fn assert_send<T: Send>(_: T) {}
+
+fn main() {
+    let _ = f();
+}
index 8fb570d67562ab65bac889ef0cd538b902d90674..35f9c581c7b21b254a4add1f516668fa17c24229 100644 (file)
@@ -4,7 +4,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL | async fn foo() {}
    | ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -13,7 +13,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL | fn baz() { async fn foo() {} }
    |            ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -22,7 +22,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL | async fn async_baz() {
    | ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -31,7 +31,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL |     async fn bar() {}
    |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -40,7 +40,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL |     async fn foo() {}
    |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -49,7 +49,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL |     async fn foo() {}
    |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -58,7 +58,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL |         async fn bar() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -67,7 +67,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL |         async fn foo() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
@@ -76,7 +76,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL |             async fn bar() {}
    |             ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0706]: functions in traits cannot be declared `async`
diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await-cargo.rs b/src/test/ui/async-await/suggest-switching-edition-on-await-cargo.rs
new file mode 100644 (file)
index 0000000..4919e0a
--- /dev/null
@@ -0,0 +1,47 @@
+// rustc-env:CARGO=/usr/bin/cargo
+
+use std::pin::Pin;
+use std::future::Future;
+
+fn main() {}
+
+fn await_on_struct_missing() {
+    struct S;
+    let x = S;
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE unknown field
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_struct_similar() {
+    struct S {
+        awai: u8,
+    }
+    let x = S { awai: 42 };
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| HELP a field with a similar name exists
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE unknown field
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_apit(x: impl Future<Output = ()>) {
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await-cargo.stderr b/src/test/ui/async-await/suggest-switching-edition-on-await-cargo.stderr
new file mode 100644 (file)
index 0000000..409eb17
--- /dev/null
@@ -0,0 +1,43 @@
+error[E0609]: no field `await` on type `await_on_struct_missing::S`
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7
+   |
+LL |     x.await;
+   |       ^^^^^ unknown field
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
+   = help: set `edition = "2021"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `await_on_struct_similar::S`
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7
+   |
+LL |     x.await;
+   |       ^^^^^ help: a field with a similar name exists: `awai`
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
+   = help: set `edition = "2021"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:33:7
+   |
+LL |     x.await;
+   |       ^^^^^ unknown field
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
+   = help: set `edition = "2021"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `impl Future<Output = ()>`
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:42:7
+   |
+LL |     x.await;
+   |       ^^^^^
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018 or later
+   = help: set `edition = "2021"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
index f2e0fb19c631d366d6cfeee44abccb81ecc701a8..9852e8fc918fe61e2647c48e25a747444c73bd35 100644 (file)
@@ -10,7 +10,7 @@ fn await_on_struct_missing() {
     //~^ ERROR no field `await` on type
     //~| NOTE unknown field
     //~| NOTE to `.await` a `Future`, switch to Rust 2018
-    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| HELP pass `--edition 2021` to `rustc`
     //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
 }
 
@@ -23,7 +23,7 @@ struct S {
     //~^ ERROR no field `await` on type
     //~| HELP a field with a similar name exists
     //~| NOTE to `.await` a `Future`, switch to Rust 2018
-    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| HELP pass `--edition 2021` to `rustc`
     //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
 }
 
@@ -32,7 +32,7 @@ fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
     //~^ ERROR no field `await` on type
     //~| NOTE unknown field
     //~| NOTE to `.await` a `Future`, switch to Rust 2018
-    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| HELP pass `--edition 2021` to `rustc`
     //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
 }
 
@@ -40,6 +40,6 @@ fn await_on_apit(x: impl Future<Output = ()>) {
     x.await;
     //~^ ERROR no field `await` on type
     //~| NOTE to `.await` a `Future`, switch to Rust 2018
-    //~| HELP set `edition = "2021"` in `Cargo.toml`
+    //~| HELP pass `--edition 2021` to `rustc`
     //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
 }
index b38c897fc7447aa8ff1866596907ec87d7e48b54..ef3334381b71524e051480a56a2a212c854caa81 100644 (file)
@@ -5,7 +5,7 @@ LL |     x.await;
    |       ^^^^^ unknown field
    |
    = note: to `.await` a `Future`, switch to Rust 2018 or later
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0609]: no field `await` on type `await_on_struct_similar::S`
@@ -15,7 +15,7 @@ LL |     x.await;
    |       ^^^^^ help: a field with a similar name exists: `awai`
    |
    = note: to `.await` a `Future`, switch to Rust 2018 or later
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
@@ -25,7 +25,7 @@ LL |     x.await;
    |       ^^^^^ unknown field
    |
    = note: to `.await` a `Future`, switch to Rust 2018 or later
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0609]: no field `await` on type `impl Future<Output = ()>`
@@ -35,7 +35,7 @@ LL |     x.await;
    |       ^^^^^
    |
    = note: to `.await` a `Future`, switch to Rust 2018 or later
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error: aborting due to 4 previous errors
index c520a07abc17267aed29eca5c119a3fb7c315d24..afaaed2ef6e4e8473a5e77f3b5770642808b68b9 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(try_trait, async_closure)]
+#![feature(async_closure)]
 // edition:2018
 fn main() {}
 
index 187356ca140219c079835955146e2ecb567b6fec..6d6d80614910403afb7e5d2816d21c72eca30d14 100644 (file)
@@ -2,10 +2,7 @@
 // Error message should pinpoint the type parameter T as needing to be bound
 // (rather than give a general error message)
 // edition:2018
-
-// FIXME(eholk): temporarily disabled while drop range tracking is disabled
-// (see generator_interior.rs:27)
-// ignore-test
+// compile-flags: -Zdrop-tracking
 
 async fn bar<T>() -> () {}
 
index d19a3226ef9a44c71a47d82bafbee82411f09bc3..7236c681f341cef1080752841952136c960f3472 100644 (file)
@@ -1,35 +1,35 @@
 error[E0698]: type inside `async fn` body must be known in this context
-  --> $DIR/unresolved_type_param.rs:9:5
+  --> $DIR/unresolved_type_param.rs:10:5
    |
 LL |     bar().await;
    |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
    |
 note: the type is part of the `async fn` body because of this `await`
-  --> $DIR/unresolved_type_param.rs:9:10
+  --> $DIR/unresolved_type_param.rs:10:10
    |
 LL |     bar().await;
    |          ^^^^^^
 
 error[E0698]: type inside `async fn` body must be known in this context
-  --> $DIR/unresolved_type_param.rs:9:5
+  --> $DIR/unresolved_type_param.rs:10:5
    |
 LL |     bar().await;
    |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
    |
 note: the type is part of the `async fn` body because of this `await`
-  --> $DIR/unresolved_type_param.rs:9:10
+  --> $DIR/unresolved_type_param.rs:10:10
    |
 LL |     bar().await;
    |          ^^^^^^
 
 error[E0698]: type inside `async fn` body must be known in this context
-  --> $DIR/unresolved_type_param.rs:9:5
+  --> $DIR/unresolved_type_param.rs:10:5
    |
 LL |     bar().await;
    |     ^^^ cannot infer type for type parameter `T` declared on the function `bar`
    |
 note: the type is part of the `async fn` body because of this `await`
-  --> $DIR/unresolved_type_param.rs:9:10
+  --> $DIR/unresolved_type_param.rs:10:10
    |
 LL |     bar().await;
    |          ^^^^^^
index 3fc60f7ce48c2154c686a218e960411ffded2267..412af195d7a19284976efe3a2089e0dd08308802 100644 (file)
@@ -1,3 +1,6 @@
+#![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
 #[rustc_const_stable(feature = "foo", since = "0")]
 //~^ ERROR macros cannot have const stability attributes
 macro_rules! foo {
index ef24e44d1908bd19e48cb88e0e84daf67791e948..c3da02c79cb53393e87d6b8abd828979db56de7e 100644 (file)
@@ -1,5 +1,5 @@
 error: macros cannot have const stability attributes
-  --> $DIR/const-stability-on-macro.rs:1:1
+  --> $DIR/const-stability-on-macro.rs:4:1
    |
 LL | #[rustc_const_stable(feature = "foo", since = "0")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
@@ -8,7 +8,7 @@ LL | macro_rules! foo {
    | ---------------- const stability attribute affects this macro
 
 error: macros cannot have const stability attributes
-  --> $DIR/const-stability-on-macro.rs:7:1
+  --> $DIR/const-stability-on-macro.rs:10:1
    |
 LL | #[rustc_const_unstable(feature = "bar", issue="none")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute
index f5f75f9f4dac5dbf9e62307de61b8d792f204641..492f84f56c3a0e2eda981165c47dbd43e8b53af4 100644 (file)
@@ -1,6 +1,5 @@
 // normalize-stderr-test: "couldn't read.*" -> "couldn't read the file"
 
-#![feature(extended_key_value_attributes)]
 #![doc = include_str!("../not_existing_file.md")]
 struct Documented {}
 //~^^ ERROR couldn't read
index e4deeacd0ff605f676e406681bac632f19f5e05f..0fcde9b7cc69f1469bda36f93a13e0d4141bf396 100644 (file)
@@ -1,5 +1,5 @@
 error: couldn't read the file
-  --> $DIR/extented-attribute-macro-error.rs:4:10
+  --> $DIR/extented-attribute-macro-error.rs:3:10
    |
 LL | #![doc = include_str!("../not_existing_file.md")]
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 76708ea98305f2ee9637ecb7bfcefca78dbfe11a..0f62d4153089a6c6a478ee032f04b5d861f87014 100644 (file)
@@ -1,9 +1,9 @@
 #![u=||{static d=||1;}]
 //~^ unexpected token
 //~| cannot find attribute `u` in this scope
-//~| `main` function not found in crate `issue_90873`
 //~| missing type for `static` item
 
 #![a={impl std::ops::Neg for i8 {}}]
 //~^ ERROR unexpected token
 //~| ERROR cannot find attribute `a` in this scope
+//~| ERROR `main` function not found in crate `issue_90873`
index 2718b65108cdd24c9d4a940e5928ead26ceddf85..fbdc05ef6f0044b1b2f2799961922792ea58b2b0 100644 (file)
@@ -10,7 +10,7 @@ LL | #![u=||{static d=||1;}]
 error: unexpected token: `{
            impl std::ops::Neg for i8 {}
        }`
-  --> $DIR/issue-90873.rs:7:6
+  --> $DIR/issue-90873.rs:6:6
    |
 LL | #![a={impl std::ops::Neg for i8 {}}]
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,22 +22,16 @@ LL | #![u=||{static d=||1;}]
    |    ^
 
 error: cannot find attribute `a` in this scope
-  --> $DIR/issue-90873.rs:7:4
+  --> $DIR/issue-90873.rs:6:4
    |
 LL | #![a={impl std::ops::Neg for i8 {}}]
    |    ^
 
 error[E0601]: `main` function not found in crate `issue_90873`
-  --> $DIR/issue-90873.rs:1:1
+  --> $DIR/issue-90873.rs:6:37
    |
-LL | / #![u=||{static d=||1;}]
-LL | |
-LL | |
-LL | |
-LL | |
-LL | |
-LL | | #![a={impl std::ops::Neg for i8 {}}]
-   | |____________________________________^ consider adding a `main` function to `$DIR/issue-90873.rs`
+LL | #![a={impl std::ops::Neg for i8 {}}]
+   |                                     ^ consider adding a `main` function to `$DIR/issue-90873.rs`
 
 error: missing type for `static` item
   --> $DIR/issue-90873.rs:1:16
diff --git a/src/test/ui/borrowck/copy-suggestion-region-vid.rs b/src/test/ui/borrowck/copy-suggestion-region-vid.rs
new file mode 100644 (file)
index 0000000..dff9528
--- /dev/null
@@ -0,0 +1,17 @@
+pub struct DataStruct();
+
+pub struct HelperStruct<'n> {
+    pub helpers: [Vec<&'n i64>; 2],
+    pub is_empty: bool,
+}
+
+impl DataStruct {
+    pub fn f(&self) -> HelperStruct {
+        let helpers = [vec![], vec![]];
+
+        HelperStruct { helpers, is_empty: helpers[0].is_empty() }
+        //~^ ERROR borrow of moved value
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/copy-suggestion-region-vid.stderr b/src/test/ui/borrowck/copy-suggestion-region-vid.stderr
new file mode 100644 (file)
index 0000000..f03cdd8
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `helpers`
+  --> $DIR/copy-suggestion-region-vid.rs:12:43
+   |
+LL |         let helpers = [vec![], vec![]];
+   |             ------- move occurs because `helpers` has type `[Vec<&i64>; 2]`, which does not implement the `Copy` trait
+LL | 
+LL |         HelperStruct { helpers, is_empty: helpers[0].is_empty() }
+   |                        -------            ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
+   |                        |
+   |                        value moved here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
index db348a50aa4298fe7690f74d0e943781f9d056dd..632f8dc3ad6f5dfe7c6dfe9a5a84b8e503a3c593 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_fn_trait_bound)]
 // Regression test related to issue 88434
 
 const _CONST: &() = &f(&|_| {});
index 845e1bdba8fc03fce5a3545390c32aec0621bcd1..d9635e1ee464ce514a16bd858292bcae3311dcc9 100644 (file)
@@ -1,14 +1,14 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-88434-minimal-example.rs:10:5
+  --> $DIR/issue-88434-minimal-example.rs:9:5
    |
 LL | const _CONST: &() = &f(&|_| {});
-   |                      ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:4:22
+   |                      ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
 ...
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
-   |     inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:4:25: 4:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:9:5
+   |     inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 4db073c66b1f368fb601a5d27132dd2bfd0b78c2..f0a6dcd4eb3b885a0b4eee555690ae1514590204 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_fn_trait_bound)]
 // Regression test for issue 88434
 
 const _CONST: &[u8] = &f(&[], |_| {});
index 8cbb6a6340c7f5b8641e65c4c1f62e41aaa14fce..44e244ae9cc3f9463736309c86628794d8eecbfb 100644 (file)
@@ -1,14 +1,14 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:9:5
    |
 LL | const _CONST: &[u8] = &f(&[], |_| {});
-   |                        -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:4:24
+   |                        -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
 ...
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
-   |     inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:9:5
+   |     inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 38ef9e51c7a1f58f4f19d094d875b8a30fb9358d..9bda42e5d15fe703fe68d26872b51d8f1e624ce2 100644 (file)
@@ -1,6 +1,10 @@
-// Check that a an empty values() is rejected
+// Check warning for unexpected cfg value
 //
-// check-fail
+// check-pass
 // compile-flags: --check-cfg=values() -Z unstable-options
 
+#[cfg(test = "value")]
+//~^ WARNING unexpected `cfg` condition value
+pub fn f() {}
+
 fn main() {}
index 106d5b7b47f9bec61c11562793d3723c597a3c68..10dab50348954e8c94e7b7572587641e33a027ec 100644 (file)
@@ -1,2 +1,13 @@
-error: invalid `--check-cfg` argument: `values()` (expected `names(name1, name2, ... nameN)` or `values(name, "value1", "value2", ... "valueN")`)
+warning: unexpected `cfg` condition value
+  --> $DIR/empty-values.rs:6:7
+   |
+LL | #[cfg(test = "value")]
+   |       ^^^^----------
+   |           |
+   |           help: remove the value
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: no expected value for `test`
+
+warning: 1 warning emitted
 
index 2440757e52da994e1c516c3b434b8c212310105a..8c80f56cb5a30e8a1f12e4dbc2106090c55e4795 100644 (file)
@@ -1,10 +1,14 @@
 // Check that we detect unexpected value when none are allowed
 //
 // check-pass
-// compile-flags: --check-cfg=values(feature) -Z unstable-options
+// compile-flags: --check-cfg=values(test) --check-cfg=values(feature) -Z unstable-options
 
 #[cfg(feature = "foo")]
 //~^ WARNING unexpected `cfg` condition value
 fn do_foo() {}
 
+#[cfg(test = "foo")]
+//~^ WARNING unexpected `cfg` condition value
+fn do_foo() {}
+
 fn main() {}
index ea1c9107d4c2ffb1137e5c67411c7c4ce90f3334..7025b4cd7bae6921941d77052f423e0fde465a1b 100644 (file)
@@ -7,5 +7,15 @@ LL | #[cfg(feature = "foo")]
    = note: `#[warn(unexpected_cfgs)]` on by default
    = note: no expected value for `feature`
 
-warning: 1 warning emitted
+warning: unexpected `cfg` condition value
+  --> $DIR/no-values.rs:10:7
+   |
+LL | #[cfg(test = "foo")]
+   |       ^^^^--------
+   |           |
+   |           help: remove the value
+   |
+   = note: no expected value for `test`
+
+warning: 2 warnings emitted
 
diff --git a/src/test/ui/check-cfg/stmt-no-ice.rs b/src/test/ui/check-cfg/stmt-no-ice.rs
new file mode 100644 (file)
index 0000000..cf76487
--- /dev/null
@@ -0,0 +1,10 @@
+// This test checks that there is no ICE with this code
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+fn main() {
+    #[cfg(crossbeam_loom)]
+    //~^ WARNING unexpected `cfg` condition name
+    {}
+}
diff --git a/src/test/ui/check-cfg/stmt-no-ice.stderr b/src/test/ui/check-cfg/stmt-no-ice.stderr
new file mode 100644 (file)
index 0000000..da65b59
--- /dev/null
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+  --> $DIR/stmt-no-ice.rs:7:11
+   |
+LL |     #[cfg(crossbeam_loom)]
+   |           ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/check-cfg/well-known-values.rs b/src/test/ui/check-cfg/well-known-values.rs
new file mode 100644 (file)
index 0000000..46004be
--- /dev/null
@@ -0,0 +1,28 @@
+// This test check that we lint on non well known values and that we don't lint on well known
+// values
+//
+// check-pass
+// compile-flags: --check-cfg=values() -Z unstable-options
+
+#[cfg(target_os = "linuz")]
+//~^ WARNING unexpected `cfg` condition value
+fn target_os_linux_misspell() {}
+
+#[cfg(target_os = "linux")]
+fn target_os_linux() {}
+
+#[cfg(target_has_atomic = "0")]
+//~^ WARNING unexpected `cfg` condition value
+fn target_has_atomic_invalid() {}
+
+#[cfg(target_has_atomic = "8")]
+fn target_has_atomic() {}
+
+#[cfg(unix = "aa")]
+//~^ WARNING unexpected `cfg` condition value
+fn unix_with_value() {}
+
+#[cfg(unix)]
+fn unix() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr
new file mode 100644 (file)
index 0000000..8eefd6a
--- /dev/null
@@ -0,0 +1,33 @@
+warning: unexpected `cfg` condition value
+  --> $DIR/well-known-values.rs:7:7
+   |
+LL | #[cfg(target_os = "linuz")]
+   |       ^^^^^^^^^^^^-------
+   |                   |
+   |                   help: did you mean: `"linux"`
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, windows
+
+warning: unexpected `cfg` condition value
+  --> $DIR/well-known-values.rs:14:7
+   |
+LL | #[cfg(target_has_atomic = "0")]
+   |       ^^^^^^^^^^^^^^^^^^^^---
+   |                           |
+   |                           help: did you mean: `"8"`
+   |
+   = note: expected values for `target_has_atomic` are: 128, 16, 32, 64, 8, ptr
+
+warning: unexpected `cfg` condition value
+  --> $DIR/well-known-values.rs:21:7
+   |
+LL | #[cfg(unix = "aa")]
+   |       ^^^^-------
+   |           |
+   |           help: remove the value
+   |
+   = note: no expected value for `unix`
+
+warning: 3 warnings emitted
+
index f02d23464f168284574dd689d4cfc2666463250b..7e22defa98dd460e43b091b5b56af30f090b7981 100644 (file)
@@ -1,26 +1,38 @@
 error[E0004]: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered
   --> $DIR/issue-88331.rs:11:20
    |
-LL | pub struct Opcode(pub u8);
-   | -------------------------- `Opcode` defined here
-...
 LL |     move |i| match msg_type {
    |                    ^^^^^^^^ patterns `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Opcode` defined here
+  --> $DIR/issue-88331.rs:4:12
+   |
+LL | pub struct Opcode(pub u8);
+   |            ^^^^^^
    = note: the matched value is of type `Opcode`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         Opcode::OP1 => unimplemented!(),
+LL ~         Opcode(0_u8) | Opcode(2_u8..=u8::MAX) => todo!(),
+   |
 
 error[E0004]: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered
   --> $DIR/issue-88331.rs:27:20
    |
-LL | pub struct Opcode2(Opcode);
-   | --------------------------- `Opcode2` defined here
-...
 LL |     move |i| match msg_type {
    |                    ^^^^^^^^ patterns `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Opcode2` defined here
+  --> $DIR/issue-88331.rs:18:12
+   |
+LL | pub struct Opcode2(Opcode);
+   |            ^^^^^^^
    = note: the matched value is of type `Opcode2`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         Opcode2::OP2=> unimplemented!(),
+LL ~         Opcode2(Opcode(0_u8)) | Opcode2(Opcode(2_u8..=u8::MAX)) => todo!(),
+   |
 
 error: aborting due to 2 previous errors
 
index 91ffe1a47f4134f460d65cb6e933cee0f6a2ea09..32d36274ff6ef7aed9b85878e020c4f044814e21 100644 (file)
@@ -1,17 +1,19 @@
 error[E0004]: non-exhaustive patterns: `B` not covered
   --> $DIR/non-exhaustive-match.rs:26:25
    |
-LL | enum L1 { A, B }
-   | ----------------
-   | |            |
-   | |            not covered
-   | `L1` defined here
-...
 LL |     let _b = || { match l1 { L1::A => () } };
    |                         ^^ pattern `B` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `L1` defined here
+  --> $DIR/non-exhaustive-match.rs:12:14
+   |
+LL | enum L1 { A, B }
+   |      --      ^ not covered
    = note: the matched value is of type `L1`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL |     let _b = || { match l1 { L1::A => (), B => todo!() } };
+   |                                         ++++++++++++++
 
 error[E0004]: non-exhaustive patterns: type `E1` is non-empty
   --> $DIR/non-exhaustive-match.rs:37:25
@@ -19,8 +21,18 @@ error[E0004]: non-exhaustive patterns: type `E1` is non-empty
 LL |     let _d = || { match e1 {} };
    |                         ^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `E1` defined here
+  --> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1
+   |
+LL | pub enum E1 {}
+   | ^^^^^^^^^^^^^^
    = note: the matched value is of type `E1`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     let _d = || { match e1 {
+LL +         _ => todo!(),
+LL ~     } };
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/non-exhaustive-match.rs:39:25
@@ -28,8 +40,16 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     let _e = || { match e2 { E2::A => (), E2::B => () } };
    |                         ^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `E2` defined here
+  --> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1
+   |
+LL | pub enum E2 { A, B }
+   | ^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `E2`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL |     let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } };
+   |                                                      ++++++++++++++
 
 error[E0505]: cannot move out of `e3` because it is borrowed
   --> $DIR/non-exhaustive-match.rs:46:22
index 45641ea3de3e0812b30da2653a18bdf037830530..e55fb7ce4bbe9528a70b259251de935fda539d20 100644 (file)
@@ -4,8 +4,13 @@ error[E0004]: non-exhaustive patterns: type `u8` is non-empty
 LL |     let c1 = || match x { };
    |                       ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     let c1 = || match x {
+LL +         _ => todo!(),
+LL ~     };
+   |
 
 error[E0381]: use of possibly-uninitialized variable: `x`
   --> $DIR/pattern-matching-should-fail.rs:8:23
index e9df780def5dfa0e9dc018e98f0713f3d0a5bd0d..d61872c48ea96c2187e943f4956500123c019c09 100644 (file)
@@ -1,9 +1,8 @@
 error[E0601]: `main` function not found in crate `cfg_attr_cfg_2`
-  --> $DIR/cfg-attr-cfg-2.rs:8:1
+  --> $DIR/cfg-attr-cfg-2.rs:9:14
    |
-LL | / #[cfg_attr(foo, cfg(bar))]
-LL | | fn main() { }
-   | |_____________^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
+LL | fn main() { }
+   |              ^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
 
 error: aborting due to previous error
 
index 0b5c3e0335586d65a94a5199b9596b76830eb919..ff72c43efbd086f343d8a41396f6a93c654066ea 100644 (file)
@@ -1,8 +1,8 @@
 error[E0601]: `main` function not found in crate `cfg_in_crate_1`
-  --> $DIR/cfg-in-crate-1.rs:3:1
+  --> $DIR/cfg-in-crate-1.rs:3:13
    |
 LL | #![cfg(bar)]
-   | ^^^^^^^^^^^^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
+   |             ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
 
 error: aborting due to previous error
 
index 771e68b0db58a0c049309d42b14b5163b817650d..e86ffbf10757e6154f9326c5cfba2aee8cf706e1 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_fn_trait_bound, generic_const_exprs)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 trait _Contains<T> {
index 2f196533dd88c931c131d9696c149a68ec14363b..ff141d328e6272b78a41cc26b65c900cf8cf931f 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_fn_trait_bound, generic_const_exprs)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 trait MiniTypeId {
index a3a0d8d06e87cb5de00620a2dd22d490769b1ba5..3539e9b966c86b06da23d2f8510817089b5ff72d 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(generic_const_exprs, array_map)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 pub struct ConstCheck<const CHECK: bool>;
index bf0b01a2ecfe0d89ed0005dc4af6ccb963a7df1a..88cea60e1b89e133344e14745939745f437166a0 100644 (file)
@@ -1,6 +1,5 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
-#![feature(const_fn_fn_ptr_basics)]
 #![crate_type="rlib"]
 
 pub const fn foo() -> usize { 22 }
index 2f5661e32a90e37dde994653e5b6472649e4e423..9332cbbd4d7c9fc2745dee0823c704687a1a3f47 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(const_indexing)]
-
 const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
 const IDX: usize = 3;
 const VAL: i32 = ARR[IDX];
index eae93b72ddc86e5eeba5babac1fa2613add73fac..f7a55d3ca72104be415e681c50abfc23218c2ed9 100644 (file)
@@ -1,11 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/const-array-oob-arith.rs:7:45
+  --> $DIR/const-array-oob-arith.rs:5:45
    |
 LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
    |                                             ^^^ expected an array with a fixed size of 2 elements, found one with 1 element
 
 error[E0308]: mismatched types
-  --> $DIR/const-array-oob-arith.rs:10:44
+  --> $DIR/const-array-oob-arith.rs:8:44
    |
 LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
    |                                            ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements
index eca2fe18ab96acd8ac756fc30cc7da94b42fe4b2..c747ab50c16b8237a4728e955f8c299bd7664fd3 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(const_indexing)]
-
 const FOO: [usize; 3] = [1, 2, 3];
 const BAR: usize = FOO[5]; // no error, because the error below occurs before regular const eval
 
index 1aa3e88e5209702f4a60896c7df402d38523231c..f1c5f58af47d3521622465b3e0121ddee10aa7d8 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-array-oob.rs:6:19
+  --> $DIR/const-array-oob.rs:4:19
    |
 LL | const BLUB: [u32; FOO[4]] = [5, 6];
    |                   ^^^^^^ index out of bounds: the length is 3 but the index is 4
index f3c82c5f96816280de4c0de4e239561b3f5c9bdf..1ccd0ee937067755115a138694e96246ff4ba31d 100644 (file)
@@ -1,5 +1,5 @@
 #![allow(unused)]
-#![feature(const_fn_trait_bound, const_trait_impl, inline_const, negative_impls)]
+#![feature(const_trait_impl, inline_const, negative_impls)]
 
 const fn f<T: ~const Drop>(x: T) {}
 
index a16ac7b2a24ee9d1e740020fb85f68f96adbb1b3..ca1585f883759914e1eaed0887a109364d94c9b3 100644 (file)
@@ -10,23 +10,11 @@ help: skipping check that does not even have a feature gate
    |
 LL |     X_CONST(x)
    |     ^^^^^^^^^^
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/const_fn_ptr.rs:18:14
-   |
-LL | const fn foo(x: fn(usize) -> usize, y: usize)  -> usize {
-   |              ^
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/const_fn_ptr.rs:19:5
-   |
-LL |     x(y)
-   |     ^
 help: skipping check that does not even have a feature gate
   --> $DIR/const_fn_ptr.rs:19:5
    |
 LL |     x(y)
    |     ^^^^
 
-error: `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
-
-error: aborting due to previous error; 1 warning emitted
+warning: 1 warning emitted
 
index 4f7a771f4184f8d50555f5476b9ae06d11dfdcaa..c17166263ba09ddaa34f9de7f07f7e8dc8940bba 100644 (file)
@@ -12,16 +12,6 @@ LL |     assert_eq!(Z, 4);
 
 warning: skipping const checks
    |
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/const_fn_ptr_fail2.rs:11:14
-   |
-LL | const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
-   |              ^
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/const_fn_ptr_fail2.rs:12:5
-   |
-LL |     x(y)
-   |     ^
 help: skipping check that does not even have a feature gate
   --> $DIR/const_fn_ptr_fail2.rs:12:5
    |
index 80f6bbec2a181f04d6146376b12e96c246ee72a8..917777a32fff3118a842763679d5abe2f2b49581 100644 (file)
@@ -1,7 +1,5 @@
 // issue-49296: Unsafe shenigans in constants can result in missing errors
 
-#![feature(const_fn_trait_bound)]
-
 use std::mem::transmute;
 
 const fn wat(x: u64) -> &'static u64 {
index bc3074b10bee6f326c048121d07b093515e63e46..1864a284579109c3b4a6960414e7ae97f550fad4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-49296.rs:11:16
+  --> $DIR/issue-49296.rs:9:16
    |
 LL | const X: u64 = *wat(42);
    |                ^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed
index bf8bae5ea2c73609d5359a9b35ac19220d15e296..abd1d32abe28904fa78350c91b133d828e9828c5 100644 (file)
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(const_fn_fn_ptr_basics)]
 
 const fn nested(x: (for<'a> fn(&'a ()), String)) -> (fn(&'static ()), String) {
     x
index 8bd1b341e6e1256460947d47c01523d1438aae8c..1f0240d4b5ac7e90ba13665c60b017d790344f99 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(const_transmute)]
-
 use std::mem;
 
 fn main() {
index 5aae8c12d16ecd827548fde1eb6b8da8382fcc0d..15b9b56ea66066c540491774ce3366bf7286df0c 100644 (file)
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/transmute-const-promotion.rs:6:37
+  --> $DIR/transmute-const-promotion.rs:4:37
    |
 LL |     let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
    |            ------------             ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
index 46748673067cebb02e795c78449a413186722521..c7078e46fa64fc21d694d602ad988df91cc790c0 100644 (file)
@@ -2,8 +2,6 @@
 
 const extern "C" fn unsize(x: &[u8; 3]) -> &[u8] { x }
 const unsafe extern "C" fn closure() -> fn() { || {} }
-//~^ ERROR function pointer
-//~| ERROR function pointer cast
 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; }
index 2b2d23477f681365370ce6589eb79005dda28b51..4bab466fb95a7e7b5892a4884a4cede9345c5256 100644 (file)
@@ -1,23 +1,5 @@
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/const-extern-fn-min-const-fn.rs:4:41
-   |
-LL | const unsafe extern "C" fn closure() -> fn() { || {} }
-   |                                         ^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/const-extern-fn-min-const-fn.rs:4:48
-   |
-LL | const unsafe extern "C" fn closure() -> fn() { || {} }
-   |                                                ^^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
 error[E0658]: floating point arithmetic is not allowed in constant functions
-  --> $DIR/const-extern-fn-min-const-fn.rs:7:42
+  --> $DIR/const-extern-fn-min-const-fn.rs:5:42
    |
 LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
    |                                          ^^^^^^^^^
@@ -26,7 +8,7 @@ LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
    = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
 
 error: pointers cannot be cast to integers during const eval
-  --> $DIR/const-extern-fn-min-const-fn.rs:9:48
+  --> $DIR/const-extern-fn-min-const-fn.rs:7:48
    |
 LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
    |                                                ^^^^^^^^^^^^
@@ -34,6 +16,6 @@ LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
    = note: at compile-time, pointers do not have an integer value
    = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index 1928c51885efff2d97205da720e57fad152097b1..59680e6e4a8e370ff23fa866a6306d85ce9fb81c 100644 (file)
@@ -4,7 +4,6 @@
 // A very basic test of const fn functionality.
 
 #![feature(const_indexing)]
-#![feature(const_fn_trait_bound)]
 
 const fn add(x: u32, y: u32) -> u32 {
     x + y
diff --git a/src/test/ui/consts/const_fn_trait_bound.gated.stderr b/src/test/ui/consts/const_fn_trait_bound.gated.stderr
deleted file mode 100644 (file)
index ded05cb..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/const_fn_trait_bound.rs:17:1
-   |
-LL | fn main() {}
-   | ^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/consts/const_fn_trait_bound.rs b/src/test/ui/consts/const_fn_trait_bound.rs
deleted file mode 100644 (file)
index 19c08b6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// gate-test-const_fn_trait_bound
-
-// revisions: stock gated
-
-#![feature(rustc_attrs)]
-#![cfg_attr(gated, feature(const_fn_trait_bound))]
-
-const fn test1<T: std::ops::Add>() {}
-//[stock]~^ trait bounds
-const fn test2(_x: &dyn Send) {}
-//[stock]~^ trait objects in const fn are unstable
-const fn test3() -> &'static dyn Send { loop {} }
-//[stock]~^ trait objects in const fn are unstable
-
-
-#[rustc_error]
-fn main() {} //[gated]~ fatal error triggered by #[rustc_error]
diff --git a/src/test/ui/consts/const_fn_trait_bound.stock.stderr b/src/test/ui/consts/const_fn_trait_bound.stock.stderr
deleted file mode 100644 (file)
index 7d9e18c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/const_fn_trait_bound.rs:8:16
-   |
-LL | const fn test1<T: std::ops::Add>() {}
-   |                ^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/const_fn_trait_bound.rs:10:16
-   |
-LL | const fn test2(_x: &dyn Send) {}
-   |                ^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/const_fn_trait_bound.rs:12:21
-   |
-LL | const fn test3() -> &'static dyn Send { loop {} }
-   |                     ^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 35b63bddca252937d815454a2a67733e42ea658b..4d00ac7fd0d59d23c256bbfd98a3ba9881f38bb9 100644 (file)
@@ -1,6 +1,8 @@
+// check-pass
+
 const fn x() {
     let t = true;
-    let x = || t; //~ ERROR function pointer
+    let x = || t;
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/issue-37550-1.stderr b/src/test/ui/consts/issue-37550-1.stderr
deleted file mode 100644 (file)
index f66d706..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/issue-37550-1.rs:3:9
-   |
-LL |     let x = || t;
-   |         ^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
index 15877c53747ec0a3171a7ee2159d069ffcdfdf4c..724eb28291ebc82b9f5ae650379a52e65c953eda 100644 (file)
@@ -2,8 +2,6 @@
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
-#![feature(const_fn_fn_ptr_basics)]
-
 const fn x() {
     let t = true;
     let x = || t;
index 0a1e835672de9db26f312254c9c7e608db2d126f..9438df1937bddecc20d7ac7edecb8a4867787205 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(const_fn_fn_ptr_basics)]
 #![deny(const_err)]
 
 pub struct Data<T> {
index 9c673d20b2a9565549532cd4ac1df0d0cab8cfba..22ac75514f62466611582baec0b931ee6bd2c2b9 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(const_fn_fn_ptr_basics)]
-
 const fn foo() { (||{})() }
 //~^ ERROR cannot call non-const closure
 
index 62a7c7db6b83ae0311894706e2ec70bcb2f69f3a..803424eedf32a18ed77393baf85f2db02d08dce7 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/issue-56164.rs:3:18
+  --> $DIR/issue-56164.rs:1:18
    |
 LL | const fn foo() { (||{})() }
    |                  ^^^^^^^^
@@ -8,7 +8,7 @@ LL | const fn foo() { (||{})() }
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
 error: function pointers are not allowed in const fn
-  --> $DIR/issue-56164.rs:7:5
+  --> $DIR/issue-56164.rs:5:5
    |
 LL |     input()
    |     ^^^^^^^
index 1f147439f8bc37e0853433fa932b5ddd59e168fb..4b8f9f536413693ddbf362b0f1ae503f234c3a7d 100644 (file)
@@ -2,7 +2,6 @@
 
 #![crate_type="lib"]
 #![allow(unreachable_patterns)]
-#![feature(const_fn_union)]
 
 #[derive(PartialEq, Eq)]
 #[repr(transparent)]
index 5da7a9e2390007ab077636c8e70a45d340a502d6..d0dbb21cee0120695393de4cf2ac58d831d71561 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot use unsized non-slice type `Username` in constant patterns
-  --> $DIR/issue-87046.rs:29:13
+  --> $DIR/issue-87046.rs:28:13
    |
 LL |             ROOT_USER => true,
    |             ^^^^^^^^^
index a2d4a642128b4f9471b8fe3c46a31b448f5f7c63..1c38c43e6c0c51292592f592818580a3af00c81c 100644 (file)
@@ -3,7 +3,6 @@
 // regression test for #88071
 
 #![feature(const_btree_new)]
-#![feature(const_fn_trait_bound)]
 
 use std::collections::BTreeMap;
 
diff --git a/src/test/ui/consts/issue-94675.rs b/src/test/ui/consts/issue-94675.rs
new file mode 100644 (file)
index 0000000..0604aab
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(const_trait_impl, const_mut_refs)]
+
+struct Foo<'a> {
+    bar: &'a mut Vec<usize>,
+}
+
+impl<'a> Foo<'a> {
+    const fn spam(&mut self, baz: &mut Vec<u32>) {
+        self.bar[0] = baz.len();
+        //~^ ERROR cannot call non-const fn `Vec::<u32>::len` in constant functions
+        //~| ERROR the trait bound `Vec<usize>: ~const IndexMut<usize>` is not satisfied
+        //~| ERROR cannot call non-const operator in constant functions
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-94675.stderr b/src/test/ui/consts/issue-94675.stderr
new file mode 100644 (file)
index 0000000..6665e42
--- /dev/null
@@ -0,0 +1,38 @@
+error[E0015]: cannot call non-const fn `Vec::<u32>::len` in constant functions
+  --> $DIR/issue-94675.rs:9:27
+   |
+LL |         self.bar[0] = baz.len();
+   |                           ^^^^^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error[E0277]: the trait bound `Vec<usize>: ~const IndexMut<usize>` is not satisfied
+  --> $DIR/issue-94675.rs:9:9
+   |
+LL |         self.bar[0] = baz.len();
+   |         ^^^^^^^^^^^ vector indices are of type `usize` or ranges of `usize`
+   |
+   = help: the trait `~const IndexMut<usize>` is not implemented for `Vec<usize>`
+note: the trait `IndexMut<usize>` is implemented for `Vec<usize>`, but that implementation is not `const`
+  --> $DIR/issue-94675.rs:9:9
+   |
+LL |         self.bar[0] = baz.len();
+   |         ^^^^^^^^^^^
+
+error[E0015]: cannot call non-const operator in constant functions
+  --> $DIR/issue-94675.rs:9:9
+   |
+LL |         self.bar[0] = baz.len();
+   |         ^^^^^^^^^^^
+   |
+note: impl defined here, but it is not `const`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL | impl<T, I: SliceIndex<[T]>, A: Allocator> IndexMut<I> for Vec<T, A> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
deleted file mode 100644 (file)
index 53ade85..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(rustc_attrs, staged_api, rustc_allow_const_fn_unstable)]
-#![feature(const_fn_fn_ptr_basics)]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_stable(since="1.0.0", feature = "mep")]
-const fn error(_: fn()) {}
-//~^ ERROR const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]`
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_stable(since="1.0.0", feature = "mep")]
-#[rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics)]
-const fn compiles(_: fn()) {}
-
-fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
deleted file mode 100644 (file)
index 6f89225..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]`
-  --> $DIR/allow_const_fn_ptr.rs:6:16
-   |
-LL | const fn error(_: fn()) {}
-   |                ^
-   |
-help: if it is not part of the public API, make this function unstably const
-   |
-LL | #[rustc_const_unstable(feature = "...", issue = "...")]
-   |
-help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
-   |
-LL | #[rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics)]
-   |
-
-error: aborting due to previous error
-
index 430e911aacdee7fb09785b067fd9e0fd906337f3..2dbc424d3ba2d76dc59ca5096239457e54aaa7c2 100644 (file)
@@ -1,13 +1,11 @@
 // run-pass
 #![feature(rustc_allow_const_fn_unstable)]
-#![feature(const_fn_fn_ptr_basics)]
 
 #![feature(rustc_attrs, staged_api)]
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(since="1.0.0", feature = "mep")]
-#[rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics)]
 const fn takes_fn_ptr(_: fn()) {}
 
 const FN: fn() = || ();
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs
deleted file mode 100644 (file)
index b68f47f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-fn main() {}
-
-const fn unsize(x: &[u8; 3]) -> &[u8] { x }
-const fn closure() -> fn() { || {} }
-//~^ ERROR function pointer
-//~| ERROR function pointer cast
-const fn closure2() {
-    (|| {}) as fn();
-//~^ ERROR function pointer
-}
-const fn reify(f: fn()) -> unsafe fn() { f }
-//~^ ERROR function pointer
-//~| ERROR function pointer
-//~| ERROR function pointer cast
-const fn reify2() { main as unsafe fn(); }
-//~^ ERROR function pointer
-//~| ERROR function pointer cast
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr
deleted file mode 100644 (file)
index fb962bd..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/cast_errors.rs:4:23
-   |
-LL | const fn closure() -> fn() { || {} }
-   |                       ^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/cast_errors.rs:4:30
-   |
-LL | const fn closure() -> fn() { || {} }
-   |                              ^^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/cast_errors.rs:8:5
-   |
-LL |     (|| {}) as fn();
-   |     ^^^^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/cast_errors.rs:11:16
-   |
-LL | const fn reify(f: fn()) -> unsafe fn() { f }
-   |                ^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/cast_errors.rs:11:28
-   |
-LL | const fn reify(f: fn()) -> unsafe fn() { f }
-   |                            ^^^^^^^^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/cast_errors.rs:11:42
-   |
-LL | const fn reify(f: fn()) -> unsafe fn() { f }
-   |                                          ^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/cast_errors.rs:15:21
-   |
-LL | const fn reify2() { main as unsafe fn(); }
-   |                     ^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/cast_errors.rs:15:21
-   |
-LL | const fn reify2() { main as unsafe fn(); }
-   |                     ^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error: aborting due to 8 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/min_const_fn/cast_fn.rs b/src/test/ui/consts/min_const_fn/cast_fn.rs
new file mode 100644 (file)
index 0000000..85802a5
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+
+fn main() {}
+
+const fn unsize(x: &[u8; 3]) -> &[u8] { x }
+const fn closure() -> fn() { || {} }
+const fn closure2() {
+    (|| {}) as fn();
+}
+const fn reify(f: fn()) -> unsafe fn() { f }
+const fn reify2() { main as unsafe fn(); }
index 638ff1d8b9c1c6da948d0adb3479047fee9ee202..e07b269c386eabee6dfc0c5e59c673e973e82bd2 100644 (file)
@@ -1,6 +1,4 @@
 const fn cmp(x: fn(), y: fn()) -> bool {
-    //~^ ERROR function pointer
-    //~| ERROR function pointer
     unsafe { x == y }
     //~^ ERROR pointers cannot be reliably compared
 }
index 5d8483cd111bf4cc744814155ccd85716a78a913..3845068d8411c652cfca567167c846d75d0d4a4d 100644 (file)
@@ -1,29 +1,10 @@
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/cmp_fn_pointers.rs:1:14
-   |
-LL | const fn cmp(x: fn(), y: fn()) -> bool {
-   |              ^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/cmp_fn_pointers.rs:1:23
-   |
-LL | const fn cmp(x: fn(), y: fn()) -> bool {
-   |                       ^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
 error: pointers cannot be reliably compared during const eval
-  --> $DIR/cmp_fn_pointers.rs:4:14
+  --> $DIR/cmp_fn_pointers.rs:2:14
    |
 LL |     unsafe { x == y }
    |              ^^^^^^
    |
    = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index 10347a02074ec56221053f5d095b13be2a1aac23..0bafaf2e81f7329fc5370326fa2878d4044a5795 100644 (file)
@@ -80,11 +80,10 @@ const fn char_cast(u: u8) -> char { u as char }
 const unsafe fn ret_null_ptr_no_unsafe<T>() -> *const T { core::ptr::null() }
 const unsafe fn ret_null_mut_ptr_no_unsafe<T>() -> *mut T { core::ptr::null_mut() }
 
-// not ok
 const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
-//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
 const fn foo11_2<T: Send>(t: T) -> T { t }
-//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+
+// not ok
 
 static BAR: u32 = 42;
 const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics
@@ -108,41 +107,28 @@ const fn foo37(a: bool, b: bool) -> bool { a || b }
 fn main() {}
 
 impl<T: std::fmt::Debug> Foo<T> {
-//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
     const fn foo(&self) {}
 }
 
 impl<T: std::fmt::Debug + Sized> Foo<T> {
-//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
     const fn foo2(&self) {}
 }
 
 impl<T: Sync + Sized> Foo<T> {
-//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
     const fn foo3(&self) {}
 }
 
 struct AlanTuring<T>(T);
 const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
-//~^ ERROR trait bounds other than `Sized`
-//~| ERROR destructor
+//~^ ERROR destructor
 const fn no_apit(_x: impl std::fmt::Debug) {}
-//~^ ERROR trait bounds other than `Sized`
-//~| ERROR destructor
+//~^ ERROR destructor
 const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
-//~^ ERROR trait objects in const fn are unstable
 const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
-//~^ ERROR trait objects in const fn are unstable
 
 const fn no_unsafe() { unsafe {} }
 
-const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-//~^ ERROR trait objects in const fn are unstable
-//~| ERROR trait objects in const fn are unstable
-//~| ERROR trait objects in const fn are unstable
+const fn traits_are_ok_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
 
-const fn no_fn_ptrs(_x: fn()) {}
-//~^ ERROR function pointer
-const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
-//~^ ERROR function pointer
-//~| ERROR function pointer cast
+const fn fn_ptrs(_x: fn()) {}
+const fn fn_ptrs2() -> fn() { fn foo() {} foo }
index 67cb604b6a7be0344258766ec7b3bd21478ab4d8..4ad17602c8452031f1ceee3bed7db076d43b063b 100644 (file)
@@ -130,26 +130,8 @@ LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:84:16
-   |
-LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
-   |                ^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:86:18
-   |
-LL | const fn foo11_2<T: Send>(t: T) -> T { t }
-   |                  ^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
 error[E0013]: constant functions cannot refer to statics
-  --> $DIR/min_const_fn.rs:90:27
+  --> $DIR/min_const_fn.rs:89:27
    |
 LL | const fn foo25() -> u32 { BAR }
    |                           ^^^
@@ -157,7 +139,7 @@ LL | const fn foo25() -> u32 { BAR }
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0013]: constant functions cannot refer to statics
-  --> $DIR/min_const_fn.rs:91:37
+  --> $DIR/min_const_fn.rs:90:37
    |
 LL | const fn foo26() -> &'static u32 { &BAR }
    |                                     ^^^
@@ -165,7 +147,7 @@ LL | const fn foo26() -> &'static u32 { &BAR }
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error: pointers cannot be cast to integers during const eval
-  --> $DIR/min_const_fn.rs:92:42
+  --> $DIR/min_const_fn.rs:91:42
    |
 LL | const fn foo30(x: *const u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
@@ -174,7 +156,7 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize }
    = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: pointers cannot be cast to integers during const eval
-  --> $DIR/min_const_fn.rs:94:63
+  --> $DIR/min_const_fn.rs:93:63
    |
 LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
    |                                                               ^^^^^^^^^^
@@ -183,7 +165,7 @@ LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize }
    = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: pointers cannot be cast to integers during const eval
-  --> $DIR/min_const_fn.rs:96:42
+  --> $DIR/min_const_fn.rs:95:42
    |
 LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
@@ -192,7 +174,7 @@ LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
 error: pointers cannot be cast to integers during const eval
-  --> $DIR/min_const_fn.rs:98:63
+  --> $DIR/min_const_fn.rs:97:63
    |
 LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
    |                                                               ^^^^^^^^^^
@@ -201,7 +183,7 @@ LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize }
    = 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
+  --> $DIR/min_const_fn.rs:100:14
    |
 LL | const fn inc(x: &mut i32) { *x += 1 }
    |              ^
@@ -209,155 +191,23 @@ LL | const fn inc(x: &mut i32) { *x += 1 }
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:110:6
-   |
-LL | impl<T: std::fmt::Debug> Foo<T> {
-   |      ^
-LL |
-LL |     const fn foo(&self) {}
-   |     ------------------- function declared as const here
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:115:6
-   |
-LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
-   |      ^
-LL |
-LL |     const fn foo2(&self) {}
-   |     -------------------- function declared as const here
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:120:6
-   |
-LL | impl<T: Sync + Sized> Foo<T> {
-   |      ^
-LL |
-LL |     const fn foo3(&self) {}
-   |     -------------------- function declared as const here
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:126:34
-   |
-LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
-   |                                  ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/min_const_fn.rs:126:19
+  --> $DIR/min_const_fn.rs:122:19
    |
 LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
    |                   ^^                                     - value is dropped here
    |                   |
    |                   constant functions cannot evaluate destructors
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
-  --> $DIR/min_const_fn.rs:129:22
-   |
-LL | const fn no_apit(_x: impl std::fmt::Debug) {}
-   |                      ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/min_const_fn.rs:129:18
+  --> $DIR/min_const_fn.rs:124:18
    |
 LL | const fn no_apit(_x: impl std::fmt::Debug) {}
    |                  ^^                         - value is dropped here
    |                  |
    |                  constant functions cannot evaluate destructors
 
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/min_const_fn.rs:132:23
-   |
-LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
-   |                       ^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/min_const_fn.rs:134:32
-   |
-LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/min_const_fn.rs:139:41
-   |
-LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   | -------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | function declared as const here
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/min_const_fn.rs:139:42
-   |
-LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   | -------------------------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | function declared as const here
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/min_const_fn.rs:139:42
-   |
-LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   | -------------------------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | function declared as const here
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/min_const_fn.rs:144:21
-   |
-LL | const fn no_fn_ptrs(_x: fn()) {}
-   |                     ^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/min_const_fn.rs:146:27
-   |
-LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
-   |                           ^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/min_const_fn.rs:146:46
-   |
-LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
-   |                                              ^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error: aborting due to 39 previous errors
+error: aborting due to 24 previous errors
 
 Some errors have detailed explanations: E0013, E0493, E0658.
 For more information about an error, try `rustc --explain E0013`.
index 1ab8253b414a3b7333052a6a44d3ff66fbbfceba..36c8880093ec32c2033db11269ecf792293428f7 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 struct HasDyn {
     field: &'static dyn std::fmt::Debug,
 }
@@ -7,9 +9,7 @@ struct HasDyn {
 const fn no_inner_dyn_trait(_x: Hide) {}
 const fn no_inner_dyn_trait2(x: Hide) {
     x.0.field;
-//~^ ERROR trait objects in const fn are unstable
 }
 const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
-//~^ ERROR trait objects in const fn are unstable
 
 fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
deleted file mode 100644 (file)
index 4c21991..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/min_const_fn_dyn.rs:9:5
-   |
-LL | const fn no_inner_dyn_trait2(x: Hide) {
-   | ------------------------------------- function declared as const here
-LL |     x.0.field;
-   |     ^^^^^^^^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/min_const_fn_dyn.rs:12:66
-   |
-LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
-   | -----------------------------------------                        ^^
-   | |
-   | function declared as const here
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs
deleted file mode 100644 (file)
index bc6fe89..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// gate-test-const_fn_fn_ptr_basics
-
-struct HasPtr {
-    field: fn(),
-}
-
-struct Hide(HasPtr);
-
-fn field() {}
-
-const fn no_inner_dyn_trait(_x: Hide) {}
-const fn no_inner_dyn_trait2(x: Hide) {
-    x.0.field;
-//~^ ERROR function pointer
-}
-const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
-//~^ ERROR function pointer
-
-fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
deleted file mode 100644 (file)
index 8d82674..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/min_const_fn_fn_ptr.rs:13:5
-   |
-LL |     x.0.field;
-   |     ^^^^^^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error[E0658]: function pointer casts are not allowed in constant functions
-  --> $DIR/min_const_fn_fn_ptr.rs:16:59
-   |
-LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
-   |                                                           ^^^^^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs
deleted file mode 100644 (file)
index e062c9f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// gate-test-const_impl_trait
-
-struct AlanTuring<T>(T);
-const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { //~ `impl Trait`
-    AlanTuring(0)
-}
-
-const fn no_rpit() -> impl std::fmt::Debug {} //~ `impl Trait`
-
-fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr
deleted file mode 100644 (file)
index 01c797c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: `impl Trait` is not allowed in constant functions
-  --> $DIR/min_const_fn_impl_trait.rs:4:24
-   |
-LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> {
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #77463 <https://github.com/rust-lang/rust/issues/77463> for more information
-   = help: add `#![feature(const_impl_trait)]` to the crate attributes to enable
-
-error[E0658]: `impl Trait` is not allowed in constant functions
-  --> $DIR/min_const_fn_impl_trait.rs:8:23
-   |
-LL | const fn no_rpit() -> impl std::fmt::Debug {}
-   |                       ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #77463 <https://github.com/rust-lang/rust/issues/77463> for more information
-   = help: add `#![feature(const_impl_trait)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 35aa587d3d24571813b5cab4c7c1b22a4acf129c..bb240fb4ad62cde406abe6991efd81e95a00c7e9 100644 (file)
@@ -15,7 +15,7 @@ const fn foo() -> u32 { 42 }
 // can't call non-min_const_fn
 const fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
 
-#[unstable(feature = "rust1", issue = "none")]
+#[unstable(feature = "foo2", issue = "none")]
 const fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 962a57bb8e9dfabafb091fd182f7f667d12ae301..03084c8674dc2778fd3f9b8121c148eeba0eb87d 100644 (file)
@@ -15,7 +15,7 @@
 // can't call non-min_const_fn
 const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR not yet stable as a const fn
 
-#[unstable(feature = "rust1", issue = "none")]
+#[unstable(feature = "foo2", issue = "none")]
 const unsafe fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 194f5fc1e5408ec91626cf4de2e23230ec29260f..94b62071362981c45e45a98ad85f0dd0e32b95d2 100644 (file)
@@ -15,7 +15,7 @@ const fn foo() -> u32 { 42 }
 // can't call non-min_const_fn
 const unsafe fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
 
-#[unstable(feature = "rust1", issue = "none")]
+#[unstable(feature = "foo2", issue = "none")]
 const fn foo2() -> u32 { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index e2f9708ddcb0143509ce9918fb39dbbd717ae7ea..aaba19c2c8b0e6b8b014f44c1a10620be26ef4ec 100644 (file)
@@ -12,16 +12,6 @@ LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "
 
 warning: skipping const checks
    |
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/abi-mismatch.rs:9:23
-   |
-LL | const fn call_rust_fn(my_fn: extern "Rust" fn()) {
-   |                       ^^^^^
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/abi-mismatch.rs:10:5
-   |
-LL |     my_fn();
-   |     ^^^^^
 help: skipping check that does not even have a feature gate
   --> $DIR/abi-mismatch.rs:10:5
    |
index 0f0068ac3bdc13e1ebfa309fa0b13a02529860e3..2e1d5d26b5c7518072e7baab20733946388d8fd5 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(const_transmute)]
-
 // normalize-stderr-64bit "64 bits" -> "word size"
 // normalize-stderr-32bit "32 bits" -> "word size"
 // normalize-stderr-64bit "128 bits" -> "2 * word size"
index 6e93aed70b65adff716ffe2fa460b6a109a2b298..27cc2f5e66a336824661c84bf6187e6a26c03b99 100644 (file)
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:15:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:13:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -11,13 +11,13 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
 error: could not evaluate constant pattern
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9
    |
 LL |         ZST => {}
    |         ^^^
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:15:29
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:13:29
    |
 LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    |                             ^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    = note: target type: `&[u8]` (2 * word size)
 
 error: could not evaluate constant pattern
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9
+  --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9
    |
 LL |         ZST => {}
    |         ^^^
index 2fbbbbffac484a0c6d58ce2e5ccd6ec2fb62bb75..16b36c8d56d8d3e1e740e3fe2302d1185ccf9b7b 100644 (file)
@@ -4,9 +4,7 @@
 // gate was not enabled in libcore.
 
 #![stable(feature = "core", since = "1.6.0")]
-#![feature(rustc_const_unstable)]
 #![feature(staged_api)]
-#![feature(const_fn_trait_bound)]
 
 enum Opt<T> {
     Some(T),
index 4ef25bd1334f3b30a85d5a086f270d0435a9acf7..180f9f10cc6bc656b9f30ae581b57c21634dd882 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/unstable-const-fn-in-libcore.rs:24:26
+  --> $DIR/unstable-const-fn-in-libcore.rs:22:26
    |
 LL |             Opt::None => f(),
    |                          ^^^
@@ -11,7 +11,7 @@ LL |     const fn unwrap_or_else<F: FnOnce() -> T + ~const std::ops::FnOnce<()>>
    |                                              +++++++++++++++++++++++++++++
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/unstable-const-fn-in-libcore.rs:19:53
+  --> $DIR/unstable-const-fn-in-libcore.rs:17:53
    |
 LL |     const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
    |                                                     ^ constant functions cannot evaluate destructors
@@ -20,7 +20,7 @@ LL |     }
    |     - value is dropped here
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/unstable-const-fn-in-libcore.rs:19:47
+  --> $DIR/unstable-const-fn-in-libcore.rs:17:47
    |
 LL |     const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
    |                                               ^^^^ constant functions cannot evaluate destructors
index c3eea2e7b8ad6629d04fb8e56aadacc548cfbb80..ebebabe349b85a509ce23d641bc6948a7fb18b6e 100644 (file)
@@ -1,14 +1,8 @@
 error[E0601]: `main` function not found in crate `continue_after_missing_main`
-  --> $DIR/continue-after-missing-main.rs:1:1
+  --> $DIR/continue-after-missing-main.rs:30:2
    |
-LL | / #![allow(dead_code)]
-LL | |
-LL | | struct Tableau<'a, MP> {
-LL | |     provider: &'a MP,
-...  |
-LL | |
-LL | | }
-   | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
+LL | }
+   |  ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
 
 error: aborting due to previous error
 
index 55796408e9d79ab1278398049bfe9fde0bb23fa2..1019cacce64213feb8fcfe230fe78bbc46bd5857 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(dead_code)] //~ ERROR `main` function not found in crate
+#![allow(dead_code)]
 
 struct Tableau<'a, MP> {
     provider: &'a MP,
@@ -27,4 +27,4 @@ fn create_and_solve_subproblems<'data_provider, 'original_data, MP>(
 ) {
     let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound();
     //~^ ERROR lifetime mismatch
-}
+} //~ ERROR `main` function not found in crate
index 439f9e5221f66556693b50b3af78f0f090866dac..29e7dc1e56c732b2da0180afb3b6afc862d01150 100644 (file)
@@ -1,14 +1,8 @@
 error[E0601]: `main` function not found in crate `continue_after_missing_main`
-  --> $DIR/continue-after-missing-main.rs:1:1
+  --> $DIR/continue-after-missing-main.rs:30:2
    |
-LL | / #![allow(dead_code)]
-LL | |
-LL | | struct Tableau<'a, MP> {
-LL | |     provider: &'a MP,
-...  |
-LL | |
-LL | | }
-   | |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
+LL | }
+   |  ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
 
 error[E0623]: lifetime mismatch
   --> $DIR/continue-after-missing-main.rs:28:56
index cf977fa4b7b44d1293a4506f9050a4bdd756e531..5c14f5ed356f321d54f21846801b1333a3c77a4d 100644 (file)
@@ -3,8 +3,6 @@ error: `#[deprecated]` cannot be used in staged API
    |
 LL | #[deprecated]
    | ^^^^^^^^^^^^^ use `#[rustc_deprecated]` instead
-LL | fn main() {}
-   | ------------
 
 error: aborting due to previous error
 
index 24112c9855acd1d967f95ce213a708839086f553..3daf4930c5b4b349f981f98c9f6c815318897d44 100644 (file)
@@ -1,7 +1,7 @@
 async fn foo() {
 //~^ ERROR `async fn` is not permitted in Rust 2015
 //~| NOTE to use `async fn`, switch to Rust 2018 or later
-//~| HELP set `edition = "2021"` in `Cargo.toml`
+//~| HELP pass `--edition 2021` to `rustc`
 //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
 
     let x = async {};
@@ -11,7 +11,7 @@ async fn foo() {
         let x = 42;
         //~^ ERROR expected identifier, found keyword `let`
         //~| NOTE expected identifier, found keyword
-        //~| HELP set `edition = "2021"` in `Cargo.toml`
+        //~| HELP pass `--edition 2021` to `rustc`
         //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
         42
     };
@@ -19,7 +19,7 @@ async fn foo() {
         42
         //~^ ERROR expected identifier, found `42`
         //~| NOTE expected identifier
-        //~| HELP set `edition = "2021"` in `Cargo.toml`
+        //~| HELP pass `--edition 2021` to `rustc`
         //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
     };
     y.await;
index da8412ddcb3333eafba7940ad8b8bca6526d80a2..b792b8c1e0dd84834e9b3353c851786df87a4022 100644 (file)
@@ -4,7 +4,7 @@ error[E0670]: `async fn` is not permitted in Rust 2015
 LL | async fn foo() {
    | ^^^^^ to use `async fn`, switch to Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error: expected identifier, found keyword `let`
@@ -15,7 +15,7 @@ LL |     let y = async {
 LL |         let x = 42;
    |         ^^^ expected identifier, found keyword
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error: expected identifier, found `42`
@@ -26,7 +26,7 @@ LL |     let z = async {
 LL |         42
    |         ^^ expected identifier
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0422]: cannot find struct, variant or union type `async` in this scope
index 175bd033067bc61ea606e29b814dcc5699f1b3b3..c74c307c492fe385fd3c8e5073083d9448ea32b9 100644 (file)
@@ -1,10 +1,8 @@
 error[E0601]: `main` function not found in crate `elided_test`
-  --> $DIR/elided-test.rs:5:1
+  --> $DIR/elided-test.rs:7:2
    |
-LL | / #[test]
-LL | | fn main() {
-LL | | }
-   | |_^ consider adding a `main` function to `$DIR/elided-test.rs`
+LL | }
+   |  ^ consider adding a `main` function to `$DIR/elided-test.rs`
 
 error: aborting due to previous error
 
index 7e9b05587b075e56805c54349b1cb9841d351491..d319227b217a73624e0a64aeb079d05a104306bb 100644 (file)
@@ -1,5 +1,8 @@
+#![feature(lint_reasons)]
+
 #![deny(unused_attributes)]
 #![allow()] //~ ERROR unused attribute
+#![expect()] //~ ERROR unused attribute
 #![warn()] //~ ERROR unused attribute
 #![deny()] //~ ERROR unused attribute
 #![forbid()] //~ ERROR unused attribute
index e0798e4f0c69fc9b610fc5ad79113f887b321711..8653eaf5ccdf3e9f048541f859a19744745a59e8 100644 (file)
@@ -1,18 +1,18 @@
 error: unused attribute
-  --> $DIR/empty-attributes.rs:8:1
+  --> $DIR/empty-attributes.rs:11:1
    |
 LL | #[repr()]
    | ^^^^^^^^^ help: remove this attribute
    |
 note: the lint level is defined here
-  --> $DIR/empty-attributes.rs:1:9
+  --> $DIR/empty-attributes.rs:3:9
    |
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
    = note: attribute `repr` with an empty list has no effect
 
 error: unused attribute
-  --> $DIR/empty-attributes.rs:11:1
+  --> $DIR/empty-attributes.rs:14:1
    |
 LL | #[target_feature()]
    | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute
@@ -20,7 +20,7 @@ LL | #[target_feature()]
    = note: attribute `target_feature` with an empty list has no effect
 
 error: unused attribute
-  --> $DIR/empty-attributes.rs:2:1
+  --> $DIR/empty-attributes.rs:4:1
    |
 LL | #![allow()]
    | ^^^^^^^^^^^ help: remove this attribute
@@ -28,7 +28,15 @@ LL | #![allow()]
    = note: attribute `allow` with an empty list has no effect
 
 error: unused attribute
-  --> $DIR/empty-attributes.rs:3:1
+  --> $DIR/empty-attributes.rs:5:1
+   |
+LL | #![expect()]
+   | ^^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: attribute `expect` with an empty list has no effect
+
+error: unused attribute
+  --> $DIR/empty-attributes.rs:6:1
    |
 LL | #![warn()]
    | ^^^^^^^^^^ help: remove this attribute
@@ -36,7 +44,7 @@ LL | #![warn()]
    = note: attribute `warn` with an empty list has no effect
 
 error: unused attribute
-  --> $DIR/empty-attributes.rs:4:1
+  --> $DIR/empty-attributes.rs:7:1
    |
 LL | #![deny()]
    | ^^^^^^^^^^ help: remove this attribute
@@ -44,7 +52,7 @@ LL | #![deny()]
    = note: attribute `deny` with an empty list has no effect
 
 error: unused attribute
-  --> $DIR/empty-attributes.rs:5:1
+  --> $DIR/empty-attributes.rs:8:1
    |
 LL | #![forbid()]
    | ^^^^^^^^^^^^ help: remove this attribute
@@ -52,12 +60,12 @@ LL | #![forbid()]
    = note: attribute `forbid` with an empty list has no effect
 
 error: unused attribute
-  --> $DIR/empty-attributes.rs:6:1
+  --> $DIR/empty-attributes.rs:9:1
    |
 LL | #![feature()]
    | ^^^^^^^^^^^^^ help: remove this attribute
    |
    = note: attribute `feature` with an empty list has no effect
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
index 64d640c0e9dbcae0785a578de4ddd15ff8b514df..8dd0f377533ce8c0dc0ce1a22e1252c4daf38da2 100644 (file)
@@ -1,19 +1,18 @@
 error[E0005]: refutable pattern in local binding: `T(_, _)` not covered
   --> $DIR/empty-never-array.rs:10:9
    |
-LL | / enum Helper<T, U> {
-LL | |     T(T, [!; 0]),
-   | |     - not covered
-LL | |     #[allow(dead_code)]
-LL | |     U(U),
-LL | | }
-   | |_- `Helper<T, U>` defined here
-...
-LL |       let Helper::U(u) = Helper::T(t, []);
-   |           ^^^^^^^^^^^^ pattern `T(_, _)` not covered
+LL |     let Helper::U(u) = Helper::T(t, []);
+   |         ^^^^^^^^^^^^ pattern `T(_, _)` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Helper<T, U>` defined here
+  --> $DIR/empty-never-array.rs:4:5
+   |
+LL | enum Helper<T, U> {
+   |      ------
+LL |     T(T, [!; 0]),
+   |     ^ not covered
    = note: the matched value is of type `Helper<T, U>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index e0bb7dbfae9f1f793113f91a5ea60b519adfa496..dab9c687e24980b0ce3a086f7e719af3c84564c3 100644 (file)
@@ -1,7 +1,6 @@
 #![feature(imported_main)]
 #![feature(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
@@ -11,4 +10,4 @@ fn bar() {}
     //~^ ERROR mismatched types [E0308]
 }
 
-use foo::BAR as main;
+use foo::BAR as main; //~ ERROR `main` function not found in crate
index c731c32832222f7d480fadea359dd2a641920362..b9bc0262a56b21ee006e311ae6c8225025ff880b 100644 (file)
@@ -1,19 +1,13 @@
 error[E0601]: `main` function not found in crate `imported_main_const_fn_item_type_forbidden`
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:1:1
+  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:13:22
    |
-LL | / #![feature(imported_main)]
-LL | | #![feature(type_alias_impl_trait)]
-LL | | #![allow(incomplete_features)]
-LL | |
-...  |
-LL | |
-LL | | use foo::BAR as main;
-   | |_____----------------^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs`
-   |       |
-   |       non-function item at `crate::main` is found
+LL | use foo::BAR as main;
+   |     ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs`
+   |     |
+   |     non-function item at `crate::main` is found
 
 error[E0308]: mismatched types
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:10:29
+  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:9:29
    |
 LL |     type MainFn = impl Fn();
    |                   --------- the expected opaque type
@@ -25,7 +19,7 @@ LL |     pub const BAR: MainFn = bar;
                   found fn item `fn() {bar}`
 
 error: could not find defining uses
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:6:19
+  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:5:19
    |
 LL |     type MainFn = impl Fn();
    |                   ^^^^^^^^^
index 989a6c97a8004cd191eb9a9793cda5f78a6215e4..1508280c0fa571bf85bfbfe81679050c0753249f 100644 (file)
@@ -1,7 +1,6 @@
 #![feature(imported_main)]
-//~^ ERROR `main` function not found in crate
 pub mod foo {
     pub const BAR: usize = 42;
 }
 
-use foo::BAR as main;
+use foo::BAR as main; //~ ERROR `main` function not found in crate
index 4640513c2bb5f599f27822c932dec30926e82d6a..9d8b40dc3c9bc4c489b7026104a3b9f56fe8ecdb 100644 (file)
@@ -1,16 +1,10 @@
 error[E0601]: `main` function not found in crate `imported_main_const_forbidden`
-  --> $DIR/imported_main_const_forbidden.rs:1:1
+  --> $DIR/imported_main_const_forbidden.rs:6:22
    |
-LL | / #![feature(imported_main)]
-LL | |
-LL | | pub mod foo {
-LL | |     pub const BAR: usize = 42;
-LL | | }
-LL | |
-LL | | use foo::BAR as main;
-   | |_____----------------^ consider adding a `main` function to `$DIR/imported_main_const_forbidden.rs`
-   |       |
-   |       non-function item at `crate::main` is found
+LL | use foo::BAR as main;
+   |     ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_forbidden.rs`
+   |     |
+   |     non-function item at `crate::main` is found
 
 error: aborting due to previous error
 
index fd0215e72ee24acb16a54ad9f088bbc8be1c219f..d4519af540859078b7587ba20c30a2ea998e9610 100644 (file)
@@ -4,16 +4,27 @@ error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered
 LL |     match x { }
    |           ^ patterns `None` and `Some(_)` not covered
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
+note: `Option<i32>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL |     None,
-   |     ---- not covered
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ---- not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     None,
+   | |     ^^^^ not covered
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+   | |     ^^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `Option<i32>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match x {
+LL +         None | Some(_) => todo!(),
+LL ~     }
+   |
 
 error: aborting due to previous error
 
index 5bf375a64843a2bb2c82b7ac291362c6c82ec512..8ba151d9e65fa483bd0b5dfb61fc6058ecfcdd6f 100644 (file)
@@ -1,18 +1,22 @@
 error[E0004]: non-exhaustive patterns: `HastaLaVistaBaby` not covered
   --> $DIR/E0004.rs:9:11
    |
-LL | / enum Terminator {
-LL | |     HastaLaVistaBaby,
-   | |     ---------------- not covered
-LL | |     TalkToMyHand,
-LL | | }
-   | |_- `Terminator` defined here
-...
-LL |       match x {
-   |             ^ pattern `HastaLaVistaBaby` not covered
+LL |     match x {
+   |           ^ pattern `HastaLaVistaBaby` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Terminator` defined here
+  --> $DIR/E0004.rs:2:5
+   |
+LL | enum Terminator {
+   |      ----------
+LL |     HastaLaVistaBaby,
+   |     ^^^^^^^^^^^^^^^^ not covered
    = note: the matched value is of type `Terminator`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Terminator::TalkToMyHand => {}
+LL +         HastaLaVistaBaby => todo!()
+   |
 
 error: aborting due to previous error
 
index b95dcbd8935b33e45367922cbea953418e4dfcf2..208c625a53e959c7df055d372bc5c1324b2249f3 100644 (file)
@@ -4,13 +4,21 @@ error[E0005]: refutable pattern in local binding: `None` not covered
 LL |     let Some(y) = x;
    |         ^^^^^^^ pattern `None` not covered
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     None,
-   |     ---- not covered
-   |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Option<i32>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     None,
+   | |     ^^^^ not covered
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+LL | | }
+   | |_-
    = note: the matched value is of type `Option<i32>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index 957e79a9f398183c55f94d9561520b4efdc0e02a..95d95003c616f60e5cf0e5bfd46673aad2afa656 100644 (file)
@@ -4,11 +4,19 @@ error[E0005]: refutable pattern in `for` loop binding: `None` not covered
 LL |     for Some(x) in xs {}
    |         ^^^^^^^ pattern `None` not covered
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     None,
-   |     ---- not covered
+note: `Option<i32>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
    |
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     None,
+   | |     ^^^^ not covered
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+LL | | }
+   | |_-
    = note: the matched value is of type `Option<i32>`
 
 error: aborting due to previous error
index e7bcd7c6bfe65c21b31ea04f40ad7d6b14985410..46d952df77195dad9046534993068c917a8eacf9 100644 (file)
@@ -1,7 +1,5 @@
 // aux-build:pub-and-stability.rs
 
-#![feature(unused_feature)]
-
 // A big point of this test is that we *declare* `unstable_declared`,
 // but do *not* declare `unstable_undeclared`. This way we can check
 // that the compiler is letting in uses of declared feature-gated
index 2f5dab7eb0559793c0f63af8eab3b18b804c28ee..e3f82137ab3b2fcc4e2ba480f6011a868f49000f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature 'unstable_undeclared'
-  --> $DIR/explore-issue-38412.rs:21:63
+  --> $DIR/explore-issue-38412.rs:19:63
    |
 LL |     let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
    |                                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_un
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'unstable_undeclared'
-  --> $DIR/explore-issue-38412.rs:30:5
+  --> $DIR/explore-issue-38412.rs:28:5
    |
 LL |     r.a_unstable_undeclared_pub;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,25 +17,25 @@ LL |     r.a_unstable_undeclared_pub;
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
 error[E0616]: field `b_crate` of struct `Record` is private
-  --> $DIR/explore-issue-38412.rs:31:7
+  --> $DIR/explore-issue-38412.rs:29:7
    |
 LL |     r.b_crate;
    |       ^^^^^^^ private field
 
 error[E0616]: field `c_mod` of struct `Record` is private
-  --> $DIR/explore-issue-38412.rs:32:7
+  --> $DIR/explore-issue-38412.rs:30:7
    |
 LL |     r.c_mod;
    |       ^^^^^ private field
 
 error[E0616]: field `d_priv` of struct `Record` is private
-  --> $DIR/explore-issue-38412.rs:33:7
+  --> $DIR/explore-issue-38412.rs:31:7
    |
 LL |     r.d_priv;
    |       ^^^^^^ private field
 
 error[E0658]: use of unstable library feature 'unstable_undeclared'
-  --> $DIR/explore-issue-38412.rs:37:5
+  --> $DIR/explore-issue-38412.rs:35:5
    |
 LL |     t.2;
    |     ^^^
@@ -44,25 +44,25 @@ LL |     t.2;
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
 error[E0616]: field `3` of struct `Tuple` is private
-  --> $DIR/explore-issue-38412.rs:38:7
+  --> $DIR/explore-issue-38412.rs:36:7
    |
 LL |     t.3;
    |       ^ private field
 
 error[E0616]: field `4` of struct `Tuple` is private
-  --> $DIR/explore-issue-38412.rs:39:7
+  --> $DIR/explore-issue-38412.rs:37:7
    |
 LL |     t.4;
    |       ^ private field
 
 error[E0616]: field `5` of struct `Tuple` is private
-  --> $DIR/explore-issue-38412.rs:40:7
+  --> $DIR/explore-issue-38412.rs:38:7
    |
 LL |     t.5;
    |       ^ private field
 
 error[E0658]: use of unstable library feature 'unstable_undeclared'
-  --> $DIR/explore-issue-38412.rs:44:7
+  --> $DIR/explore-issue-38412.rs:42:7
    |
 LL |     r.unstable_undeclared_trait_method();
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL |     r.unstable_undeclared_trait_method();
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'unstable_undeclared'
-  --> $DIR/explore-issue-38412.rs:48:7
+  --> $DIR/explore-issue-38412.rs:46:7
    |
 LL |     r.unstable_undeclared();
    |       ^^^^^^^^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     r.unstable_undeclared();
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
 error[E0624]: associated function `pub_crate` is private
-  --> $DIR/explore-issue-38412.rs:50:7
+  --> $DIR/explore-issue-38412.rs:48:7
    |
 LL |     r.pub_crate();
    |       ^^^^^^^^^ private associated function
@@ -91,7 +91,7 @@ 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
+  --> $DIR/explore-issue-38412.rs:49:7
    |
 LL |     r.pub_mod();
    |       ^^^^^^^ private associated function
@@ -102,7 +102,7 @@ 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
+  --> $DIR/explore-issue-38412.rs:50:7
    |
 LL |     r.private();
    |       ^^^^^^^ private associated function
@@ -113,7 +113,7 @@ 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
+  --> $DIR/explore-issue-38412.rs:55:7
    |
 LL |     t.unstable_undeclared_trait_method();
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -122,7 +122,7 @@ LL |     t.unstable_undeclared_trait_method();
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'unstable_undeclared'
-  --> $DIR/explore-issue-38412.rs:61:7
+  --> $DIR/explore-issue-38412.rs:59:7
    |
 LL |     t.unstable_undeclared();
    |       ^^^^^^^^^^^^^^^^^^^
@@ -131,7 +131,7 @@ LL |     t.unstable_undeclared();
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
 
 error[E0624]: associated function `pub_crate` is private
-  --> $DIR/explore-issue-38412.rs:63:7
+  --> $DIR/explore-issue-38412.rs:61:7
    |
 LL |     t.pub_crate();
    |       ^^^^^^^^^ private associated function
@@ -142,7 +142,7 @@ 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
+  --> $DIR/explore-issue-38412.rs:62:7
    |
 LL |     t.pub_mod();
    |       ^^^^^^^ private associated function
@@ -153,7 +153,7 @@ 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
+  --> $DIR/explore-issue-38412.rs:63:7
    |
 LL |     t.private();
    |       ^^^^^^^ private associated function
index c5ffa55ebec6f64985bca63f2e7ac730f6ced3c5..c2ffda6bb72d24e97dae7ce25fdcdfe0637b21d3 100644 (file)
@@ -4,13 +4,20 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered
 LL |     let Ok(_x) = foo();
    |         ^^^^^^ pattern `Err(_)` not covered
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     --- not covered
-   |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | / pub enum Result<T, E> {
+LL | |     /// Contains the success value
+LL | |     #[lang = "Ok"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+   | |     ^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `Result<u32, !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index 1d2be3657ffb2b16379768d9d3a1dfa0c593ddaa..c5c13451488915c496e44b210e5a5ab7388a4a01 100644 (file)
@@ -24,7 +24,7 @@ trait Bar {
 }
 
 impl Bar for Foo {
-    type Assoc where Self: Sized = Foo;
+    type Assoc = Foo where Self: Sized;
     //~^ ERROR where clauses on associated types are unstable
 }
 
index 6c2c3ed9c365537d38c22a016144ea52928e7af1..12a40ff0a12f5b9db1800ac6ddbaf343a09c355f 100644 (file)
@@ -55,7 +55,7 @@ LL |     type Assoc where Self: Sized;
 error[E0658]: where clauses on associated types are unstable
   --> $DIR/feature-gate-generic_associated_types.rs:27:5
    |
-LL |     type Assoc where Self: Sized = Foo;
+LL |     type Assoc = Foo where Self: Sized;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
index 9895646fc2ba477d8aa3c7d530acf78a79c46731..b5510683328f54097f884ca53d7c749371af823e 100644 (file)
@@ -4,10 +4,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0usize {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
    = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         0..=usize::MAX => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
@@ -15,10 +19,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
    = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         isize::MIN..=isize::MAX => {}
+LL +         _ => todo!()
+   |
 
 error: aborting due to 2 previous errors
 
index 04f816ea5016401112bd152625b6431456d77ae2..667bc9f8ddf182905e5a8f9f725cc4f24f39f73c 100644 (file)
@@ -2,6 +2,6 @@
 
 #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
 #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
-#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
+#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
 
 fn main() {}
index 822368a5946ecb2fa0b1210fec38a06e309f7a55..45a095903d2a7b59a39b9cabb9a0a2b6bee67558 100644 (file)
@@ -14,7 +14,7 @@ LL | #[rustc_error]
    |
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
+error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
   --> $DIR/feature-gate-rustc-attrs-1.rs:5:1
    |
 LL | #[rustc_nonnull_optimization_guaranteed]
index a71d26ce16f5b6f407ce1d593bc24b845b2ed80a..951bb5a17400f16068edea5e514bbd395bc51154 100644 (file)
@@ -1,15 +1,15 @@
-error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/feature-gate-staged_api.rs:1:1
-   |
-LL | #![stable(feature = "a", since = "b")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/feature-gate-staged_api.rs:8:1
    |
 LL | #[stable(feature = "a", since = "b")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0734]: stability attributes may not be used outside of the standard library
+  --> $DIR/feature-gate-staged_api.rs:1:1
+   |
+LL | #![stable(feature = "a", since = "b")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
index f8aa23d95e5b6c24ea04bc27bb6963fbf3d80c10..51f2db5556e2b2963bd97e7262daa0b1ef2ca843 100644 (file)
@@ -1,10 +1,10 @@
 #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
 //~^ ERROR malformed `feature`
 //~| ERROR malformed `feature`
-
+//~| ERROR unknown feature `foo`
+//~| ERROR unknown feature `foo_bar_baz`
 #![feature] //~ ERROR malformed `feature` attribute
 #![feature = "foo"] //~ ERROR malformed `feature` attribute
-
 #![feature(test_removed_feature)] //~ ERROR: feature has been removed
 
 fn main() {}
index 477bf5e866eef3e51f562ac901647aa40403f616..2d01bdf3c1dffa2b6c7fcc0ce8aef1b439f5fc73 100644 (file)
@@ -17,18 +17,30 @@ LL | #![feature(test_removed_feature)]
    |            ^^^^^^^^^^^^^^^^^^^^ feature has been removed
 
 error: malformed `feature` attribute input
-  --> $DIR/gated-bad-feature.rs:5:1
+  --> $DIR/gated-bad-feature.rs:6:1
    |
 LL | #![feature]
    | ^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]`
 
 error: malformed `feature` attribute input
-  --> $DIR/gated-bad-feature.rs:6:1
+  --> $DIR/gated-bad-feature.rs:7:1
    |
 LL | #![feature = "foo"]
    | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]`
 
-error: aborting due to 5 previous errors
+error[E0635]: unknown feature `foo_bar_baz`
+  --> $DIR/gated-bad-feature.rs:1:12
+   |
+LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
+   |            ^^^^^^^^^^^
+
+error[E0635]: unknown feature `foo`
+  --> $DIR/gated-bad-feature.rs:1:48
+   |
+LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
+   |                                                ^^^
+
+error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0556, E0557.
+Some errors have detailed explanations: E0556, E0557, E0635.
 For more information about an error, try `rustc --explain E0556`.
index a01d85515a8b72da5ef7ef2a39dba1a3669af84e..3acfbd0ca23aedd6b89356c27a504d4b800e8953 100644 (file)
@@ -6,25 +6,38 @@
 
 #![rustc_deprecated()]
 //~^ ERROR stability attributes may not be used outside of the standard library
+//~| ERROR missing 'since' [E0542]
 
 #[rustc_deprecated()]
 //~^ ERROR stability attributes may not be used outside of the standard library
+//~| ERROR missing 'since' [E0542]
 mod rustc_deprecated {
-    mod inner { #![rustc_deprecated()] }
-    //~^ ERROR stability attributes may not be used outside of the standard library
+    mod inner {
+        #![rustc_deprecated()]
+        //~^ ERROR stability attributes may not be used outside of the standard library
+        //~| ERROR missing 'since' [E0542]
+    }
 
-    #[rustc_deprecated()] fn f() { }
+    #[rustc_deprecated()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR missing 'since' [E0542]
+    fn f() {}
 
-    #[rustc_deprecated()] struct S;
+    #[rustc_deprecated()]
     //~^ ERROR stability attributes may not be used outside of the standard library
-    //~| ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR missing 'since' [E0542]
+    //~| ERROR missing 'since' [E0542]
+    struct S;
 
-    #[rustc_deprecated()] type T = S;
+    #[rustc_deprecated()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR missing 'since' [E0542]
+    type T = S;
 
-    #[rustc_deprecated()] impl S { }
+    #[rustc_deprecated()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    //~| ERROR missing 'since' [E0542]
+    impl S {}
 }
 
 fn main() {}
index 3c4dcfec02b12df493aea1f811352de148882121..4ec78f318c2338fd6d19de21e2e3e59f5001dd7b 100644 (file)
@@ -1,51 +1,94 @@
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:7:1
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:16:9
    |
-LL | #![rustc_deprecated()]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+LL |         #![rustc_deprecated()]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:10:1
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:21:5
    |
-LL | #[rustc_deprecated()]
-   | ^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_deprecated()]
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:13:17
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:26:5
    |
-LL |     mod inner { #![rustc_deprecated()] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[rustc_deprecated()]
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:16:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:32:5
    |
-LL |     #[rustc_deprecated()] fn f() { }
+LL |     #[rustc_deprecated()]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:19:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:37:5
    |
-LL |     #[rustc_deprecated()] struct S;
+LL |     #[rustc_deprecated()]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:19:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:11:1
    |
-LL |     #[rustc_deprecated()] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:23:5
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:7:1
+   |
+LL | #![rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:7:1
+   |
+LL | #![rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:11:1
+   |
+LL | #[rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:16:9
+   |
+LL |         #![rustc_deprecated()]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:21:5
    |
-LL |     #[rustc_deprecated()] type T = S;
+LL |     #[rustc_deprecated()]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0734]: stability attributes may not be used outside of the standard library
+error[E0542]: missing 'since'
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:26:5
    |
-LL |     #[rustc_deprecated()] impl S { }
+LL |     #[rustc_deprecated()]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:26:5
+   |
+LL |     #[rustc_deprecated()]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:32:5
+   |
+LL |     #[rustc_deprecated()]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:37:5
+   |
+LL |     #[rustc_deprecated()]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 15 previous errors
 
-For more information about this error, try `rustc --explain E0734`.
+Some errors have detailed explanations: E0542, E0734.
+For more information about an error, try `rustc --explain E0542`.
index 73ff965307fd72d3fad5823ea0ad135d2c5d93fa..621ec01bbe219c24d112f2151e4bb3d91403701a 100644 (file)
 #[stable()]
 //~^ ERROR stability attributes may not be used outside of the standard library
 mod stable {
-    mod inner { #![stable()] }
-    //~^ ERROR stability attributes may not be used outside of the standard library
+    mod inner {
+        #![stable()]
+        //~^ ERROR stability attributes may not be used outside of the standard library
+    }
 
-    #[stable()] fn f() { }
+    #[stable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    fn f() {}
 
-    #[stable()] struct S;
+    #[stable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
-    //~| ERROR stability attributes may not be used outside of the standard library
+    struct S;
 
-    #[stable()] type T = S;
+    #[stable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    type T = S;
 
-    #[stable()] impl S { }
+    #[stable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    impl S {}
 }
 
 fn main() {}
index 2573db1d684d9670d5bac1fbdbb67c5270d39828..677fef3a926b58552d7f769ffdfc3834bc3f99fc 100644 (file)
@@ -1,51 +1,45 @@
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:7:1
-   |
-LL | #![stable()]
-   | ^^^^^^^^^^^^
-
-error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:10:1
+  --> $DIR/issue-43106-gating-of-stable.rs:14:9
    |
-LL | #[stable()]
-   | ^^^^^^^^^^^
+LL |         #![stable()]
+   |         ^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:13:17
+  --> $DIR/issue-43106-gating-of-stable.rs:18:5
    |
-LL |     mod inner { #![stable()] }
-   |                 ^^^^^^^^^^^^
+LL |     #[stable()]
+   |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:16:5
+  --> $DIR/issue-43106-gating-of-stable.rs:22:5
    |
-LL |     #[stable()] fn f() { }
+LL |     #[stable()]
    |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:19:5
+  --> $DIR/issue-43106-gating-of-stable.rs:26:5
    |
-LL |     #[stable()] struct S;
+LL |     #[stable()]
    |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:19:5
+  --> $DIR/issue-43106-gating-of-stable.rs:30:5
    |
-LL |     #[stable()] struct S;
+LL |     #[stable()]
    |     ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:23:5
+  --> $DIR/issue-43106-gating-of-stable.rs:10:1
    |
-LL |     #[stable()] type T = S;
-   |     ^^^^^^^^^^^
+LL | #[stable()]
+   | ^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-stable.rs:26:5
+  --> $DIR/issue-43106-gating-of-stable.rs:7:1
    |
-LL |     #[stable()] impl S { }
-   |     ^^^^^^^^^^^
+LL | #![stable()]
+   | ^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
index d8339b00c12d2459221eb59705d909dc2a3e6c90..d507bcd8f15df2e9fb20feda47e781ae4228d0cb 100644 (file)
 #[unstable()]
 //~^ ERROR stability attributes may not be used outside of the standard library
 mod unstable {
-    mod inner { #![unstable()] }
-    //~^ ERROR stability attributes may not be used outside of the standard library
+    mod inner {
+        #![unstable()]
+        //~^ ERROR stability attributes may not be used outside of the standard library
+    }
 
-    #[unstable()] fn f() { }
+    #[unstable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    fn f() {}
 
-    #[unstable()] struct S;
+    #[unstable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
-    //~| ERROR stability attributes may not be used outside of the standard library
+    struct S;
 
-    #[unstable()] type T = S;
+    #[unstable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    type T = S;
 
-    #[unstable()] impl S { }
+    #[unstable()]
     //~^ ERROR stability attributes may not be used outside of the standard library
+    impl S {}
 }
 
 fn main() {}
index 500675e054c3f02346c2a1e4677cebbb90842c1f..a2f361878c6dba45466aa463b3a220f47afc99ec 100644 (file)
@@ -1,51 +1,45 @@
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:7:1
-   |
-LL | #![unstable()]
-   | ^^^^^^^^^^^^^^
-
-error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:10:1
+  --> $DIR/issue-43106-gating-of-unstable.rs:14:9
    |
-LL | #[unstable()]
-   | ^^^^^^^^^^^^^
+LL |         #![unstable()]
+   |         ^^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:13:17
+  --> $DIR/issue-43106-gating-of-unstable.rs:18:5
    |
-LL |     mod inner { #![unstable()] }
-   |                 ^^^^^^^^^^^^^^
+LL |     #[unstable()]
+   |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:16:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:22:5
    |
-LL |     #[unstable()] fn f() { }
+LL |     #[unstable()]
    |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:19:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:26:5
    |
-LL |     #[unstable()] struct S;
+LL |     #[unstable()]
    |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:19:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:30:5
    |
-LL |     #[unstable()] struct S;
+LL |     #[unstable()]
    |     ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:23:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:10:1
    |
-LL |     #[unstable()] type T = S;
-   |     ^^^^^^^^^^^^^
+LL | #[unstable()]
+   | ^^^^^^^^^^^^^
 
 error[E0734]: stability attributes may not be used outside of the standard library
-  --> $DIR/issue-43106-gating-of-unstable.rs:26:5
+  --> $DIR/issue-43106-gating-of-unstable.rs:7:1
    |
-LL |     #[unstable()] impl S { }
-   |     ^^^^^^^^^^^^^
+LL | #![unstable()]
+   | ^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0734`.
index 914a7d71dc4210853587198f854b7202ade0ce9e..d383680002f4b9fcdde3eadb3a3d6c7d0f923293 100644 (file)
@@ -1,10 +1,6 @@
 // build-pass
 // compile-flags: -Zdrop-tracking
 
-// FIXME(eholk): temporarily disabled while drop range tracking is disabled
-// (see generator_interior.rs:27)
-// ignore-test
-
 // A test to ensure generators capture values that were conditionally dropped,
 // and also that values that are dropped along all paths to a yield do not get
 // included in the generator type.
index da00b230d9fb73b54e7506187a4d9b967772fbfd..f82111a76b18f9427fe99d2ab9bfd71afd4d368b 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(generators, generator_trait, box_leak)]
+#![feature(generators, generator_trait)]
 
 use std::cell::RefCell;
 use std::ops::Generator;
index 5c23ecbae32730bcc08425efc1a5986d597960a3..91407ea1844f54922c084cb77f34619928f7d1e9 100644 (file)
@@ -1,8 +1,5 @@
 // check-pass
-
-// FIXME(eholk): temporarily disabled while drop range tracking is disabled
-// (see generator_interior.rs:27)
-// ignore-test
+// compile-flags: -Zdrop-tracking
 
 #![feature(negative_impls, generators)]
 
index e89e4b61bbff779632fdd214c26576c834468de3..c872fb7f3e6305745d3d4ff91c3d6a32aebdf3f7 100644 (file)
@@ -1,6 +1,4 @@
-// FIXME(eholk): temporarily disabled while drop range tracking is disabled
-// (see generator_interior.rs:27)
-// ignore-test
+// compile-flags: -Zdrop-tracking
 
 #![feature(negative_impls, generators)]
 
index 9a1b0734d8c865111a2397a6f82c9053a86e1c7e..16b34c917ece43395c24d729324f3d22188f11d9 100644 (file)
@@ -1,12 +1,12 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:12:5
+  --> $DIR/partial-drop.rs:14:5
    |
 LL |     assert_send(|| {
    |     ^^^^^^^^^^^ generator is not `Send`
    |
-   = help: within `[generator@$DIR/partial-drop.rs:12:17: 18:6]`, the trait `Send` is not implemented for `Foo`
+   = help: within `[generator@$DIR/partial-drop.rs:14:17: 20:6]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/partial-drop.rs:17:9
+  --> $DIR/partial-drop.rs:19:9
    |
 LL |         let guard = Bar { foo: Foo, x: 42 };
    |             ----- has type `Bar` which is not `Send`
@@ -16,20 +16,20 @@ LL |         yield;
 LL |     });
    |     - `guard` is later dropped here
 note: required by a bound in `assert_send`
-  --> $DIR/partial-drop.rs:40:19
+  --> $DIR/partial-drop.rs:42:19
    |
 LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:20:5
+  --> $DIR/partial-drop.rs:22:5
    |
 LL |     assert_send(|| {
    |     ^^^^^^^^^^^ generator is not `Send`
    |
-   = help: within `[generator@$DIR/partial-drop.rs:20:17: 28:6]`, the trait `Send` is not implemented for `Foo`
+   = help: within `[generator@$DIR/partial-drop.rs:22:17: 30:6]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/partial-drop.rs:27:9
+  --> $DIR/partial-drop.rs:29:9
    |
 LL |         let guard = Bar { foo: Foo, x: 42 };
    |             ----- has type `Bar` which is not `Send`
@@ -39,20 +39,20 @@ LL |         yield;
 LL |     });
    |     - `guard` is later dropped here
 note: required by a bound in `assert_send`
-  --> $DIR/partial-drop.rs:40:19
+  --> $DIR/partial-drop.rs:42:19
    |
 LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:30:5
+  --> $DIR/partial-drop.rs:32:5
    |
 LL |     assert_send(|| {
    |     ^^^^^^^^^^^ generator is not `Send`
    |
-   = help: within `[generator@$DIR/partial-drop.rs:30:17: 37:6]`, the trait `Send` is not implemented for `Foo`
+   = help: within `[generator@$DIR/partial-drop.rs:32:17: 39:6]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/partial-drop.rs:36:9
+  --> $DIR/partial-drop.rs:38:9
    |
 LL |         let guard = Bar { foo: Foo, x: 42 };
    |             ----- has type `Bar` which is not `Send`
@@ -62,7 +62,7 @@ LL |         yield;
 LL |     });
    |     - `guard` is later dropped here
 note: required by a bound in `assert_send`
-  --> $DIR/partial-drop.rs:40:19
+  --> $DIR/partial-drop.rs:42:19
    |
 LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
index 6d6063f8085ba5bc253de9560b41dc797c448363..53e3ad7fe694314b6c7b09079e233ec3c84a7bbd 100644 (file)
@@ -12,7 +12,7 @@ pub trait AsRef2 {
 }
 
 impl<T> AsRef2 for Vec<T> {
-  type Output<'a> where Self: 'a = &'a [T];
+  type Output<'a> = &'a [T] where Self: 'a;
 
   fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
     &self[..]
@@ -33,7 +33,7 @@ impl<'b, T, U> AsRef2 for Foo<T>
     T: AsRef2<Output<'b> = &'b [U]>,
     U: 'b
 {
-  type Output<'a> where Self: 'a = FooRef<'a, U>;
+  type Output<'a> = FooRef<'a, U> where Self: 'a;
 
   fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
     FooRef(self.0.as_ref2())
index ffcfd62cbb3be48c6e81f62c6d0ac008487d3a6c..6e7cd45bdb1f6cd29e902bcc7828cc048ffb4fea 100644 (file)
@@ -13,7 +13,7 @@ trait MyTrait {
 struct Foo;
 
 impl MyTrait for Foo {
-    type Assoc<'a, 'b> where 'b: 'a = u32;
+    type Assoc<'a, 'b> = u32 where 'b: 'a;
 
     fn do_sth(_: u32) {}
     // fn do_sth(_: Self::Assoc<'static, 'static>) {}
index 5b94cdee7c9c7deea6fb73f325ec198a982ee5a4..157e1b1d295734cba370716498807d36ddf2463d 100644 (file)
@@ -32,7 +32,7 @@ impl CollectionFamily for VecFamily {
 }
 
 impl<T> Collection<T> for Vec<T> {
-    type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
+    type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter;
     type Family = VecFamily;
 
     fn empty() -> Self {
index b0f2fb3f567856e8d649f1c0ed7c3e0c4612081b..1c00aa73feb9fa24c39cd8236f74e27ab3693a6b 100644 (file)
@@ -32,7 +32,7 @@ impl CollectionFamily for VecFamily {
 }
 
 impl<T> Collection<T> for Vec<T> {
-    type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
+    type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter;
     type Family = VecFamily;
 
     fn empty() -> Self {
index 9ae328cc48b1d988d8a9fecd3632987ab2d8a219..060804269aa70a6a18d07010a10d19f743c8b7a2 100644 (file)
@@ -16,9 +16,9 @@ trait Baz {
 }
 
 impl<T> Baz for T where T: Foo {
-    type Quux<'a> where T: 'a = T;
+    type Quux<'a> = T where T: 'a;
 
-    type Baa<'a> where T: 'a = &'a <T as Foo>::Bar<'a, 'static>;
+    type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static> where T: 'a;
 }
 
 fn main() {}
index fb03a86e169715df91c5d4bcaae07a096c4f359b..7bbcf950ae183c20f7b6c6adda8296ebdf18a955 100644 (file)
@@ -15,7 +15,7 @@ impl Foo for Fooy {
 struct Fooer<T>(T);
 
 impl<T> Foo for Fooer<T> {
-    type A<'x> where T: 'x = &'x ();
+    type A<'x> = &'x () where T: 'x;
 }
 
 fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
index 592ff9399232371489bbb3bb3aede873efcd2d4c..2ecbc8c5912590097d4647be547a6cb143144ded 100644 (file)
@@ -19,7 +19,7 @@ impl Foo for Bar {
     type Assoc = usize;
     type Assoc2<T> = Vec<T>;
     //~^ ERROR `T` doesn't implement `std::fmt::Display`
-    type Assoc3<T> where T: Iterator = Vec<T>;
+    type Assoc3<T> = Vec<T> where T: Iterator;
     //~^ ERROR impl has stricter requirements than trait
     type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>;
     type NoGenerics = ::std::cell::Cell<i32>;
index 544f2bcbbd7778c456297eebef49c8f08fe4ba0b..68594bba48632bac76e779867e79291c93785b90 100644 (file)
@@ -16,7 +16,7 @@ error[E0276]: impl has stricter requirements than trait
 LL |     type Assoc3<T>;
    |     --------------- definition of `Assoc3` from trait
 ...
-LL |     type Assoc3<T> where T: Iterator = Vec<T>;
+LL |     type Assoc3<T> = Vec<T> where T: Iterator;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
 
 error: aborting due to 2 previous errors
index ff2ffec22c4564a65a0b49a151edcab3a61825ec..bb5992c88f08f0973abf045c3e663610fedbbf5f 100644 (file)
@@ -12,12 +12,12 @@ trait Foo {
 struct Fooy<T>(T);
 
 impl<T> Foo for Fooy<T> {
-    type A<'a> where Self: 'static = (&'a ());
+    type A<'a> = (&'a ()) where Self: 'static;
     //~^ ERROR `impl` associated type
-    type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+    type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
     //~^ ERROR `impl` associated type
     //~| ERROR lifetime bound not satisfied
-    type C where Self: Copy = String;
+    type C = String where Self: Copy;
     //~^ ERROR the trait bound `T: Copy` is not satisfied
     fn d() where Self: Copy {}
     //~^ ERROR the trait bound `T: Copy` is not satisfied
index bd0dea372194d4f14a6b4c90c975b6c33abe0510..3d90471e398e613f78684270075664dbb1942b50 100644 (file)
@@ -4,7 +4,7 @@ error: `impl` associated type signature for `A` doesn't match `trait` associated
 LL |     type A<'a> where Self: 'a;
    |     -------------------------- expected
 ...
-LL |     type A<'a> where Self: 'static = (&'a ());
+LL |     type A<'a> = (&'a ()) where Self: 'static;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
 
 error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
@@ -13,35 +13,33 @@ error: `impl` associated type signature for `B` doesn't match `trait` associated
 LL |     type B<'a, 'b> where 'a: 'b;
    |     ---------------------------- expected
 ...
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
 
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/impl_bounds.rs:17:35
+  --> $DIR/impl_bounds.rs:17:22
    |
 LL |     type B<'a, 'b> where 'a: 'b;
    |     ---------------------------- definition of `B` from trait
 ...
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-   |                                -  ^^^^^^^^^^^^^^^
-   |                                |
-   |                                help: try copying this clause from the trait: `, 'a: 'b`
+LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
+   |                      ^^^^^^^^^^^^^^^             - help: try copying this clause from the trait: `, 'a: 'b`
    |
 note: lifetime parameter instantiated with the lifetime `'a` as defined here
   --> $DIR/impl_bounds.rs:17:12
    |
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
    |            ^^
 note: but lifetime parameter must outlive the lifetime `'b` as defined here
   --> $DIR/impl_bounds.rs:17:16
    |
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
    |                ^^
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/impl_bounds.rs:20:5
    |
-LL |     type C where Self: Copy = String;
+LL |     type C = String where Self: Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
index 08120b9670f67da1a295391463d3aae2ce27d0c0..4df8235d95f34b878158503c2b4d10ad6511a64d 100644 (file)
@@ -22,9 +22,9 @@ impl Foo for Fooy {
 struct Fooer<T>(T);
 
 impl<T> Foo for Fooer<T> {
-    type A<'x> where T: 'x = (&'x ());
-    type B<'u, 'v> where 'u: 'v = (&'v &'u ());
-    type C where Self: Clone + ToOwned = String;
+    type A<'x> = (&'x ()) where T: 'x;
+    type B<'u, 'v> = (&'v &'u ()) where 'u: 'v;
+    type C = String where Self: Clone + ToOwned;
 }
 
 fn main() {}
index da5fca2a6569f942a833beb392ba72176dd54d53..d352c1948f234f417c404f24c806a399d243cdb6 100644 (file)
@@ -9,7 +9,7 @@ trait Foo {
 struct Bar;
 
 impl Foo for Bar {
-    type Assoc3<T> where T: Iterator = Vec<T>;
+    type Assoc3<T> = Vec<T> where T: Iterator;
     //~^ ERROR impl has stricter requirements than trait
 }
 
index 56677457726f7868229e2cf090a1c9ef4db3f690..39beac38c0b6151951ff84594ff6a07f95b7b0d2 100644 (file)
@@ -4,7 +4,7 @@ error[E0276]: impl has stricter requirements than trait
 LL |     type Assoc3<T>;
    |     --------------- definition of `Assoc3` from trait
 ...
-LL |     type Assoc3<T> where T: Iterator = Vec<T>;
+LL |     type Assoc3<T> = Vec<T> where T: Iterator;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
 
 error: aborting due to previous error
index d3201a156a18cf22a4457bb50f305b3688fa5ba6..28eb3b0e750e2dbc866db4f866864fdf12fb860b 100644 (file)
@@ -29,7 +29,7 @@ pub fn new(items: Vec<T>, len: usize) -> Self {
 }
 
 impl<T> Iter for Windows<T> {
-    type Item<'a> where T: 'a = &'a mut [T];
+    type Item<'a> = &'a mut [T] where T: 'a;
 
     fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
         let slice = self.items.get_mut(self.start..self.start + self.len)?;
index 47ef38ff45d65beadccc13496883013c7420e21d..b9a3c583f7c89991f59db5571622016ad08f01bc 100644 (file)
@@ -22,7 +22,7 @@ trait MapLike<K, V> {
 }
 
 impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> {
-    type VRefCont<'a> where Self: 'a = &'a V;
+    type VRefCont<'a> = &'a V where Self: 'a;
     fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
         std::collections::BTreeMap::get(self, key)
     }
index 47decb70ae74c64b77a82d7dec2710f800a97fda..11c3dffde4b38f2e4400396d0fdef337af6ea69d 100644 (file)
@@ -2,9 +2,9 @@ error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/issue-84931.rs:15:21
    |
 LL |     type Item<'a> = &'a mut T;
-   |                  -  ^^^^^^^^^ ...so that the reference type `&'a mut T` does not outlive the data it points at
-   |                  |
-   |                  help: consider adding a where clause: `where T: 'a`
+   |                     ^^^^^^^^^- help: consider adding a where clause: `where T: 'a`
+   |                     |
+   |                     ...so that the reference type `&'a mut T` does not outlive the data it points at
 
 error: aborting due to previous error
 
index 5863bac2f9d0bdb19f7eb1a8840c7fb39b988bb9..0f8096c8a7c1bf37c374c7448ccf072dd044763a 100644 (file)
@@ -21,13 +21,10 @@ impl<Left, Right> HasChildrenOf for Either<Left, Right>
     Right: HasChildrenOf,
 {
     type T = Either<Left::T, Right::T>;
-    // We used to error below because the where clause doesn't match the trait.
-    // Now, we error early on the trait itself.
-    type TRef<'a>
+    type TRef<'a> = Either<&'a Left::T, &'a Right::T>
     where
-    <Left as HasChildrenOf>::T: 'a,
-    <Right as HasChildrenOf>::T: 'a
-    = Either<&'a Left::T, &'a Right::T>;
+        <Left as HasChildrenOf>::T: 'a,
+        <Right as HasChildrenOf>::T: 'a;
 
     fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>> {
         todo!()
index df5586ed422f84f0491c3330ccc6e492b33f194c..6b10edf073ff6ca01a141599597eb2dfa997c350 100644 (file)
@@ -27,11 +27,10 @@ impl<T, Criteria> SearchableResourceExt<Criteria> for T
 where
     T: SearchableResource<Criteria>,
 {
-    type Future<'f, A, B: 'f>
+    type Future<'f, A, B: 'f> = SearchFutureTy<'f, A, B>
     where
         A: SearchableResource<B> + ?Sized + 'f,
-        Self: 'f,
-    = SearchFutureTy<'f, A, B>;
+        Self: 'f;
 
     fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
         async move { todo!() }
index f8fb71bbddb4b8673145ec7592e03efe984a3334..51fe3360c7eb256195dc61d53dbc08a083a8e844 100644 (file)
@@ -5,9 +5,7 @@ LL |     type Fut<'a> where Self: 'a;
    |     ---------------------------- definition of `Fut` from trait
 ...
 LL |     type Fut<'a> = impl Future<Output = ()>;
-   |                 -  ^^^^^^^^^^^^^^^^^^^^^^^^
-   |                 |
-   |                 help: try copying this clause from the trait: `where Self: 'a`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a`
    |
 note: type must outlive the lifetime `'a` as defined here
   --> $DIR/issue-90014.rs:14:14
diff --git a/src/test/ui/generic-associated-types/issue-90729.rs b/src/test/ui/generic-associated-types/issue-90729.rs
new file mode 100644 (file)
index 0000000..98295cc
--- /dev/null
@@ -0,0 +1,38 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+use std::marker::PhantomData;
+
+pub trait Type {
+    type Ref<'a>;
+}
+
+pub trait AsBytes {}
+
+impl AsBytes for &str {}
+
+pub struct Utf8;
+
+impl Type for Utf8 {
+    type Ref<'a> = &'a str;
+}
+
+pub struct Bytes<T: Type> {
+    _marker: PhantomData<T>,
+}
+
+impl<T: Type> Bytes<T>
+where
+    for<'a> T::Ref<'a>: AsBytes,
+{
+    pub fn new() -> Self {
+        Self {
+            _marker: PhantomData,
+        }
+    }
+}
+
+fn main() {
+    let _b = Bytes::<Utf8>::new();
+}
diff --git a/src/test/ui/generic-associated-types/issue-91139.migrate.stderr b/src/test/ui/generic-associated-types/issue-91139.migrate.stderr
new file mode 100644 (file)
index 0000000..a27d811
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/issue-91139.rs:27:12
+   |
+LL | fn foo<T>() {
+   |        - help: consider adding an explicit lifetime bound...: `T: 'a`
+LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+
+error: aborting due to previous error
+
index 2b82d2946b3ba11b6e47a39fa35914426ac5bf90..78b2b63dadc5e94179cac8832248c65a9c27d00e 100644 (file)
@@ -1,4 +1,13 @@
-// check-pass
+// revisions: migrate nll
+//[nll]compile-flags: -Z borrowck=mir
+
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[nll] check-pass
+//[migrate] check-fail
 
 #![feature(generic_associated_types)]
 
@@ -9,14 +18,14 @@ trait Foo<T> {
 }
 
 impl<T> Foo<T> for () {
-    type Type<'a>
+    type Type<'a> = ()
     where
-        T: 'a,
-    = ();
+        T: 'a;
 }
 
 fn foo<T>() {
     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
+    //[migrate]~^ the parameter type `T` may not live long enough
 }
 
 pub fn main() {}
index caa6618f39884b1e7bbc9a1dfccc69f8c2704af8..5b90199b8091f6cf94d7837dab99df1fcd910277 100644 (file)
@@ -7,9 +7,7 @@ LL | |         Self: 'a;
    | |_________________- definition of `TextureIter` from trait
 ...
 LL |       type TextureIter<'a> = std::option::IntoIter<&'a Texture>;
-   |                           -  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                           |
-   |                           help: try copying this clause from the trait: `where Self: 'a`
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a`
    |
 note: type must outlive the lifetime `'a` as defined here
   --> $DIR/issue-92033.rs:22:22
index db26493ecadfab926b1df9c68cf74ccba707e815..81d000f1076ca3194b2af91a7d110f68556ad007 100644 (file)
@@ -17,10 +17,9 @@ struct KeySegment_Broken<T> {
     key: T,
 }
 impl<S: HasAssoc> Iterate<S> for KeySegment_Broken<S::Assoc> {
-    type Iter<'a>
+    type Iter<'a> = ()
     where
-        Self: 'a,
-    = ();
+        Self: 'a;
 }
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-93341.rs b/src/test/ui/generic-associated-types/issue-93341.rs
new file mode 100644 (file)
index 0000000..e96a768
--- /dev/null
@@ -0,0 +1,55 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+use std::marker::PhantomData;
+
+pub struct Id<'id>(PhantomData<fn(&'id ()) -> &'id ()>);
+
+fn new_id() -> Id<'static> {
+    Id(PhantomData)
+}
+
+pub trait HasLifetime where {
+    type AtLifetime<'a>;
+}
+
+pub struct ExistentialLifetime<S: HasLifetime>(S::AtLifetime<'static>);
+
+impl<S: HasLifetime> ExistentialLifetime<S> {
+    pub fn new<F>(f: F) -> ExistentialLifetime<S>
+        where for<'id> F: FnOnce(Id<'id>) -> S::AtLifetime<'id> {
+        ExistentialLifetime(f(new_id()))
+    }
+}
+
+
+struct ExampleS<'id>(Id<'id>);
+
+struct ExampleMarker;
+
+impl HasLifetime for ExampleMarker {
+    type AtLifetime<'id> = ExampleS<'id>;
+}
+
+
+fn broken0() -> ExistentialLifetime<ExampleMarker> {
+    fn new_helper<'id>(id: Id<'id>) -> ExampleS<'id> {
+        ExampleS(id)
+    }
+
+    ExistentialLifetime::<ExampleMarker>::new(new_helper)
+}
+
+fn broken1() -> ExistentialLifetime<ExampleMarker> {
+    fn new_helper<'id>(id: Id<'id>) -> <ExampleMarker as HasLifetime>::AtLifetime<'id> {
+        ExampleS(id)
+    }
+
+    ExistentialLifetime::<ExampleMarker>::new(new_helper)
+}
+
+fn broken2() -> ExistentialLifetime<ExampleMarker> {
+    ExistentialLifetime::<ExampleMarker>::new(|id| ExampleS(id))
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-93342.rs b/src/test/ui/generic-associated-types/issue-93342.rs
new file mode 100644 (file)
index 0000000..d8d7ada
--- /dev/null
@@ -0,0 +1,57 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+use std::marker::PhantomData;
+
+pub trait Scalar: 'static {
+    type RefType<'a>: ScalarRef<'a>;
+}
+
+pub trait ScalarRef<'a>: 'a {}
+
+impl Scalar for i32 {
+    type RefType<'a> = i32;
+}
+
+impl Scalar for String {
+    type RefType<'a> = &'a str;
+}
+
+impl Scalar for bool {
+    type RefType<'a> = i32;
+}
+
+impl<'a> ScalarRef<'a> for bool {}
+
+impl<'a> ScalarRef<'a> for i32 {}
+
+impl<'a> ScalarRef<'a> for &'a str {}
+
+fn str_contains(a: &str, b: &str) -> bool {
+    a.contains(b)
+}
+
+pub struct BinaryExpression<A: Scalar, B: Scalar, O: Scalar, F>
+where
+    F: Fn(A::RefType<'_>, B::RefType<'_>) -> O,
+{
+    f: F,
+    _phantom: PhantomData<(A, B, O)>,
+}
+
+impl<A: Scalar, B: Scalar, O: Scalar, F> BinaryExpression<A, B, O, F>
+where
+    F: Fn(A::RefType<'_>, B::RefType<'_>) -> O,
+{
+    pub fn new(f: F) -> Self {
+        Self {
+            f,
+            _phantom: PhantomData,
+        }
+    }
+}
+
+fn main() {
+    BinaryExpression::<String, String, bool, _>::new(str_contains);
+}
index 952fca8ab8a65fff5314647d3de9d60cf94ee965..af0049891b69685f96852a88172858c118384cb6 100644 (file)
@@ -11,8 +11,8 @@ trait Iterable {
 
 // Impl for struct type
 impl<T> Iterable for Vec<T> {
-    type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
-    type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
+    type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a;
+    type Iter<'a> = std::slice::Iter<'a, T> where T: 'a;
 
     fn iter<'a>(&'a self) -> Self::Iter<'a> {
         self[..].iter()
@@ -21,8 +21,8 @@ fn iter<'a>(&'a self) -> Self::Iter<'a> {
 
 // Impl for a primitive type
 impl<T> Iterable for [T] {
-    type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
-    type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
+    type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a;
+    type Iter<'a> = std::slice::Iter<'a, T> where T: 'a;
 
     fn iter<'a>(&'a self) -> Self::Iter<'a> {
         self.iter()
index ad9f2e3e4ec4a8273d8248c7d7ec43c0d6b6e79c..5fb8f7a4773d68a583015ffe71284b14a15ed32c 100644 (file)
@@ -6,7 +6,7 @@ trait Foo {
     type Assoc<'a, 'b>;
 }
 impl Foo for () {
-    type Assoc<'a, 'b> where 'a: 'b = ();
+    type Assoc<'a, 'b> = () where 'a: 'b;
     //~^ `impl` associated type
 }
 
index 0e183c8d69a4c0e6a531ba034b7bddfef4036156..9e0896127a8a3e11aeb4ccc8007581c432cbf9f3 100644 (file)
@@ -4,7 +4,7 @@ error: `impl` associated type signature for `Assoc` doesn't match `trait` associ
 LL |     type Assoc<'a, 'b>;
    |     ------------------- expected
 ...
-LL |     type Assoc<'a, 'b> where 'a: 'b = ();
+LL |     type Assoc<'a, 'b> = () where 'a: 'b;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
 
 error: aborting due to previous error
index 7517e1fa9d061fc3777ba41f8e21fb2b6a9466c7..794d677c8b657679f35f842fd1a38c5928e0128a 100644 (file)
@@ -22,7 +22,7 @@ impl<T> Foo for Number<T> {
     // }
     // ```
     // which it is :)
-    type Item where [T]: Sized = [T];
+    type Item = [T] where [T]: Sized;
 }
 
 struct OnlySized<T> where T: Sized { f: T }
index 8f8cb679e9c0e8c7815fa0a85a1d5f6c2293c771..6564a3608ec0eb03a7aca3c73b5cbe41a6f6da39 100644 (file)
@@ -24,7 +24,7 @@ impl Foo for Number {
     // }
     // ```
     // which it is :)
-    type Item where str: Sized = str;
+    type Item = str where str: Sized;
 }
 
 struct OnlySized<T> where T: Sized { f: T }
index f83d4d7b68e48ae155a5db86ae28bf2f6486654a..e71b6805ad412ca377f897143162a163337eea27 100644 (file)
@@ -30,7 +30,7 @@ struct StreamEnumerate<I> {
 }
 
 impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
-    type Item<'a> where Self: 'a = (usize, I::Item<'a>);
+    type Item<'a> = (usize, I::Item<'a>) where Self: 'a;
     fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
         match self.iter.next() {
             None => None,
@@ -44,7 +44,7 @@ fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
 }
 
 impl<I: Iterator> StreamingIterator for I {
-    type Item<'a> where Self: 'a = <I as Iterator>::Item;
+    type Item<'a> = <I as Iterator>::Item where Self: 'a;
     fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> {
         Iterator::next(self)
     }
index 14dbca60b78f238d8202519ccd52e8d825a0fca8..c2c77290c4374a59ce9c0bb157c4e2d48d6dec21 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0f32, f32::NEG_INFINITY..);
    |        ^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `f32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:17:8
@@ -13,8 +17,12 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0f32, ..f32::INFINITY);
    |        ^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `f32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
@@ -22,8 +30,12 @@ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
 LL |     m!('a', ..core::char::MAX);
    |        ^^^ pattern `'\u{10ffff}'` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `char`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         '\u{10ffff}' => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
@@ -31,8 +43,12 @@ error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
 LL |     m!('a', ..ALMOST_MAX);
    |        ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `char`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         '\u{10fffe}'..='\u{10ffff}' => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
@@ -40,8 +56,12 @@ error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered
 LL |     m!('a', ALMOST_MIN..);
    |        ^^^ pattern `'\u{0}'` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `char`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         '\u{0}' => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
@@ -49,8 +69,12 @@ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
 LL |     m!('a', ..=ALMOST_MAX);
    |        ^^^ pattern `'\u{10ffff}'` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `char`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         '\u{10ffff}' => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `'b'` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
@@ -58,8 +82,12 @@ error[E0004]: non-exhaustive patterns: `'b'` not covered
 LL |     m!('a', ..=VAL | VAL_2..);
    |        ^^^ pattern `'b'` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `char`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         'b' => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `'b'` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:31:8
@@ -67,8 +95,12 @@ error[E0004]: non-exhaustive patterns: `'b'` not covered
 LL |     m!('a', ..VAL_1 | VAL_2..);
    |        ^^^ pattern `'b'` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `char`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         'b' => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
@@ -76,8 +108,12 @@ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
 LL |         m!(0, ..u8::MAX);
    |            ^ pattern `u8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
@@ -85,8 +121,12 @@ error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `254_u8..=u8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         254_u8..=u8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_u8` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
@@ -94,8 +134,12 @@ error[E0004]: non-exhaustive patterns: `0_u8` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         0_u8 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
@@ -103,8 +147,12 @@ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u8` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
@@ -112,8 +160,12 @@ error[E0004]: non-exhaustive patterns: `43_u8` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u8 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u8` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:46:12
@@ -121,8 +173,12 @@ error[E0004]: non-exhaustive patterns: `43_u8` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u8 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
@@ -130,8 +186,12 @@ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
 LL |         m!(0, ..u16::MAX);
    |            ^ pattern `u16::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u16::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
@@ -139,8 +199,12 @@ error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `65534_u16..=u16::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         65534_u16..=u16::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_u16` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
@@ -148,8 +212,12 @@ error[E0004]: non-exhaustive patterns: `0_u16` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u16` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         0_u16 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
@@ -157,8 +225,12 @@ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u16::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u16::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u16` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
@@ -166,8 +238,12 @@ error[E0004]: non-exhaustive patterns: `43_u16` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u16` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u16 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u16` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:59:12
@@ -175,8 +251,12 @@ error[E0004]: non-exhaustive patterns: `43_u16` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u16` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u16 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
@@ -184,8 +264,12 @@ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
 LL |         m!(0, ..u32::MAX);
    |            ^ pattern `u32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u32::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
@@ -193,8 +277,12 @@ error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `4294967294_u32..=u32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         4294967294_u32..=u32::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_u32` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
@@ -202,8 +290,12 @@ error[E0004]: non-exhaustive patterns: `0_u32` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u32` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         0_u32 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
@@ -211,8 +303,12 @@ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u32::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u32` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
@@ -220,8 +316,12 @@ error[E0004]: non-exhaustive patterns: `43_u32` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u32` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u32 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u32` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:72:12
@@ -229,8 +329,12 @@ error[E0004]: non-exhaustive patterns: `43_u32` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u32` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u32 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
@@ -238,8 +342,12 @@ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
 LL |         m!(0, ..u64::MAX);
    |            ^ pattern `u64::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u64::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
@@ -247,8 +355,12 @@ error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `18446744073709551614_u64..=u64::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         18446744073709551614_u64..=u64::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_u64` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
@@ -256,8 +368,12 @@ error[E0004]: non-exhaustive patterns: `0_u64` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u64` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         0_u64 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
@@ -265,8 +381,12 @@ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u64::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u64::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u64` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
@@ -274,8 +394,12 @@ error[E0004]: non-exhaustive patterns: `43_u64` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u64` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u64 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u64` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:85:12
@@ -283,8 +407,12 @@ error[E0004]: non-exhaustive patterns: `43_u64` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u64` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u64 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
@@ -292,8 +420,12 @@ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
 LL |         m!(0, ..u128::MAX);
    |            ^ pattern `u128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
@@ -301,8 +433,12 @@ error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         340282366920938463463374607431768211454_u128..=u128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_u128` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
@@ -310,8 +446,12 @@ error[E0004]: non-exhaustive patterns: `0_u128` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u128` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         0_u128 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
@@ -319,8 +459,12 @@ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u128` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
@@ -328,8 +472,12 @@ error[E0004]: non-exhaustive patterns: `43_u128` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u128` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u128 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_u128` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:98:12
@@ -337,8 +485,12 @@ error[E0004]: non-exhaustive patterns: `43_u128` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u128` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_u128 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
@@ -346,8 +498,12 @@ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
 LL |         m!(0, ..i8::MAX);
    |            ^ pattern `i8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
@@ -355,8 +511,12 @@ error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `126_i8..=i8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         126_i8..=i8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
@@ -364,8 +524,12 @@ error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i8::MIN` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i8::MIN => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
@@ -373,8 +537,12 @@ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i8` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
@@ -382,8 +550,12 @@ error[E0004]: non-exhaustive patterns: `43_i8` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i8 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i8` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:114:12
@@ -391,8 +563,12 @@ error[E0004]: non-exhaustive patterns: `43_i8` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i8 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
@@ -400,8 +576,12 @@ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
 LL |         m!(0, ..i16::MAX);
    |            ^ pattern `i16::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i16::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
@@ -409,8 +589,12 @@ error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `32766_i16..=i16::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         32766_i16..=i16::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i16::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
@@ -418,8 +602,12 @@ error[E0004]: non-exhaustive patterns: `i16::MIN` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i16::MIN` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i16::MIN => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
@@ -427,8 +615,12 @@ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i16::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i16::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i16` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
@@ -436,8 +628,12 @@ error[E0004]: non-exhaustive patterns: `43_i16` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i16` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i16 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i16` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:127:12
@@ -445,8 +641,12 @@ error[E0004]: non-exhaustive patterns: `43_i16` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i16` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i16 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
@@ -454,8 +654,12 @@ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
 LL |         m!(0, ..i32::MAX);
    |            ^ pattern `i32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i32::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
@@ -463,8 +667,12 @@ error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `2147483646_i32..=i32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         2147483646_i32..=i32::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i32::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
@@ -472,8 +680,12 @@ error[E0004]: non-exhaustive patterns: `i32::MIN` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i32::MIN` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i32::MIN => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
@@ -481,8 +693,12 @@ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i32::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i32` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
@@ -490,8 +706,12 @@ error[E0004]: non-exhaustive patterns: `43_i32` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i32` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i32 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i32` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:140:12
@@ -499,8 +719,12 @@ error[E0004]: non-exhaustive patterns: `43_i32` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i32` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i32 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
@@ -508,8 +732,12 @@ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
 LL |         m!(0, ..i64::MAX);
    |            ^ pattern `i64::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i64::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
@@ -517,8 +745,12 @@ error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `9223372036854775806_i64..=i64::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         9223372036854775806_i64..=i64::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i64::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
@@ -526,8 +758,12 @@ error[E0004]: non-exhaustive patterns: `i64::MIN` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i64::MIN` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i64::MIN => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
@@ -535,8 +771,12 @@ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i64::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i64::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i64` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
@@ -544,8 +784,12 @@ error[E0004]: non-exhaustive patterns: `43_i64` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i64` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i64 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i64` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:153:12
@@ -553,8 +797,12 @@ error[E0004]: non-exhaustive patterns: `43_i64` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i64` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i64 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
@@ -562,8 +810,12 @@ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
 LL |         m!(0, ..i128::MAX);
    |            ^ pattern `i128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
@@ -571,8 +823,12 @@ error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         170141183460469231731687303715884105726_i128..=i128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i128::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
@@ -580,8 +836,12 @@ error[E0004]: non-exhaustive patterns: `i128::MIN` not covered
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i128::MIN` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i128::MIN => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
@@ -589,8 +849,12 @@ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i128` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
@@ -598,8 +862,12 @@ error[E0004]: non-exhaustive patterns: `43_i128` not covered
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i128` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i128 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `43_i128` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:166:12
@@ -607,8 +875,12 @@ error[E0004]: non-exhaustive patterns: `43_i128` not covered
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i128` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         43_i128 => todo!() }
+   |
 
 error: aborting due to 68 previous errors
 
index 7c3c72e04cb781d32091328e33310422e858e473..c6f29fa59085d9258cf9636d2aa84076875ffddd 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 // FamilyType (GAT workaround)
 pub trait FamilyLt<'a> {
     type Out;
@@ -78,8 +80,6 @@ fn task<P>(processor: P) -> Task
 
 fn main() {
     task(annotate(
-        //~^ the size
-        //~^^ the trait bound
         Annotate::<RefMutFamily<usize>>::new(),
         |value: &mut usize| {
             *value = 2;
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
deleted file mode 100644 (file)
index 01b1466..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time
-  --> $DIR/issue-62529-1.rs:80:10
-   |
-LL |       task(annotate(
-   |  _____----_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |         Annotate::<RefMutFamily<usize>>::new(),
-...  |
-LL | |         }
-LL | |     ));
-   | |_____^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `impl Execute`
-note: required by a bound in `task`
-  --> $DIR/issue-62529-1.rs:69:9
-   |
-LL | fn task<P>(processor: P) -> Task
-   |         ^ required by this bound in `task`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | fn task<P: ?Sized>(processor: P) -> Task
-   |          ++++++++
-
-error[E0277]: the trait bound `impl Execute: Execute` is not satisfied
-  --> $DIR/issue-62529-1.rs:80:10
-   |
-LL |       task(annotate(
-   |  _____----_^
-   | |     |
-   | |     required by a bound introduced by this call
-LL | |
-LL | |
-LL | |         Annotate::<RefMutFamily<usize>>::new(),
-...  |
-LL | |         }
-LL | |     ));
-   | |_____^ the trait `Execute` is not implemented for `impl Execute`
-   |
-note: required by a bound in `task`
-  --> $DIR/issue-62529-1.rs:70:10
-   |
-LL | fn task<P>(processor: P) -> Task
-   |    ---- required by a bound in this
-LL | where P: Execute + 'static {
-   |          ^^^^^^^ required by this bound in `task`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
index 7da6b029c26f0f6ad6e712410fa3fe9e16a4fbf0..e6ffe38ee92e871329391f24edee74efa7b7bba1 100644 (file)
@@ -1,5 +1,5 @@
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:57:5
+  --> $DIR/issue-71955.rs:54:5
    |
 LL |     foo(bar, "string", |s| s.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -8,79 +8,7 @@ LL |     foo(bar, "string", |s| s.len() == 5);
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
 error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:57:5
-   |
-LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:57:5
-   |
-LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:57:5
-   |
-LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:57:5
-   |
-LL |     foo(bar, "string", |s| s.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:63:5
-   |
-LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:63:5
-   |
-LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:63:5
-   |
-LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:63:5
-   |
-LL |     foo(baz, "string", |s| s.0.len() == 5);
-   |     ^^^ implementation of `Parser` is not general enough
-   |
-   = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
-   = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
-
-error: implementation of `Parser` is not general enough
-  --> $DIR/issue-71955.rs:63:5
+  --> $DIR/issue-71955.rs:58:5
    |
 LL |     foo(baz, "string", |s| s.0.len() == 5);
    |     ^^^ implementation of `Parser` is not general enough
@@ -88,5 +16,5 @@ LL |     foo(baz, "string", |s| s.0.len() == 5);
    = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
    = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
 
-error: aborting due to 10 previous errors
+error: aborting due to 2 previous errors
 
index c2feaa91280557c001a6d88fe53b304e89e5905b..0f38f8e3283a278a5a6579706eee58b6e1fe4800 100644 (file)
@@ -1,8 +1,79 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-71955.rs:47:1
+error[E0308]: mismatched types
+  --> $DIR/issue-71955.rs:54:5
    |
-LL | fn main() {
-   | ^^^^^^^^^
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r, 's> FnOnce<(&'r &'s str,)>`
+              found type `for<'r> FnOnce<(&'r &str,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-71955.rs:54:24
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |                        ^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-71955.rs:34:9
+   |
+LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-71955.rs:54:5
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `FnOnce<(&&str,)>`
+              found type `for<'r> FnOnce<(&'r &str,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-71955.rs:54:24
+   |
+LL |     foo(bar, "string", |s| s.len() == 5);
+   |                        ^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-71955.rs:34:44
+   |
+LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
+   |                                            ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
+              found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-71955.rs:58:24
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |                        ^^^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-71955.rs:34:9
+   |
+LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-71955.rs:58:5
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `FnOnce<(&Wrapper<'_>,)>`
+              found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-71955.rs:58:24
+   |
+LL |     foo(baz, "string", |s| s.0.len() == 5);
+   |                        ^^^^^^^^^^^^^^^^^^
+note: the lifetime requirement is introduced here
+  --> $DIR/issue-71955.rs:34:44
+   |
+LL |     F2: FnOnce(&<F1 as Parser>::Output) -> bool
+   |                                            ^^^^
 
-error: aborting due to previous error
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
index 3d6778b6942c52c8213684d14fc30ae50ff1df9d..4b7e207b96d49d403512cc978ab55fdeb2f20434 100644 (file)
@@ -42,10 +42,7 @@ fn foo<F1, F2>(
 
 struct Wrapper<'a>(&'a str);
 
-// Because nll currently succeeds and migrate doesn't
-#[rustc_error]
 fn main() {
-    //[nll]~^ fatal
     fn bar<'a>(s: &'a str) -> (&'a str, &'a str) {
         (&s[..1], &s[..])
     }
@@ -56,14 +53,10 @@ fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) {
 
     foo(bar, "string", |s| s.len() == 5);
     //[migrate]~^ ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[nll]~^^ ERROR mismatched types
+    //[nll]~| ERROR mismatched types
     foo(baz, "string", |s| s.0.len() == 5);
     //[migrate]~^ ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
-    //[migrate]~| ERROR implementation of `Parser` is not general enough
+    //[nll]~^^ ERROR mismatched types
+    //[nll]~| ERROR mismatched types
 }
index 3a4d6c02a159fd06a0019ec6331950da6d1c15c5..fe319e6c8515c7ff51b02b48f72f0b70304220cd 100644 (file)
@@ -6,7 +6,8 @@ trait SomeTrait<'a> {
 
 fn give_me_ice<T>() {
     callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
-    //~^ ERROR: the trait bound `T: SomeTrait<'_>` is not satisfied
+    //~^ ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277]
+    //~| ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277]
 }
 
 fn callee<T: Fn<(&'static (),)>>() {
index aaf45dc7ad5642514b11428fa6b794403ab46369..13b68b072403a57b148fcca053f9d3b43ea5029c 100644 (file)
@@ -9,6 +9,17 @@ help: consider restricting type parameter `T`
 LL | fn give_me_ice<T: SomeTrait<'_>>() {
    |                 +++++++++++++++
 
-error: aborting due to previous error
+error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied
+  --> $DIR/issue-85455.rs:8:14
+   |
+LL |     callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn give_me_ice<T: SomeTrait<'_>>() {
+   |                 +++++++++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 4c9ec2a83ff37959c37c945fcd6866e3f8f0ab51..362c67dafd2c5e88c7d050ba45e0bdbcbdcfb7d3 100644 (file)
@@ -6,7 +6,7 @@ LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
    |                                                         |
    |                                                         `async` blocks are only allowed in Rust 2018 or later
    |
-   = help: set `edition = "2021"` in `Cargo.toml`
+   = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
index f661c62c9e4408db0c3a69d9226a06366f0cf80d..d1e5aa6c6b916878f1cdb70749e102411982e3fb 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(universal_impl_trait)]
-
 use std::fmt::Debug;
 
 fn foo<T>(x: impl Debug) { }
index 90c252537ef82b1b72f94e5fbc0a3fa3f3f9ec05..02c7fe8ff2c41ec4b82dd9b05c5f5dbdddae065d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/universal-issue-48703.rs:8:11
+  --> $DIR/universal-issue-48703.rs:6:11
    |
 LL |     foo::<String>('a');
    |           ^^^^^^ explicit generic argument not allowed
index 2ef8618192f6b8d14570544c74ab45db51e2aead..64333a29313b349d2187441020d27c7326be8c5b 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(question_mark, question_mark_carrier)]
-
 // Test that type inference fails where there are multiple possible return types
 // for the `?` operator.
 
index 86c533d7a59c9b81d8a87a68dfdede04f1b78b4b..e7d5fee18127fb54dd79b2c738acddd2f41a3134 100644 (file)
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed
-  --> $DIR/question-mark-type-infer.rs:12:21
+  --> $DIR/question-mark-type-infer.rs:10:21
    |
 LL |     l.iter().map(f).collect()?
    |                     ^^^^^^^ cannot infer type
index 3d8478f06db0ea0875c640774d7a3f371955ee0b..6eabd9b1015b79602886d27770a93f7de498c1fb 100644 (file)
@@ -29,6 +29,11 @@ fn foo6<const X: usize>() {}
 #[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] functions must only have
 fn foo8<X>() {}
 
+impl S {
+    #[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function
+    fn foo9<const X: usize>() {}
+}
+
 #[rustc_legacy_const_generics] //~ ERROR malformed `rustc_legacy_const_generics` attribute
 fn bar1() {}
 
index 1f55a8e72d2cb29795b0c1dcc37ff071a5d4a166..bfe7bb2e10dccf7d9cd14252eb430fc64a0cc78c 100644 (file)
@@ -7,13 +7,13 @@ LL | #[rustc_legacy_const_generics(0usize)]
    = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
 
 error: malformed `rustc_legacy_const_generics` attribute input
-  --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:32:1
+  --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:37:1
    |
 LL | #[rustc_legacy_const_generics]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]`
 
 error: malformed `rustc_legacy_const_generics` attribute input
-  --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:35:1
+  --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:40:1
    |
 LL | #[rustc_legacy_const_generics = 1]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]`
@@ -66,6 +66,14 @@ LL | #[rustc_legacy_const_generics(0)]
 LL | fn foo8<X>() {}
    |         - non-const generic parameter
 
+error: attribute should be applied to a function
+  --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:5
+   |
+LL |     #[rustc_legacy_const_generics(0)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn foo9<const X: usize>() {}
+   |     ---------------------------- not a function
+
 error: attribute should be applied to a function
   --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:5
    |
@@ -82,6 +90,6 @@ LL |     fn foo7<const X: usize>();
    |
    = help: replace the const parameters with concrete consts
 
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0044`.
index 60a2bf1e2d66083485e4539df7124141a9523d69..7dab7de7619704767303fc7f31bbc799e6eec94f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: cannot call non-const fn `Y::foo` in statics
-  --> $DIR/issue-16538.rs:15:23
+  --> $DIR/issue-16538.rs:14:23
    |
 LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
 
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:15:30
+  --> $DIR/issue-16538.rs:14:30
    |
 LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                              ^^^^ use of extern static
@@ -15,7 +15,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
 
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:15:21
+  --> $DIR/issue-16538.rs:14:21
    |
 LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
index b6891deb937da0af8a10319f2255d0b81c644dcd..270fa3014142732f78dc776dca3b3ed086e44e0a 100644 (file)
@@ -1,7 +1,6 @@
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
-#![feature(const_raw_ptr_deref)]
 mod Y {
     pub type X = usize;
     extern "C" {
index 2ba9dfa2bc5f844c62d484d8b4b80db45b1e37be..a18b0197d879ad41639489de6dcbee30657c0366 100644 (file)
@@ -1,5 +1,5 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:15:22
+  --> $DIR/issue-16538.rs:14:22
    |
 LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
@@ -7,7 +7,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    = 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[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-16538.rs:15:30
+  --> $DIR/issue-16538.rs:14:30
    |
 LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                              ^^^^ use of extern static
@@ -15,7 +15,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
 
 error[E0015]: cannot call non-const fn `Y::foo` in statics
-  --> $DIR/issue-16538.rs:15:23
+  --> $DIR/issue-16538.rs:14:23
    |
 LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
index ae6ec62be38ad5298c89a8738ffea5e1f386b9be..5f09b9587b15a0d2bdb58866dc90c0064bcc98e8 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(associated_consts)]
-
 trait Foo {
     const BAR: i32;
     fn foo(self) -> &'static i32 {
index 98cec1bfe9d990693e226cb734e6174afd9789f3..ced92bbd4848f50f76af3bd3a075b3ac5aebf189 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
-  --> $DIR/issue-27078.rs:5:12
+  --> $DIR/issue-27078.rs:3:12
    |
 LL |     fn foo(self) -> &'static i32 {
    |            ^^^^ doesn't have a size known at compile-time
index c7b6f1d58f33d798f691ce9554cce7d66049cc1d..6f3834d51a1ade945af777f2cc4675794d1ae50c 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(associated_consts)]
-
 trait VecN {
     const DIM: usize;
 }
index c555983ea68e0abed2b3dabca1d66f50d1eb689a..cd2a014bb683d7dd875fac773898fbe4e1246a88 100644 (file)
@@ -1,5 +1,5 @@
 error: constant expression depends on a generic parameter
-  --> $DIR/issue-39211.rs:11:17
+  --> $DIR/issue-39211.rs:9:17
    |
 LL |     let a = [3; M::Row::DIM];
    |                 ^^^^^^^^^^^
index 7c8bf299db5819a54cae5b1235222b5f6cff0267..ab3d30d401f06c8adb2a997ec9cdb82fca1735b8 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(use_extern_macros)]
 trait Foo {}
 #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
                          //~| ERROR failed to resolve: partially resolved path in a derive macro
index 2ffa15264b66df02da64b1734e6b6a0b9dd5efb3..40295b8a115308c09531b0c7b67140a5b91d2fe6 100644 (file)
@@ -1,11 +1,11 @@
 error[E0433]: failed to resolve: partially resolved path in a derive macro
-  --> $DIR/issue-46101.rs:3:10
+  --> $DIR/issue-46101.rs:2:10
    |
 LL | #[derive(Foo::Anything)]
    |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
 
 error[E0433]: failed to resolve: partially resolved path in a derive macro
-  --> $DIR/issue-46101.rs:3:10
+  --> $DIR/issue-46101.rs:2:10
    |
 LL | #[derive(Foo::Anything)]
    |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
index 0f33b52577b7071747c1cdc0ad88ef69e5b24e3f..98c141b6c6a1ddc943b53bfb01e7d80c4059459e 100644 (file)
@@ -1,14 +1,15 @@
+// check-fail
+// known-bug
+
 // Regression test for #47511: anonymous lifetimes can appear
 // unconstrained in a return type, but only if they appear just once
 // in the input, as the input to a projection.
 
 fn f(_: X) -> X {
-    //~^ ERROR return type references an anonymous lifetime
     unimplemented!()
 }
 
 fn g<'a>(_: X<'a>) -> X<'a> {
-    //~^ ERROR return type references lifetime `'a`, which is not constrained
     unimplemented!()
 }
 
index 4473c0e68cfc8d803ef8525124de5e2b9b23ad92..5b84f7ed62c3a18239eb36191ebbe7795660b496 100644 (file)
@@ -1,5 +1,5 @@
 error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
-  --> $DIR/issue-47511.rs:5:15
+  --> $DIR/issue-47511.rs:8:15
    |
 LL | fn f(_: X) -> X {
    |               ^
@@ -7,7 +7,7 @@ LL | fn f(_: X) -> X {
    = note: lifetimes appearing in an associated type are not considered constrained
 
 error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
-  --> $DIR/issue-47511.rs:10:23
+  --> $DIR/issue-47511.rs:12:23
    |
 LL | fn g<'a>(_: X<'a>) -> X<'a> {
    |                       ^^^^^
index 8f7c98d9a67a77baaee8f3f6332d56869631439c..8401c4a9d6cfd9ddc6787e3aa7a055ca163a78c0 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(macro_rules)]
-
 macro_rules! g {
     ($inp:ident) => (
         { $inp $nonexistent }
index 3fe3d4d9d67c268e82d4e92e32bc7e970289b1a5..4fa73a464fbbe10a8311c9b96b86a3c7b286f7ee 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$`
-  --> $DIR/issue-6596-2.rs:5:16
+  --> $DIR/issue-6596-2.rs:3:16
    |
 LL |         { $inp $nonexistent }
    |                ^^^^^^^^^^^^ expected one of 8 possible tokens
index d779753687ed5af1513029d48676637619a01af9..370cd72fd558d485f049cbd2cde2e36ae9a37b94 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/issue-75777.rs:13:5
+  --> $DIR/issue-75777.rs:11:5
    |
 LL | fn inject<'a, Env: 'a, A: 'a + Send>(v: A) -> Box<dyn FnOnce(&'a Env) -> BoxFuture<'a, A>> {
    |           -- lifetime `'a` defined here
index 291a3db093672c1632c47249fe6a64ccb8ea0539..357c07c7cec914ec97128f116e399818002df94b 100644 (file)
@@ -1,8 +1,6 @@
 // Regression test for #75777.
 // Checks that a boxed future can be properly constructed.
 
-#![feature(future_readiness_fns)]
-
 use std::future::{self, Future};
 use std::pin::Pin;
 
index bf271ab78f7ee1c40b48f49d402440711acd6436..f440d7d19321557c140a495a6d8e546888f3112c 100644 (file)
@@ -1,16 +1,16 @@
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/issue-75777.rs:13:14
+  --> $DIR/issue-75777.rs:11:14
    |
 LL |     Box::new(move |_| fut)
    |              ^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
-  --> $DIR/issue-75777.rs:11:11
+  --> $DIR/issue-75777.rs:9:11
    |
 LL | fn inject<'a, Env: 'a, A: 'a + Send>(v: A) -> Box<dyn FnOnce(&'a Env) -> BoxFuture<'a, A>> {
    |           ^^
 note: ...so that the types are compatible
-  --> $DIR/issue-75777.rs:13:14
+  --> $DIR/issue-75777.rs:11:14
    |
 LL |     Box::new(move |_| fut)
    |              ^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL |     Box::new(move |_| fut)
               found `(Pin<Box<(dyn Future<Output = A> + Send + 'a)>>,)`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the types are compatible
-  --> $DIR/issue-75777.rs:13:5
+  --> $DIR/issue-75777.rs:11:5
    |
 LL |     Box::new(move |_| fut)
    |     ^^^^^^^^^^^^^^^^^^^^^^
index 263c69bbc0b62444d7e2f4374855d84a30148328..567c59fd560d9b104ed0abadca413e1eca021a42 100644 (file)
@@ -1,5 +1,4 @@
 #![deny(unused_attributes)]
-#![feature(min_const_generics)]
 
 use std::marker::PhantomData;
 
index 26437ee4befdeee212c0b024ee85be99c3d9fcd0..703d272dc988b55865c5a0602d46e0fe6e3497c6 100644 (file)
@@ -1,11 +1,11 @@
 error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-78957.rs:6:16
+  --> $DIR/issue-78957.rs:5:16
    |
 LL | pub struct Foo<#[inline] const N: usize>;
    |                ^^^^^^^^^       - not a function or closure
 
 error: attribute should be applied to a function
-  --> $DIR/issue-78957.rs:8:16
+  --> $DIR/issue-78957.rs:7:16
    |
 LL | pub struct Bar<#[cold] const N: usize>;
    |                ^^^^^^^       - not a function
@@ -18,19 +18,19 @@ LL | #![deny(unused_attributes)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-78957.rs:11:23
+  --> $DIR/issue-78957.rs:10:23
    |
 LL | pub struct Baz<#[repr(C)] const N: usize>;
    |                       ^         - not a struct, enum, or union
 
 error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-78957.rs:14:17
+  --> $DIR/issue-78957.rs:13:17
    |
 LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
    |                 ^^^^^^^^^ -- not a function or closure
 
 error: attribute should be applied to a function
-  --> $DIR/issue-78957.rs:16:17
+  --> $DIR/issue-78957.rs:15:17
    |
 LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
    |                 ^^^^^^^ -- not a function
@@ -38,19 +38,19 @@ LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-78957.rs:19:24
+  --> $DIR/issue-78957.rs:18:24
    |
 LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
    |                        ^   -- not a struct, enum, or union
 
 error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-78957.rs:22:17
+  --> $DIR/issue-78957.rs:21:17
    |
 LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
    |                 ^^^^^^^^^ - not a function or closure
 
 error: attribute should be applied to a function
-  --> $DIR/issue-78957.rs:24:17
+  --> $DIR/issue-78957.rs:23:17
    |
 LL | pub struct Bar3<#[cold] T>(PhantomData<T>);
    |                 ^^^^^^^ - not a function
@@ -58,7 +58,7 @@ LL | pub struct Bar3<#[cold] T>(PhantomData<T>);
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-78957.rs:27:24
+  --> $DIR/issue-78957.rs:26:24
    |
 LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
    |                        ^   - not a struct, enum, or union
diff --git a/src/test/ui/issues/issue-87707.rs b/src/test/ui/issues/issue-87707.rs
new file mode 100644 (file)
index 0000000..26e9e2c
--- /dev/null
@@ -0,0 +1,16 @@
+// test for #87707
+// edition:2018
+// run-fail
+// exec-env:RUST_BACKTRACE=0
+// check-run-results
+
+use std::sync::Once;
+use std::panic;
+
+fn main() {
+    let o = Once::new();
+    let _ = panic::catch_unwind(|| {
+        o.call_once(|| panic!("Here Once instance is poisoned."));
+    });
+    o.call_once(|| {});
+}
diff --git a/src/test/ui/issues/issue-87707.run.stderr b/src/test/ui/issues/issue-87707.run.stderr
new file mode 100644 (file)
index 0000000..e6c9ea0
--- /dev/null
@@ -0,0 +1,3 @@
+thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:13:24
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:15:7
diff --git a/src/test/ui/lint/issue-87308.rs b/src/test/ui/lint/issue-87308.rs
deleted file mode 100644 (file)
index 48fbb2a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Regression test for issue #87308.
-
-// compile-flags: -Zunpretty=everybody_loops
-// check-pass
-
-macro_rules! foo {
-    () => { break 'x; }
-}
-
-pub fn main() {
-    'x: loop { foo!() }
-}
diff --git a/src/test/ui/lint/issue-87308.stdout b/src/test/ui/lint/issue-87308.stdout
deleted file mode 100644 (file)
index 4f81ee8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(prelude_import)]
-#![no_std]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-// Regression test for issue #87308.
-
-// compile-flags: -Zunpretty=everybody_loops
-// check-pass
-
-macro_rules! foo { () => { break 'x ; } }
-
-pub fn main() { loop {} }
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs b/src/test/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs
new file mode 100644 (file)
index 0000000..6b255b7
--- /dev/null
@@ -0,0 +1,45 @@
+// check-pass
+
+#![feature(lint_reasons)]
+
+#![warn(unused)]
+
+// This expect attribute should catch all lint triggers
+#[expect(unused_variables)]
+fn check_multiple_lints_1() {
+    let value_i = 0xff00ff;
+    let value_ii = 0xff00ff;
+    let value_iii = 0xff00ff;
+    let value_iiii = 0xff00ff;
+    let value_iiiii = 0xff00ff;
+}
+
+// This expect attribute should catch all lint triggers
+#[expect(unused_mut)]
+fn check_multiple_lints_2() {
+    let mut a = 0xa;
+    let mut b = 0xb;
+    let mut c = 0xc;
+    println!("The ABC goes as: {:#x} {:#x} {:#x}", a, b, c);
+}
+
+// This expect attribute should catch all lint triggers
+#[expect(while_true)]
+fn check_multiple_lints_3() {
+    // `while_true` is an early lint
+    while true {}
+
+    while true {}
+
+    while true {}
+
+    while true {}
+
+    while true {}
+}
+
+fn main() {
+    check_multiple_lints_1();
+    check_multiple_lints_2();
+    check_multiple_lints_3();
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs b/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs
new file mode 100644 (file)
index 0000000..9f591ba
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(lint_reasons)]
+
+#![warn(unused)]
+
+#![expect(unused_mut)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
+
+#![expect(unused_variables)]
+
+fn main() {
+    let x = 0;
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr b/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr
new file mode 100644 (file)
index 0000000..7237f6f
--- /dev/null
@@ -0,0 +1,10 @@
+warning: this lint expectation is unfulfilled
+  --> $DIR/crate_level_expect.rs:7:11
+   |
+LL | #![expect(unused_mut)]
+   |           ^^^^^^^^^^
+   |
+   = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs
new file mode 100644 (file)
index 0000000..b95815b
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(lint_reasons)]
+
+#![warn(unused)]
+
+macro_rules! expect_inside_macro {
+    () => {
+        #[expect(unused_variables)]
+        let x = 0;
+    };
+}
+
+fn main() {
+    expect_inside_macro!();
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs
new file mode 100644 (file)
index 0000000..07c60fa
--- /dev/null
@@ -0,0 +1,42 @@
+// check-pass
+
+#![feature(lint_reasons)]
+
+#![warn(unused_variables)]
+
+macro_rules! trigger_unused_variables_macro {
+    () => {
+        let x = 0;
+        //~^ WARNING unused variable: `x` [unused_variables]
+        //~| WARNING unused variable: `x` [unused_variables]
+    };
+}
+
+pub fn check_macro() {
+    // This should trigger the `unused_variables` from inside the macro
+    trigger_unused_variables_macro!();
+}
+
+// This should be fulfilled by the macro
+#[expect(unused_variables)]
+pub fn check_expect_on_item() {
+    trigger_unused_variables_macro!();
+}
+
+pub fn check_expect_on_macro() {
+    // This should be fulfilled by the macro
+    #[expect(unused_variables)]
+    trigger_unused_variables_macro!();
+
+    // FIXME: Lint attributes currently don't work directly on macros, and
+    // therefore also doesn't work for the new `expect` attribute. This bug
+    // is being tracked in rust#87391. The test will until then produce two
+    // warnings about the unused variable x.
+    //
+    // The expectation is still marked as fulfilled. I'm not totally why but
+    // my guess is that this will remain working when rust#87391 has been fixed.
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr
new file mode 100644 (file)
index 0000000..817e16f
--- /dev/null
@@ -0,0 +1,29 @@
+warning: unused variable: `x`
+  --> $DIR/expect_lint_from_macro.rs:9:13
+   |
+LL |         let x = 0;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_x`
+...
+LL |     trigger_unused_variables_macro!();
+   |     --------------------------------- in this macro invocation
+   |
+note: the lint level is defined here
+  --> $DIR/expect_lint_from_macro.rs:5:9
+   |
+LL | #![warn(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unused variable: `x`
+  --> $DIR/expect_lint_from_macro.rs:9:13
+   |
+LL |         let x = 0;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_x`
+...
+LL |     trigger_unused_variables_macro!();
+   |     --------------------------------- in this macro invocation
+   |
+   = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs
new file mode 100644 (file)
index 0000000..928e161
--- /dev/null
@@ -0,0 +1,9 @@
+// should error due to missing feature gate.
+
+#![warn(unused)]
+
+#[expect(unused)]
+//~^ ERROR: the `#[expect]` attribute is an experimental feature [E0658]
+fn main() {
+    let x = 1;
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr
new file mode 100644 (file)
index 0000000..b5601cf
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: the `#[expect]` attribute is an experimental feature
+  --> $DIR/expect_missing_feature_gate.rs:5:1
+   |
+LL | #[expect(unused)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #54503 <https://github.com/rust-lang/rust/issues/54503> for more information
+   = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs
new file mode 100644 (file)
index 0000000..dc9a719
--- /dev/null
@@ -0,0 +1,58 @@
+// check-pass
+
+#![feature(lint_reasons)]
+
+#![warn(unused)]
+
+// The warnings are not double triggers, they identify different unfulfilled lint
+// expectations one for each listed lint.
+
+#[expect(unused_variables, unused_mut, while_true)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
+//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+fn check_multiple_lints_1() {
+    // This only trigger `unused_variables`
+    let who_am_i = 666;
+}
+
+#[expect(unused_variables, unused_mut, while_true)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+fn check_multiple_lints_2() {
+    // This only triggers `unused_mut`
+    let mut x = 0;
+    println!("I use x: {}", x);
+}
+
+#[expect(unused_variables, unused_mut, while_true)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+fn check_multiple_lints_3() {
+    // This only triggers `while_true` which is also an early lint
+    while true {}
+}
+
+#[expect(unused, while_true)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+fn check_multiple_lints_with_lint_group_1() {
+    let who_am_i = 666;
+
+    let mut x = 0;
+    println!("I use x: {}", x);
+}
+
+#[expect(unused, while_true)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+fn check_multiple_lints_with_lint_group_2() {
+    while true {}
+}
+
+fn main() {
+    check_multiple_lints_1();
+    check_multiple_lints_2();
+    check_multiple_lints_3();
+
+    check_multiple_lints_with_lint_group_1();
+    check_multiple_lints_with_lint_group_2();
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr
new file mode 100644 (file)
index 0000000..90ee744
--- /dev/null
@@ -0,0 +1,52 @@
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:10:28
+   |
+LL | #[expect(unused_variables, unused_mut, while_true)]
+   |                            ^^^^^^^^^^
+   |
+   = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:10:40
+   |
+LL | #[expect(unused_variables, unused_mut, while_true)]
+   |                                        ^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:19:10
+   |
+LL | #[expect(unused_variables, unused_mut, while_true)]
+   |          ^^^^^^^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:19:40
+   |
+LL | #[expect(unused_variables, unused_mut, while_true)]
+   |                                        ^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:28:10
+   |
+LL | #[expect(unused_variables, unused_mut, while_true)]
+   |          ^^^^^^^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:28:28
+   |
+LL | #[expect(unused_variables, unused_mut, while_true)]
+   |                            ^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:36:18
+   |
+LL | #[expect(unused, while_true)]
+   |                  ^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_multiple_lints.rs:45:10
+   |
+LL | #[expect(unused, while_true)]
+   |          ^^^^^^
+
+warning: 8 warnings emitted
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs
new file mode 100644 (file)
index 0000000..8f94bd6
--- /dev/null
@@ -0,0 +1,53 @@
+// ignore-tidy-linelength
+
+#![feature(lint_reasons)]
+#![warn(unused_mut)]
+
+#[expect(
+    unused_mut,
+    //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+    //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
+    //~| NOTE this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered
+    reason = "this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered"
+)]
+mod foo {
+    fn bar() {
+        #[allow(
+            unused_mut,
+            reason = "this overrides the previous `expect` lint level and allows the `unused_mut` lint here"
+        )]
+        let mut v = 0;
+    }
+}
+
+#[expect(
+    unused_mut,
+    //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+    //~| NOTE this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered
+    reason = "this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered"
+)]
+mod oof {
+    #[warn(
+        unused_mut,
+        //~^ NOTE the lint level is defined here
+        reason = "this overrides the previous `expect` lint level and warns about the `unused_mut` lint here"
+    )]
+    fn bar() {
+        let mut v = 0;
+        //~^ WARNING variable does not need to be mutable [unused_mut]
+        //~| NOTE this overrides the previous `expect` lint level and warns about the `unused_mut` lint here
+        //~| HELP remove this `mut`
+    }
+}
+
+#[expect(unused_variables)]
+//~^ WARNING this lint expectation is unfulfilled
+#[forbid(unused_variables)]
+//~^ NOTE the lint level is defined here
+fn check_expect_then_forbid() {
+    let this_is_my_function = 3;
+    //~^ ERROR unused variable: `this_is_my_function` [unused_variables]
+    //~| HELP if this is intentional, prefix it with an underscore
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
new file mode 100644 (file)
index 0000000..370e51b
--- /dev/null
@@ -0,0 +1,52 @@
+error: unused variable: `this_is_my_function`
+  --> $DIR/expect_nested_lint_levels.rs:48:9
+   |
+LL |     let this_is_my_function = 3;
+   |         ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_is_my_function`
+   |
+note: the lint level is defined here
+  --> $DIR/expect_nested_lint_levels.rs:45:10
+   |
+LL | #[forbid(unused_variables)]
+   |          ^^^^^^^^^^^^^^^^
+
+warning: variable does not need to be mutable
+  --> $DIR/expect_nested_lint_levels.rs:36:13
+   |
+LL |         let mut v = 0;
+   |             ----^
+   |             |
+   |             help: remove this `mut`
+   |
+   = note: this overrides the previous `expect` lint level and warns about the `unused_mut` lint here
+note: the lint level is defined here
+  --> $DIR/expect_nested_lint_levels.rs:31:9
+   |
+LL |         unused_mut,
+   |         ^^^^^^^^^^
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_nested_lint_levels.rs:7:5
+   |
+LL |     unused_mut,
+   |     ^^^^^^^^^^
+   |
+   = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+   = note: this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_nested_lint_levels.rs:24:5
+   |
+LL |     unused_mut,
+   |     ^^^^^^^^^^
+   |
+   = note: this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered
+
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_nested_lint_levels.rs:43:10
+   |
+LL | #[expect(unused_variables)]
+   |          ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 4 warnings emitted
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs
new file mode 100644 (file)
index 0000000..479ee19
--- /dev/null
@@ -0,0 +1,34 @@
+#![feature(lint_reasons)]
+
+#[forbid(unused_variables)]
+//~^ NOTE `forbid` level set here
+//~| NOTE `forbid` level set here
+#[expect(unused_variables)]
+//~^ ERROR incompatible with previous forbid [E0453]
+//~| NOTE overruled by previous forbid
+//~| ERROR incompatible with previous forbid [E0453]
+//~| NOTE overruled by previous forbid
+fn expect_forbidden_lint_1() {}
+
+#[forbid(while_true)]
+//~^ NOTE `forbid` level set here
+//~| NOTE `forbid` level set here
+//~| NOTE the lint level is defined here
+#[expect(while_true)]
+//~^ ERROR incompatible with previous forbid [E0453]
+//~| NOTE overruled by previous forbid
+//~| ERROR incompatible with previous forbid [E0453]
+//~| NOTE overruled by previous forbid
+fn expect_forbidden_lint_2() {
+    // This while loop will produce a `while_true` lint as the lint level
+    // at this node is still `forbid` and the `while_true` check happens
+    // before the compilation terminates due to `E0453`
+    while true {}
+    //~^ ERROR denote infinite loops with `loop { ... }`
+    //~| HELP use `loop`
+}
+
+fn main() {
+    expect_forbidden_lint_1();
+    expect_forbidden_lint_2();
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr
new file mode 100644 (file)
index 0000000..a8116e9
--- /dev/null
@@ -0,0 +1,51 @@
+error[E0453]: expect(unused_variables) incompatible with previous forbid
+  --> $DIR/expect_with_forbid.rs:6:10
+   |
+LL | #[forbid(unused_variables)]
+   |          ---------------- `forbid` level set here
+...
+LL | #[expect(unused_variables)]
+   |          ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: expect(while_true) incompatible with previous forbid
+  --> $DIR/expect_with_forbid.rs:17:10
+   |
+LL | #[forbid(while_true)]
+   |          ---------- `forbid` level set here
+...
+LL | #[expect(while_true)]
+   |          ^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: expect(unused_variables) incompatible with previous forbid
+  --> $DIR/expect_with_forbid.rs:6:10
+   |
+LL | #[forbid(unused_variables)]
+   |          ---------------- `forbid` level set here
+...
+LL | #[expect(unused_variables)]
+   |          ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: expect(while_true) incompatible with previous forbid
+  --> $DIR/expect_with_forbid.rs:17:10
+   |
+LL | #[forbid(while_true)]
+   |          ---------- `forbid` level set here
+...
+LL | #[expect(while_true)]
+   |          ^^^^^^^^^^ overruled by previous forbid
+
+error: denote infinite loops with `loop { ... }`
+  --> $DIR/expect_with_forbid.rs:26:5
+   |
+LL |     while true {}
+   |     ^^^^^^^^^^ help: use `loop`
+   |
+note: the lint level is defined here
+  --> $DIR/expect_with_forbid.rs:13:10
+   |
+LL | #[forbid(while_true)]
+   |          ^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs
new file mode 100644 (file)
index 0000000..b4183d9
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(lint_reasons)]
+#![warn(unused)]
+
+#![expect(unused_variables, reason = "<This should fail and display this reason>")]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
+//~| NOTE <This should fail and display this reason>
+
+fn main() {}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr
new file mode 100644 (file)
index 0000000..82c1a4c
--- /dev/null
@@ -0,0 +1,11 @@
+warning: this lint expectation is unfulfilled
+  --> $DIR/expect_with_reason.rs:6:11
+   |
+LL | #![expect(unused_variables, reason = "<This should fail and display this reason>")]
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+   = note: <This should fail and display this reason>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs b/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs
new file mode 100644 (file)
index 0000000..6624b93
--- /dev/null
@@ -0,0 +1,23 @@
+// check-pass
+
+#![feature(lint_reasons)]
+
+fn expect_early_pass_lints() {
+    #[expect(while_true)]
+    while true {
+        println!("I never stop")
+    }
+
+    #[expect(unused_doc_comments)]
+    /// This comment triggers the `unused_doc_comments` lint
+    let _sheep = "wolf";
+
+    let x = 123;
+    #[expect(ellipsis_inclusive_range_patterns)]
+    match x {
+        0...100 => {}
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs b/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs
new file mode 100644 (file)
index 0000000..5d928b3
--- /dev/null
@@ -0,0 +1,43 @@
+// check-pass
+
+#![feature(lint_reasons)]
+#![warn(unused)]
+
+#[expect(unused_variables)]
+fn check_specific_lint() {
+    let x = 2;
+}
+
+#[expect(unused)]
+fn check_lint_group() {
+    let x = 15;
+}
+
+#[expect(unused_variables)]
+fn check_multiple_lint_emissions() {
+    let r = 1;
+    let u = 8;
+    let s = 2;
+    let t = 9;
+}
+
+mod check_fulfilled_expect_in_macro {
+    macro_rules! expect_inside_macro {
+        () => {
+            #[expect(unused_variables)]
+            let x = 0;
+        };
+    }
+
+    pub fn check_macro() {
+        expect_inside_macro!();
+    }
+}
+
+fn main() {
+    check_specific_lint();
+    check_lint_group();
+    check_multiple_lint_emissions();
+
+    check_fulfilled_expect_in_macro::check_macro();
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs b/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs
new file mode 100644 (file)
index 0000000..bafdea9
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(lint_reasons)]
+
+#![deny(unused_attributes)]
+
+#[allow(reason = "I want to allow something")]//~ ERROR unused attribute
+#[expect(reason = "I don't know what I'm waiting for")]//~ ERROR unused attribute
+#[warn(reason = "This should be warn by default")]//~ ERROR unused attribute
+#[deny(reason = "All listed lints are denied")]//~ ERROR unused attribute
+#[forbid(reason = "Just some reason")]//~ ERROR unused attribute
+
+#[allow(clippy::box_collection, reason = "This is still valid")]
+#[warn(dead_code, reason = "This is also reasonable")]
+
+fn main() {}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr b/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr
new file mode 100644 (file)
index 0000000..3bf8137
--- /dev/null
@@ -0,0 +1,47 @@
+error: unused attribute
+  --> $DIR/lint-attribute-only-with-reason.rs:5:1
+   |
+LL | #[allow(reason = "I want to allow something")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: the lint level is defined here
+  --> $DIR/lint-attribute-only-with-reason.rs:3:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+   = note: attribute `allow` without any lints has no effect
+
+error: unused attribute
+  --> $DIR/lint-attribute-only-with-reason.rs:6:1
+   |
+LL | #[expect(reason = "I don't know what I'm waiting for")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: attribute `expect` without any lints has no effect
+
+error: unused attribute
+  --> $DIR/lint-attribute-only-with-reason.rs:7:1
+   |
+LL | #[warn(reason = "This should be warn by default")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: attribute `warn` without any lints has no effect
+
+error: unused attribute
+  --> $DIR/lint-attribute-only-with-reason.rs:8:1
+   |
+LL | #[deny(reason = "All listed lints are denied")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: attribute `deny` without any lints has no effect
+
+error: unused attribute
+  --> $DIR/lint-attribute-only-with-reason.rs:9:1
+   |
+LL | #[forbid(reason = "Just some reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: attribute `forbid` without any lints has no effect
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs b/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs
new file mode 100644 (file)
index 0000000..98080b4
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(lint_reasons)]
+#![warn(unused)]
+
+#[warn(unused_variables)]
+#[expect(unused_variables)]
+//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
+//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
+#[allow(unused_variables)]
+#[expect(unused_variables)] // Only this expectation will be fulfilled
+fn main() {
+    let x = 2;
+}
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr b/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr
new file mode 100644 (file)
index 0000000..df7d658
--- /dev/null
@@ -0,0 +1,10 @@
+warning: this lint expectation is unfulfilled
+  --> $DIR/multiple_expect_attrs.rs:7:10
+   |
+LL | #[expect(unused_variables)]
+   |          ^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+
+warning: 1 warning emitted
+
index 50e6b81dcf4b4a62a95111d230bb6a7b061638af..f66afa94f4da71fe9db1e389001a7d101c97c3da 100644 (file)
@@ -1,6 +1,6 @@
 warning: Linking globals named 'foo': symbol multiply defined!
 
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.HASH-cgu.0.rcgu.o": 
+error: failed to load bitcode of module "lto-duplicate-symbols2.lto_duplicate_symbols2.HASH-cgu.0.rcgu.o": 
 
 error: aborting due to previous error; 1 warning emitted
 
index c74aaf42bf21b5276b96905792a856b6e3212f7c..26e1f2afa91bb81f1d76cfca0813a26592ad3872 100644 (file)
@@ -1,7 +1,5 @@
 // Test for issue #50381: non-lifetime passed to :lifetime.
 
-#![feature(macro_lifetime_matcher)]
-
 macro_rules! m { ($x:lifetime) => { } }
 
 fn main() {
index 2cf1a792f9fc55d6a47103e8614fba05273d8f31..6234735dfc8a41779124de2cd5ae5bcfb2719a14 100644 (file)
@@ -1,5 +1,5 @@
 error: no rules expected the token `a`
-  --> $DIR/macro-non-lifetime.rs:8:8
+  --> $DIR/macro-non-lifetime.rs:6:8
    |
 LL | macro_rules! m { ($x:lifetime) => { } }
    | -------------- when calling this macro
index cd695ca916ea9aac354b35a6533fab14d6afe31c..d93792bdfe38d8cd8febba9870ae18f46823b8a4 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(extern_prelude)]
-
 mod m {
     fn check() {
         Vec::clone!(); //~ ERROR failed to resolve: `Vec` is a struct, not a module
index b68e89f07f67600c91c5fadd0f74ff15379277ef..f8377ffb3555673018dd4ad1ce4254c29b8bd847 100644 (file)
@@ -1,11 +1,11 @@
 error[E0433]: failed to resolve: `Vec` is a struct, not a module
-  --> $DIR/macro-path-prelude-fail-1.rs:5:9
+  --> $DIR/macro-path-prelude-fail-1.rs:3:9
    |
 LL |         Vec::clone!();
    |         ^^^ `Vec` is a struct, not a module
 
 error[E0433]: failed to resolve: `u8` is a builtin type, not a module
-  --> $DIR/macro-path-prelude-fail-1.rs:6:9
+  --> $DIR/macro-path-prelude-fail-1.rs:4:9
    |
 LL |         u8::clone!();
    |         ^^ `u8` is a builtin type, not a module
index 600b55c64d46027169335aff65cc5941dd6e45f9..d7181200085c46dec097f040e800d67e3e5f43ee 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:macro-in-other-crate.rs
 
-#![feature(decl_macro, extern_prelude)]
+#![feature(decl_macro)]
 
 macro_rules! add_macro_expanded_things_to_macro_prelude {() => {
     #[macro_use]
index e2eff7c1c2d6c83f6081bb1d4dac3b1195677a68..019f6a874cab3719395af067d12db0073f8c694b 100644 (file)
@@ -2,7 +2,10 @@
 
 #![feature(decl_macro)]
 #![feature(staged_api)]
-#[macro_use] extern crate unstable_macros;
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[macro_use]
+extern crate unstable_macros;
 
 #[unstable(feature = "local_unstable", issue = "none")]
 macro_rules! local_unstable { () => () }
index 34b62b4b1c3fdf051a0571568960f9b8ed38de51..75da9f47a3573e45a78d05e75f3d87b6cd189ab2 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature 'local_unstable'
-  --> $DIR/macro-stability.rs:19:5
+  --> $DIR/macro-stability.rs:22:5
    |
 LL |     local_unstable!();
    |     ^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     local_unstable!();
    = help: add `#![feature(local_unstable)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'local_unstable'
-  --> $DIR/macro-stability.rs:20:5
+  --> $DIR/macro-stability.rs:23:5
    |
 LL |     local_unstable_modern!();
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL |     local_unstable_modern!();
    = help: add `#![feature(local_unstable)]` to the crate attributes to enable
 
 error[E0658]: use of unstable library feature 'unstable_macros'
-  --> $DIR/macro-stability.rs:21:5
+  --> $DIR/macro-stability.rs:24:5
    |
 LL |     unstable_macro!();
    |     ^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |     unstable_macro!();
    = help: add `#![feature(unstable_macros)]` to the crate attributes to enable
 
 warning: use of deprecated macro `deprecated_macro`: deprecation reason
-  --> $DIR/macro-stability.rs:24:5
+  --> $DIR/macro-stability.rs:27:5
    |
 LL |     deprecated_macro!();
    |     ^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |     deprecated_macro!();
    = note: `#[warn(deprecated)]` on by default
 
 warning: use of deprecated macro `local_deprecated`: local deprecation reason
-  --> $DIR/macro-stability.rs:26:5
+  --> $DIR/macro-stability.rs:29:5
    |
 LL |     local_deprecated!();
    |     ^^^^^^^^^^^^^^^^
index f3acd80a7a48f0797a456bbd2b16794a135bcade..d7deeaed99da265dc77fa1519144cfcb4ce94437 100644 (file)
@@ -1,6 +1,5 @@
 mod m {
-//~^ ERROR `main` function not found
     // An inferred main entry point
     // must appear at the top of the crate
     fn main() { }
-}
+} //~ ERROR `main` function not found
index 754ff0f80eb9afc7d8305c810aeb1f07b94eb407..0058af9b79ebfe14cbbbf5ad5da956f75b74fc27 100644 (file)
@@ -1,16 +1,11 @@
 error[E0601]: `main` function not found in crate `main_wrong_location`
-  --> $DIR/main-wrong-location.rs:1:1
+  --> $DIR/main-wrong-location.rs:5:2
    |
-LL | / mod m {
-LL | |
-LL | |     // An inferred main entry point
-LL | |     // must appear at the top of the crate
-LL | |     fn main() { }
-LL | | }
-   | |_^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`)
+LL | }
+   |  ^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`)
    |
 note: here is a function named `main`
-  --> $DIR/main-wrong-location.rs:5:5
+  --> $DIR/main-wrong-location.rs:4:5
    |
 LL |     fn main() { }
    |     ^^^^^^^^^^^^^
index 5debfe1c566c4893f477988c03d7573eb2af6f71..6206dc85ea05f81c72ab6854ef03416a232cbcb5 100644 (file)
@@ -1,17 +1,19 @@
 error[E0004]: non-exhaustive patterns: `B` not covered
   --> $DIR/match_non_exhaustive.rs:23:11
    |
-LL | enum L { A, B }
-   | ---------------
-   | |           |
-   | |           not covered
-   | `L` defined here
-...
 LL |     match l { L::A => () };
    |           ^ pattern `B` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `L` defined here
+  --> $DIR/match_non_exhaustive.rs:10:13
+   |
+LL | enum L { A, B }
+   |      -      ^ not covered
    = note: the matched value is of type `L`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL |     match l { L::A => (), B => todo!() };
+   |                         ++++++++++++++
 
 error[E0004]: non-exhaustive patterns: type `E1` is non-empty
   --> $DIR/match_non_exhaustive.rs:28:11
@@ -19,8 +21,18 @@ error[E0004]: non-exhaustive patterns: type `E1` is non-empty
 LL |     match e1 {};
    |           ^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `E1` defined here
+  --> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1
+   |
+LL | pub enum E1 {}
+   | ^^^^^^^^^^^^^^
    = note: the matched value is of type `E1`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match e1 {
+LL +         _ => todo!(),
+LL ~     };
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/match_non_exhaustive.rs:30:11
@@ -28,8 +40,16 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match e2 { E2::A => (), E2::B => () };
    |           ^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `E2` defined here
+  --> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1
+   |
+LL | pub enum E2 { A, B }
+   | ^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `E2`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL |     match e2 { E2::A => (), E2::B => (), _ => todo!() };
+   |                                        ++++++++++++++
 
 error: aborting due to 3 previous errors
 
index 902a6ec81d60b9cd87d328c50e1a3c89f6495382..d62625faaaa083b1bf6a907ecfb645c72768c263 100644 (file)
@@ -30,4 +30,5 @@ fn main() {
     //~^ ERROR this function takes 1 argument but 0 arguments were supplied
     let ans = s("burma", "shave");
     //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+    //~| ERROR mismatched types
 }
index 264d7cbb9b1cb9c2fa7b1765ebf353751479a98e..9ae9c474162d94c4c221b4b312260253a781af40 100644 (file)
@@ -18,6 +18,12 @@ note: associated function defined here
 LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
    |                           ^^^^^^^^
 
+error[E0308]: mismatched types
+  --> $DIR/overloaded-calls-bad.rs:31:17
+   |
+LL |     let ans = s("burma", "shave");
+   |                 ^^^^^^^ expected `isize`, found `&str`
+
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:31:15
    |
@@ -32,7 +38,7 @@ note: associated function defined here
 LL |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
    |                           ^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0057, E0308.
 For more information about an error, try `rustc --explain E0057`.
index ae0c067bb5f3ebd5c4ca44d2bf8eeed420ec3d36..4d378f010ed4d54230d2d5cfc0d21f5142f1c4d5 100644 (file)
@@ -3,7 +3,7 @@
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(panic_handler, alloc_error_handler)]
+#![feature(alloc_error_handler)]
 
 #[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
index 6d867e2e8b48e12b980e564c72892b80f5fc37ef..2dc509f2c632da0b599b2be0beacc1a39c0f4594 100644 (file)
@@ -3,7 +3,7 @@
 
 #![no_std]
 #![crate_type = "staticlib"]
-#![feature(panic_handler, alloc_error_handler)]
+#![feature(alloc_error_handler)]
 
 #[panic_handler]
 fn panic(_: &core::panic::PanicInfo) -> ! {
index 6a35f5117efd66cb34430617489f69a2ba29624f..5113dc6ec08c44a80cab77f93b8e755a4e3c0a8f 100644 (file)
@@ -1,8 +1,8 @@
 error[E0601]: `main` function not found in crate `missing_main`
-  --> $DIR/missing-main.rs:2:1
+  --> $DIR/missing-main.rs:2:14
    |
 LL | fn mian() { }
-   | ^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/missing-main.rs`
+   |              ^ consider adding a `main` function to `$DIR/missing-main.rs`
 
 error: aborting due to previous error
 
index c9efccd15b7c5016a44e19abb2b680f1fb2fe18b..17c4a0496b6d882af86867574e33f5a8b43befbf 100644 (file)
@@ -1,8 +1,10 @@
 // Regression test for issue #55825
 // Tests that we don't emit a spurious warning in NLL mode
 
+// check-pass
+
 #![feature(nll)]
 
-const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } //~ ERROR const
+const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
 
 fn main() { }
diff --git a/src/test/ui/nll/issue-55825-const-fn.stderr b/src/test/ui/nll/issue-55825-const-fn.stderr
deleted file mode 100644 (file)
index c834f8b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: trait objects in const fn are unstable
-  --> $DIR/issue-55825-const-fn.rs:6:32
-   |
-LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #93706 <https://github.com/rust-lang/rust/issues/93706> for more information
-   = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/nll/lint-no-err.rs b/src/test/ui/nll/lint-no-err.rs
new file mode 100644 (file)
index 0000000..4b4169f
--- /dev/null
@@ -0,0 +1,28 @@
+// check-pass
+
+// mir borrowck previously incorrectly set `tainted_by_errors`
+// when buffering lints, which resulted in ICE later on,
+// see #94502.
+
+// Errors with `nll` which is already tested in enough other tests,
+// so we ignore it here.
+//
+// ignore-compare-mode-nll
+
+struct Repro;
+impl Repro {
+    fn get(&self) -> &i32 {
+        &3
+    }
+
+    fn insert(&mut self, _: i32) {}
+}
+
+fn main() {
+    let x = &0;
+    let mut conflict = Repro;
+    let prev = conflict.get();
+    conflict.insert(*prev + *x);
+    //~^ WARN cannot borrow `conflict` as mutable because it is also borrowed as immutable
+    //~| WARN this borrowing pattern was not meant to be accepted
+}
diff --git a/src/test/ui/nll/lint-no-err.stderr b/src/test/ui/nll/lint-no-err.stderr
new file mode 100644 (file)
index 0000000..1e7aecf
--- /dev/null
@@ -0,0 +1,17 @@
+warning: cannot borrow `conflict` as mutable because it is also borrowed as immutable
+  --> $DIR/lint-no-err.rs:25:5
+   |
+LL |     let prev = conflict.get();
+   |                -------------- immutable borrow occurs here
+LL |     conflict.insert(*prev + *x);
+   |     ^^^^^^^^^^^^^^^^-----^^^^^^
+   |     |               |
+   |     |               immutable borrow later used here
+   |     mutable borrow occurs here
+   |
+   = note: `#[warn(mutable_borrow_reservation_conflict)]` on by default
+   = warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
+   = note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
+
+warning: 1 warning emitted
+
index 93a8506ab181f3553cd7fb45dc771d782918e810..4165c5dc13aaae07bdc05a6ed1c4cd75d78d56df 100644 (file)
@@ -1,5 +1,4 @@
 #![allow(dead_code)]
-#![feature(recover)]
 
 use std::panic::UnwindSafe;
 
index b95cd9173e3c0c2991f7781fcbd007a2f05d3a82..3e54df12376ba6cd30a6b9e5fa3b5ac033b794d4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the type `&mut i32` may not be safely transferred across an unwind boundary
-  --> $DIR/not-panic-safe.rs:9:5
+  --> $DIR/not-panic-safe.rs:8:5
    |
 LL |     assert::<&mut i32>();
    |     ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary
@@ -7,7 +7,7 @@ LL |     assert::<&mut i32>();
    = help: the trait `UnwindSafe` is not implemented for `&mut i32`
    = note: `UnwindSafe` is implemented for `&i32`, but not for `&mut i32`
 note: required by a bound in `assert`
-  --> $DIR/not-panic-safe.rs:6:14
+  --> $DIR/not-panic-safe.rs:5:14
    |
 LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
index 6df54638ce00425262306af2cad2ea9af9538321..2bc8e097859d3972420a68b98d07e710fd6e9f1e 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:21:5
+  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:5
    |
 LL | fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
    |      -- lifetime `'a` defined here
index ae2878539cfd1875d316219a73549e7ea161769d..dc0b86903c9e50cd0c45547241a7630b98b2cb7f 100644 (file)
@@ -2,7 +2,6 @@
 // through the `MyBox` struct.
 
 #![allow(dead_code)]
-#![feature(rustc_error)]
 
 trait Test {
     fn foo(&self) { }
index 07c321ed8c3449a317b50f601b57e9de11e47add..1649841c186854551bcc702dcc5245229bb7ad33 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:21:12
+  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:12
    |
 LL |     ss.t = t;
    |            ^ lifetime mismatch
@@ -7,7 +7,7 @@ LL |     ss.t = t;
    = note: expected reference `&'a MyBox<(dyn Test + 'static)>`
               found reference `&'a MyBox<(dyn Test + 'a)>`
 note: the lifetime `'a` as defined here...
-  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:6
+  --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:19:6
    |
 LL | fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
    |      ^^
diff --git a/src/test/ui/on-unimplemented/impl-substs.rs b/src/test/ui/on-unimplemented/impl-substs.rs
new file mode 100644 (file)
index 0000000..fe9c50e
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(rustc_attrs)]
+
+trait Foo<A> {
+    fn foo(self);
+}
+
+#[rustc_on_unimplemented = "an impl did not match: {A} {B} {C}"]
+impl<A, B, C> Foo<A> for (A, B, C) {
+    fn foo(self) {}
+}
+
+fn main() {
+    Foo::<usize>::foo((1i32, 1i32, 1i32));
+    //~^ ERROR the trait bound `(i32, i32, i32): Foo<usize>` is not satisfied
+}
diff --git a/src/test/ui/on-unimplemented/impl-substs.stderr b/src/test/ui/on-unimplemented/impl-substs.stderr
new file mode 100644 (file)
index 0000000..db66ab0
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0277]: the trait bound `(i32, i32, i32): Foo<usize>` is not satisfied
+  --> $DIR/impl-substs.rs:13:23
+   |
+LL |     Foo::<usize>::foo((1i32, 1i32, 1i32));
+   |     ----------------- ^^^^^^^^^^^^^^^^^^ an impl did not match: usize _ _
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 9aefe1e5a2156a0603194bda4867efc12861654c..3fd8c5cadca98c80db915fecde5cb2df4d2f979a 100644 (file)
@@ -1,7 +1,6 @@
 // Testing guarantees provided by once functions.
 // This program would segfault if it were legal.
 
-#![feature(once_fns)]
 use std::sync::Arc;
 
 fn foo<F:FnOnce()>(blk: F) {
index dde75724ed701fe5173bd4bdfa339f48e9c58a9c..335ac633822604cdc44558ae06defbf00d06c771 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `blk`
-  --> $DIR/once-cant-call-twice-on-heap.rs:9:5
+  --> $DIR/once-cant-call-twice-on-heap.rs:8:5
    |
 LL | fn foo<F:FnOnce()>(blk: F) {
    |                    --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
@@ -9,7 +9,7 @@ LL |     blk();
    |     ^^^ value used here after move
    |
 note: this value implements `FnOnce`, which causes it to be moved when called
-  --> $DIR/once-cant-call-twice-on-heap.rs:8:5
+  --> $DIR/once-cant-call-twice-on-heap.rs:7:5
    |
 LL |     blk();
    |     ^^^
index 44f334eee9386cf99d12306e276f32c53a10526c..9aa808e6bc9a69db9b07d19d49e945961335ce92 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `(2_u8..=u8::MAX, _)` not covered
 LL |     match (0u8, 0u8) {
    |           ^^^^^^^^^^ pattern `(2_u8..=u8::MAX, _)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(u8, u8)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         (0 | 1, 2 | 3) => {}
+LL +         (2_u8..=u8::MAX, _) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered
   --> $DIR/exhaustiveness-non-exhaustive.rs:9:11
@@ -13,8 +17,12 @@ error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered
 LL |     match ((0u8,),) {
    |           ^^^^^^^^^ pattern `((4_u8..=u8::MAX))` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `((u8,),)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         ((0 | 1,) | (2 | 3,),) => {}
+LL +         ((4_u8..=u8::MAX)) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered
   --> $DIR/exhaustiveness-non-exhaustive.rs:13:11
@@ -22,8 +30,12 @@ error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered
 LL |     match (Some(0u8),) {
    |           ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX))` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(Option<u8>,)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         (None | Some(0 | 1),) => {}
+LL +         (Some(2_u8..=u8::MAX)) => todo!()
+   |
 
 error: aborting due to 3 previous errors
 
index 8e6964e30623ddbe9932faf75e5668c72b17bfde..37a35700b36d5731ebc544d4e1de7a2ad5c43263 100644 (file)
@@ -18,8 +18,12 @@ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX
 LL |     match 0 {
    |           ^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         0 | (1 | 2) => {}
+LL +         i32::MIN..=-1_i32 | 3_i32..=i32::MAX => todo!()
+   |
 
 error: aborting due to 2 previous errors
 
index 208662b1c425df2655b37274f466a9a06239b524..047836203575ffb814eb6ca72d9bf841d493371c 100644 (file)
@@ -5,8 +5,6 @@
 // types of patterns that allow undelimited subpatterns that could cause the same ambiguity.
 // Currently, those should be impossible due to precedence rule. This test enforces that.
 
-#![feature(or_patterns)]
-
 enum E {
     A,
     B,
index 1d78d5193cb883d2e7be28da8e65f7912e60d1d6..2e25d8b3e7b0da43533aa088835e82b4b30ed530 100644 (file)
@@ -1,35 +1,35 @@
 error: top-level or-patterns are not allowed in `let` bindings
-  --> $DIR/nested-undelimited-precedence.rs:21:9
+  --> $DIR/nested-undelimited-precedence.rs:19:9
    |
 LL |     let b @ A | B: E = A;
    |         ^^^^^^^^^ help: wrap the pattern in parentheses: `(b @ A | B)`
 
 error: top-level or-patterns are not allowed in `let` bindings
-  --> $DIR/nested-undelimited-precedence.rs:36:9
+  --> $DIR/nested-undelimited-precedence.rs:34:9
    |
 LL |     let &A(_) | B(_): F = A(3);
    |         ^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&A(_) | B(_))`
 
 error: top-level or-patterns are not allowed in `let` bindings
-  --> $DIR/nested-undelimited-precedence.rs:38:9
+  --> $DIR/nested-undelimited-precedence.rs:36:9
    |
 LL |     let &&A(_) | B(_): F = A(3);
    |         ^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&A(_) | B(_))`
 
 error: top-level or-patterns are not allowed in `let` bindings
-  --> $DIR/nested-undelimited-precedence.rs:40:9
+  --> $DIR/nested-undelimited-precedence.rs:38:9
    |
 LL |     let &mut A(_) | B(_): F = A(3);
    |         ^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&mut A(_) | B(_))`
 
 error: top-level or-patterns are not allowed in `let` bindings
-  --> $DIR/nested-undelimited-precedence.rs:42:9
+  --> $DIR/nested-undelimited-precedence.rs:40:9
    |
 LL |     let &&mut A(_) | B(_): F = A(3);
    |         ^^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&mut A(_) | B(_))`
 
 error[E0408]: variable `b` is not bound in all patterns
-  --> $DIR/nested-undelimited-precedence.rs:21:17
+  --> $DIR/nested-undelimited-precedence.rs:19:17
    |
 LL |     let b @ A | B: E = A;
    |         -       ^ pattern doesn't bind `b`
@@ -37,7 +37,7 @@ LL |     let b @ A | B: E = A;
    |         variable not in all patterns
 
 error[E0308]: mismatched types
-  --> $DIR/nested-undelimited-precedence.rs:36:9
+  --> $DIR/nested-undelimited-precedence.rs:34:9
    |
 LL |     let &A(_) | B(_): F = A(3);
    |         ^^^^^         - expected due to this
@@ -48,7 +48,7 @@ LL |     let &A(_) | B(_): F = A(3);
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/nested-undelimited-precedence.rs:38:9
+  --> $DIR/nested-undelimited-precedence.rs:36:9
    |
 LL |     let &&A(_) | B(_): F = A(3);
    |         ^^^^^^         - expected due to this
@@ -59,7 +59,7 @@ LL |     let &&A(_) | B(_): F = A(3);
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/nested-undelimited-precedence.rs:40:9
+  --> $DIR/nested-undelimited-precedence.rs:38:9
    |
 LL |     let &mut A(_) | B(_): F = A(3);
    |         ^^^^^^^^^         - expected due to this
@@ -70,7 +70,7 @@ LL |     let &mut A(_) | B(_): F = A(3);
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/nested-undelimited-precedence.rs:42:9
+  --> $DIR/nested-undelimited-precedence.rs:40:9
    |
 LL |     let &&mut A(_) | B(_): F = A(3);
    |         ^^^^^^^^^^         - expected due to this
index 9c3c5dd360e07912754c13c0cac043f7e59b5069..a624cbc899ffc0ad76e331eff0cdf60bd528efb1 100644 (file)
@@ -2,8 +2,6 @@
 
 // edition:2018
 
-#![feature(or_patterns)]
-
 fn main() {}
 
 // Test the `pat` macro fragment parser:
index 7dbc3087663477117df5946f23e393261927d90a..001c68a9774737390acb8d46b8b6bec4a3f134fc 100644 (file)
@@ -1,5 +1,5 @@
 error: no rules expected the token `|`
-  --> $DIR/or-patterns-syntactic-fail-2018.rs:14:15
+  --> $DIR/or-patterns-syntactic-fail-2018.rs:12:15
    |
 LL | macro_rules! accept_pat {
    | ----------------------- when calling this macro
@@ -8,7 +8,7 @@ LL | accept_pat!(p | q);
    |               ^ no rules expected this token in macro call
 
 error: no rules expected the token `|`
-  --> $DIR/or-patterns-syntactic-fail-2018.rs:15:13
+  --> $DIR/or-patterns-syntactic-fail-2018.rs:13:13
    |
 LL | macro_rules! accept_pat {
    | ----------------------- when calling this macro
diff --git a/src/test/ui/parser/attr-with-a-semicolon.rs b/src/test/ui/parser/attr-with-a-semicolon.rs
new file mode 100644 (file)
index 0000000..56fe40b
--- /dev/null
@@ -0,0 +1,4 @@
+#[derive(Debug, Clone)]; //~ERROR expected item after attributes
+struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/parser/attr-with-a-semicolon.stderr b/src/test/ui/parser/attr-with-a-semicolon.stderr
new file mode 100644 (file)
index 0000000..49ed301
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected item after attributes
+  --> $DIR/attr-with-a-semicolon.rs:1:1
+   |
+LL | #[derive(Debug, Clone)];
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider removing this semicolon
+   |
+LL - #[derive(Debug, Clone)];
+LL + #[derive(Debug, Clone)]
+   | 
+
+error: aborting due to previous error
+
index e60cc153e670fbe0103316d217aacc470b2f4937..7ff75233d3a8e019c3afcb3e3bffac7c0250fbe9 100644 (file)
@@ -5,6 +5,6 @@
 type A where 'a: 'b + 'c = u8; // OK
 type A where = u8; // OK
 type A where 'a: 'b + = u8; // OK
-type A where , = u8; //~ ERROR expected one of `;`, `=`, lifetime, or type, found `,`
+type A where , = u8; //~ ERROR expected one of `;`, `=`, `where`, lifetime, or type, found `,`
 
 fn main() {}
index 950fa46c66b7e3bd38722b31bfb0771fb57ecb77..785a1fb679324fbbcac0cc5e4451b774f98c2db1 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `;`, `=`, lifetime, or type, found `,`
+error: expected one of `;`, `=`, `where`, lifetime, or type, found `,`
   --> $DIR/bounds-lifetime-where.rs:8:14
    |
 LL | type A where , = u8;
-   |              ^ expected one of `;`, `=`, lifetime, or type
+   |              ^ expected one of `;`, `=`, `where`, lifetime, or type
 
 error: aborting due to previous error
 
index 56befe3a0a75d7eff1216f6c2080a11176b488c9..8af7838c7913850179d3b6f6a4bbed7b6a79a423 100644 (file)
@@ -5,10 +5,10 @@ LL | #![allow(unused_variables)];
    |                            ^ help: remove this semicolon
 
 error[E0601]: `main` function not found in crate `issue_49040`
-  --> $DIR/issue-49040.rs:1:1
+  --> $DIR/issue-49040.rs:1:29
    |
 LL | #![allow(unused_variables)];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
+   |                             ^ consider adding a `main` function to `$DIR/issue-49040.rs`
 
 error: aborting due to 2 previous errors
 
index 5b551addbc893dc519125034532b4480cdfc1e83..cc69af44a13ca2d0393954df1de758c148a000e8 100644 (file)
@@ -1 +1 @@
-type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, or `<`, found `/`
+type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/`
index 5b388ff4ce0597cc5a506c3f74a6b74e06810aa4..914de43e62d66fa904ce4e67cd734247be1b5eeb 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `!`, `(`, `::`, `;`, or `<`, found `/`
+error: expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/`
   --> $DIR/removed-syntax-ptr-lifetime.rs:1:22
    |
 LL | type bptr = &lifetime/isize;
-   |                      ^ expected one of `!`, `(`, `::`, `;`, or `<`
+   |                      ^ expected one of `!`, `(`, `::`, `;`, `<`, or `where`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/trailing-question-in-macro-type.rs b/src/test/ui/parser/trailing-question-in-macro-type.rs
new file mode 100644 (file)
index 0000000..e2a681d
--- /dev/null
@@ -0,0 +1,14 @@
+macro_rules! fn_expr {
+    ($return_type:ty : $body:expr) => {
+        (|| -> $return_type { $body })()
+    };
+    ($body:expr) => {
+        (|| $body)()
+    };
+}
+
+
+fn main() {
+    fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) };
+    //~^ ERROR cannot find value `o` in this scope
+}
diff --git a/src/test/ui/parser/trailing-question-in-macro-type.stderr b/src/test/ui/parser/trailing-question-in-macro-type.stderr
new file mode 100644 (file)
index 0000000..c096ae0
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `o` in this scope
+  --> $DIR/trailing-question-in-macro-type.rs:12:15
+   |
+LL |     fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) };
+   |               ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/type-alias-where-fixable.fixed b/src/test/ui/parser/type-alias-where-fixable.fixed
new file mode 100644 (file)
index 0000000..41dd106
--- /dev/null
@@ -0,0 +1,30 @@
+// check-pass
+// run-rustfix
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+    // Fine.
+    type Assoc where u32: Copy;
+    // Fine.
+    type Assoc2 where u32: Copy, i32: Copy;
+}
+
+impl Trait for u32 {
+    // Not fine, suggests moving.
+    type Assoc  = () where u32: Copy;
+    //~^ WARNING where clause not allowed here
+    // Not fine, suggests moving `u32: Copy`
+    type Assoc2  = () where i32: Copy, u32: Copy;
+    //~^ WARNING where clause not allowed here
+}
+
+impl Trait for i32 {
+    // Fine.
+    type Assoc = () where u32: Copy;
+    // Not fine, suggests moving both.
+    type Assoc2  = () where u32: Copy, i32: Copy;
+    //~^ WARNING where clause not allowed here
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/type-alias-where-fixable.rs b/src/test/ui/parser/type-alias-where-fixable.rs
new file mode 100644 (file)
index 0000000..562a530
--- /dev/null
@@ -0,0 +1,30 @@
+// check-pass
+// run-rustfix
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+    // Fine.
+    type Assoc where u32: Copy;
+    // Fine.
+    type Assoc2 where u32: Copy, i32: Copy;
+}
+
+impl Trait for u32 {
+    // Not fine, suggests moving.
+    type Assoc where u32: Copy = ();
+    //~^ WARNING where clause not allowed here
+    // Not fine, suggests moving `u32: Copy`
+    type Assoc2 where u32: Copy = () where i32: Copy;
+    //~^ WARNING where clause not allowed here
+}
+
+impl Trait for i32 {
+    // Fine.
+    type Assoc = () where u32: Copy;
+    // Not fine, suggests moving both.
+    type Assoc2 where u32: Copy, i32: Copy = ();
+    //~^ WARNING where clause not allowed here
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/type-alias-where-fixable.stderr b/src/test/ui/parser/type-alias-where-fixable.stderr
new file mode 100644 (file)
index 0000000..7ec1a96
--- /dev/null
@@ -0,0 +1,42 @@
+warning: where clause not allowed here
+  --> $DIR/type-alias-where-fixable.rs:15:16
+   |
+LL |     type Assoc where u32: Copy = ();
+   |                ^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_where_clause_location)]` on by default
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+help: move it to the end of the type declaration
+   |
+LL -     type Assoc where u32: Copy = ();
+LL +     type Assoc  = () where u32: Copy;
+   | 
+
+warning: where clause not allowed here
+  --> $DIR/type-alias-where-fixable.rs:18:17
+   |
+LL |     type Assoc2 where u32: Copy = () where i32: Copy;
+   |                 ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+help: move it to the end of the type declaration
+   |
+LL -     type Assoc2 where u32: Copy = () where i32: Copy;
+LL +     type Assoc2  = () where i32: Copy, u32: Copy;
+   | 
+
+warning: where clause not allowed here
+  --> $DIR/type-alias-where-fixable.rs:26:17
+   |
+LL |     type Assoc2 where u32: Copy, i32: Copy = ();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+help: move it to the end of the type declaration
+   |
+LL -     type Assoc2 where u32: Copy, i32: Copy = ();
+LL +     type Assoc2  = () where u32: Copy, i32: Copy;
+   | 
+
+warning: 3 warnings emitted
+
index a9fa23dd95ef4eceda62e7de1c2d340ef88f09ad..f6e7dfb7b7b2ecd5788cf525625f2b4dc44060b6 100644 (file)
@@ -6,32 +6,8 @@
 type Foo where u32: Copy = ();
 // Not fine.
 type Bar = () where u32: Copy;
-//~^ ERROR where clause not allowed here
+//~^ ERROR where clauses are not allowed
 type Baz = () where;
-//~^ ERROR where clause not allowed here
-
-trait Trait {
-    // Fine.
-    type Assoc where u32: Copy;
-    // Fine.
-    type Assoc2 where u32: Copy, i32: Copy;
-}
-
-impl Trait for u32 {
-    // Fine.
-    type Assoc where u32: Copy = ();
-    // Not fine, suggests moving `i32: Copy`
-    type Assoc2 where u32: Copy = () where i32: Copy;
-    //~^ ERROR where clause not allowed here
-}
-
-impl Trait for i32 {
-    // Not fine, suggests moving `u32: Copy`
-    type Assoc = () where u32: Copy;
-    //~^ ERROR where clause not allowed here
-    // Not fine, suggests moving both.
-    type Assoc2 = () where u32: Copy, i32: Copy;
-    //~^ ERROR where clause not allowed here
-}
+//~^ ERROR where clauses are not allowed
 
 fn main() {}
index 7ab0b28c8640a6539d3632ece12f32d6476cb22f..8789d2665ad92f49431c41fc51ea0c4497e2a89e 100644 (file)
@@ -1,40 +1,18 @@
-error: where clause not allowed here
+error: where clauses are not allowed after the type for type aliases
   --> $DIR/type-alias-where.rs:8:15
    |
 LL | type Bar = () where u32: Copy;
-   |         -     ^^^^^^^^^^^^^^^
-   |         |
-   |         help: move it here: `where u32: Copy`
+   |               ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
 
-error: where clause not allowed here
+error: where clauses are not allowed after the type for type aliases
   --> $DIR/type-alias-where.rs:10:15
    |
 LL | type Baz = () where;
    |               ^^^^^
-
-error: where clause not allowed here
-  --> $DIR/type-alias-where.rs:24:38
-   |
-LL |     type Assoc2 where u32: Copy = () where i32: Copy;
-   |                                -     ^^^^^^^^^^^^^^^
-   |                                |
-   |                                help: move it here: `, i32: Copy`
-
-error: where clause not allowed here
-  --> $DIR/type-alias-where.rs:30:21
-   |
-LL |     type Assoc = () where u32: Copy;
-   |               -     ^^^^^^^^^^^^^^^
-   |               |
-   |               help: move it here: `where u32: Copy`
-
-error: where clause not allowed here
-  --> $DIR/type-alias-where.rs:33:22
    |
-LL |     type Assoc2 = () where u32: Copy, i32: Copy;
-   |                -     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                |
-   |                help: move it here: `where u32: Copy, i32: Copy`
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
index 2ca774a48b66b73339ca92b4260f8c627334d6ae..cd5c283f9fd93c75c4d551c900317d2b29ecfde0 100644 (file)
@@ -4,23 +4,33 @@ error[E0004]: non-exhaustive patterns: type `&!` is non-empty
 LL |     match uninhab_ref() {
    |           ^^^^^^^^^^^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&!`
    = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match uninhab_ref() {
+LL +         _ => todo!(),
+LL +     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
   --> $DIR/always-inhabited-union-ref.rs:27:11
    |
-LL | / pub union Foo {
-LL | |     foo: !,
-LL | | }
-   | |_- `Foo` defined here
-...
-LL |       match uninhab_union() {
-   |             ^^^^^^^^^^^^^^^
+LL |     match uninhab_union() {
+   |           ^^^^^^^^^^^^^^^
+   |
+note: `Foo` defined here
+  --> $DIR/always-inhabited-union-ref.rs:10:11
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | pub union Foo {
+   |           ^^^
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match uninhab_union() {
+LL +         _ => todo!(),
+LL +     }
+   |
 
 error: aborting due to 2 previous errors
 
index 6c9539822b3dd6de105fb42ec08fa81a134e3339..7d0b71a497ec2f91f0fb290bf18f9f74a77cb900 100644 (file)
@@ -4,8 +4,22 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match Foo::A {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Foo` defined here
+  --> $DIR/auxiliary/hidden.rs:1:1
+   |
+LL | / pub enum Foo {
+LL | |     A,
+LL | |     B,
+LL | |     #[doc(hidden)]
+LL | |     C,
+LL | | }
+   | |_^
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Foo::B => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `B` not covered
   --> $DIR/doc-hidden-non-exhaustive.rs:14:11
@@ -13,13 +27,23 @@ error[E0004]: non-exhaustive patterns: `B` not covered
 LL |     match Foo::A {
    |           ^^^^^^ pattern `B` not covered
    |
-  ::: $DIR/auxiliary/hidden.rs:3:5
+note: `Foo` defined here
+  --> $DIR/auxiliary/hidden.rs:3:5
    |
-LL |     B,
-   |     - not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum Foo {
+LL | |     A,
+LL | |     B,
+   | |     ^ not covered
+LL | |     #[doc(hidden)]
+LL | |     C,
+LL | | }
+   | |_-
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Foo::C => {}
+LL +         B => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `B` and `_` not covered
   --> $DIR/doc-hidden-non-exhaustive.rs:20:11
@@ -27,13 +51,23 @@ error[E0004]: non-exhaustive patterns: `B` and `_` not covered
 LL |     match Foo::A {
    |           ^^^^^^ patterns `B` and `_` not covered
    |
-  ::: $DIR/auxiliary/hidden.rs:3:5
+note: `Foo` defined here
+  --> $DIR/auxiliary/hidden.rs:3:5
    |
-LL |     B,
-   |     - not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum Foo {
+LL | |     A,
+LL | |     B,
+   | |     ^ not covered
+LL | |     #[doc(hidden)]
+LL | |     C,
+LL | | }
+   | |_-
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         Foo::A => {}
+LL +         B | _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Some(B)` and `Some(_)` not covered
   --> $DIR/doc-hidden-non-exhaustive.rs:25:11
@@ -41,13 +75,24 @@ error[E0004]: non-exhaustive patterns: `Some(B)` and `Some(_)` not covered
 LL |     match None {
    |           ^^^^ patterns `Some(B)` and `Some(_)` not covered
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
+note: `Option<Foo>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ---- not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+   | |     ^^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `Option<Foo>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         Some(Foo::A) => {}
+LL +         Some(B) | Some(_) => todo!()
+   |
 
 error: aborting due to 4 previous errors
 
index b99386e74020e8da394e86cf987b490000c32ffe..d31ee0dbd14e5a032c8327c20a244021f269b4a2 100644 (file)
@@ -46,107 +46,112 @@ error[E0004]: non-exhaustive patterns: type `u8` is non-empty
 LL |     match_no_arms!(0u8);
    |                    ^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
   --> $DIR/empty-match.rs:79:20
    |
-LL | struct NonEmptyStruct1;
-   | ----------------------- `NonEmptyStruct1` defined here
-...
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct1` defined here
+  --> $DIR/empty-match.rs:14:8
+   |
+LL | struct NonEmptyStruct1;
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
   --> $DIR/empty-match.rs:80:20
    |
-LL | struct NonEmptyStruct2(bool);
-   | ----------------------------- `NonEmptyStruct2` defined here
-...
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct2` defined here
+  --> $DIR/empty-match.rs:15:8
+   |
+LL | struct NonEmptyStruct2(bool);
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
   --> $DIR/empty-match.rs:81:20
    |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_no_arms!((NonEmptyUnion1 { foo: () }));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `NonEmptyUnion1` defined here
+  --> $DIR/empty-match.rs:16:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion1 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
   --> $DIR/empty-match.rs:82:20
    |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_no_arms!((NonEmptyUnion2 { foo: () }));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `NonEmptyUnion2` defined here
+  --> $DIR/empty-match.rs:19:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion2 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
   --> $DIR/empty-match.rs:83:20
    |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_no_arms!(NonEmptyEnum1::Foo(true));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyEnum1` defined here
+  --> $DIR/empty-match.rs:24:5
+   |
+LL | enum NonEmptyEnum1 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum1`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
   --> $DIR/empty-match.rs:84:20
    |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |     Bar,
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_no_arms!(NonEmptyEnum2::Foo(true));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+note: `NonEmptyEnum2` defined here
+  --> $DIR/empty-match.rs:27:5
+   |
+LL | enum NonEmptyEnum2 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
+LL |     Bar,
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
   --> $DIR/empty-match.rs:85:20
    |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_no_arms!(NonEmptyEnum5::V1);
-   |                      ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |     match_no_arms!(NonEmptyEnum5::V1);
+   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+note: `NonEmptyEnum5` defined here
+  --> $DIR/empty-match.rs:30:6
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum NonEmptyEnum5 {
+   |      ^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyEnum5`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/empty-match.rs:87:24
@@ -154,107 +159,144 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
   --> $DIR/empty-match.rs:88:24
    |
-LL | struct NonEmptyStruct1;
-   | ----------------------- `NonEmptyStruct1` defined here
-...
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct1` defined here
+  --> $DIR/empty-match.rs:14:8
+   |
+LL | struct NonEmptyStruct1;
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyStruct1 => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
   --> $DIR/empty-match.rs:89:24
    |
-LL | struct NonEmptyStruct2(bool);
-   | ----------------------------- `NonEmptyStruct2` defined here
-...
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct2` defined here
+  --> $DIR/empty-match.rs:15:8
+   |
+LL | struct NonEmptyStruct2(bool);
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyStruct2(_) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
   --> $DIR/empty-match.rs:90:24
    |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_guarded_arm!((NonEmptyUnion1 { foo: () }));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+   |
+note: `NonEmptyUnion1` defined here
+  --> $DIR/empty-match.rs:16:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion1 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyUnion1 { .. } => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
   --> $DIR/empty-match.rs:91:24
    |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_guarded_arm!((NonEmptyUnion2 { foo: () }));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+   |
+note: `NonEmptyUnion2` defined here
+  --> $DIR/empty-match.rs:19:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion2 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyUnion2 { .. } => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
   --> $DIR/empty-match.rs:92:24
    |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_guarded_arm!(NonEmptyEnum1::Foo(true));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyEnum1` defined here
+  --> $DIR/empty-match.rs:24:5
+   |
+LL | enum NonEmptyEnum1 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum1`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             Foo(_) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
   --> $DIR/empty-match.rs:93:24
    |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |     Bar,
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_guarded_arm!(NonEmptyEnum2::Foo(true));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+note: `NonEmptyEnum2` defined here
+  --> $DIR/empty-match.rs:27:5
+   |
+LL | enum NonEmptyEnum2 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
+LL |     Bar,
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~             _ if false => {}
+LL +             Foo(_) | Bar => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
   --> $DIR/empty-match.rs:94:24
    |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_guarded_arm!(NonEmptyEnum5::V1);
-   |                          ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |     match_guarded_arm!(NonEmptyEnum5::V1);
+   |                        ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+note: `NonEmptyEnum5` defined here
+  --> $DIR/empty-match.rs:30:6
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum NonEmptyEnum5 {
+   |      ^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyEnum5`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~             _ if false => {}
+LL +             _ => todo!()
+   |
 
 error: aborting due to 22 previous errors
 
index b99386e74020e8da394e86cf987b490000c32ffe..d31ee0dbd14e5a032c8327c20a244021f269b4a2 100644 (file)
@@ -46,107 +46,112 @@ error[E0004]: non-exhaustive patterns: type `u8` is non-empty
 LL |     match_no_arms!(0u8);
    |                    ^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
   --> $DIR/empty-match.rs:79:20
    |
-LL | struct NonEmptyStruct1;
-   | ----------------------- `NonEmptyStruct1` defined here
-...
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct1` defined here
+  --> $DIR/empty-match.rs:14:8
+   |
+LL | struct NonEmptyStruct1;
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
   --> $DIR/empty-match.rs:80:20
    |
-LL | struct NonEmptyStruct2(bool);
-   | ----------------------------- `NonEmptyStruct2` defined here
-...
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct2` defined here
+  --> $DIR/empty-match.rs:15:8
+   |
+LL | struct NonEmptyStruct2(bool);
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
   --> $DIR/empty-match.rs:81:20
    |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_no_arms!((NonEmptyUnion1 { foo: () }));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `NonEmptyUnion1` defined here
+  --> $DIR/empty-match.rs:16:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion1 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
   --> $DIR/empty-match.rs:82:20
    |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_no_arms!((NonEmptyUnion2 { foo: () }));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `NonEmptyUnion2` defined here
+  --> $DIR/empty-match.rs:19:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion2 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
   --> $DIR/empty-match.rs:83:20
    |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_no_arms!(NonEmptyEnum1::Foo(true));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyEnum1` defined here
+  --> $DIR/empty-match.rs:24:5
+   |
+LL | enum NonEmptyEnum1 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum1`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
   --> $DIR/empty-match.rs:84:20
    |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |     Bar,
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_no_arms!(NonEmptyEnum2::Foo(true));
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+note: `NonEmptyEnum2` defined here
+  --> $DIR/empty-match.rs:27:5
+   |
+LL | enum NonEmptyEnum2 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
+LL |     Bar,
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
   --> $DIR/empty-match.rs:85:20
    |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_no_arms!(NonEmptyEnum5::V1);
-   |                      ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |     match_no_arms!(NonEmptyEnum5::V1);
+   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+note: `NonEmptyEnum5` defined here
+  --> $DIR/empty-match.rs:30:6
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum NonEmptyEnum5 {
+   |      ^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyEnum5`
+   = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/empty-match.rs:87:24
@@ -154,107 +159,144 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
   --> $DIR/empty-match.rs:88:24
    |
-LL | struct NonEmptyStruct1;
-   | ----------------------- `NonEmptyStruct1` defined here
-...
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct1` defined here
+  --> $DIR/empty-match.rs:14:8
+   |
+LL | struct NonEmptyStruct1;
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyStruct1 => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
   --> $DIR/empty-match.rs:89:24
    |
-LL | struct NonEmptyStruct2(bool);
-   | ----------------------------- `NonEmptyStruct2` defined here
-...
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyStruct2` defined here
+  --> $DIR/empty-match.rs:15:8
+   |
+LL | struct NonEmptyStruct2(bool);
+   |        ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyStruct2(_) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
   --> $DIR/empty-match.rs:90:24
    |
-LL | / union NonEmptyUnion1 {
-LL | |     foo: (),
-LL | | }
-   | |_- `NonEmptyUnion1` defined here
-...
-LL |       match_guarded_arm!((NonEmptyUnion1 { foo: () }));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+   |
+note: `NonEmptyUnion1` defined here
+  --> $DIR/empty-match.rs:16:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion1 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyUnion1 { .. } => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
   --> $DIR/empty-match.rs:91:24
    |
-LL | / union NonEmptyUnion2 {
-LL | |     foo: (),
-LL | |     bar: (),
-LL | | }
-   | |_- `NonEmptyUnion2` defined here
-...
-LL |       match_guarded_arm!((NonEmptyUnion2 { foo: () }));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+   |
+note: `NonEmptyUnion2` defined here
+  --> $DIR/empty-match.rs:19:7
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | union NonEmptyUnion2 {
+   |       ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             NonEmptyUnion2 { .. } => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
   --> $DIR/empty-match.rs:92:24
    |
-LL | / enum NonEmptyEnum1 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum1` defined here
-...
-LL |       match_guarded_arm!(NonEmptyEnum1::Foo(true));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonEmptyEnum1` defined here
+  --> $DIR/empty-match.rs:24:5
+   |
+LL | enum NonEmptyEnum1 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum1`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             _ if false => {}
+LL +             Foo(_) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
   --> $DIR/empty-match.rs:93:24
    |
-LL | / enum NonEmptyEnum2 {
-LL | |     Foo(bool),
-   | |     --- not covered
-LL | |     Bar,
-   | |     --- not covered
-LL | | }
-   | |_- `NonEmptyEnum2` defined here
-...
-LL |       match_guarded_arm!(NonEmptyEnum2::Foo(true));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+   |
+note: `NonEmptyEnum2` defined here
+  --> $DIR/empty-match.rs:27:5
+   |
+LL | enum NonEmptyEnum2 {
+   |      -------------
+LL |     Foo(bool),
+   |     ^^^ not covered
+LL |     Bar,
+   |     ^^^ not covered
    = note: the matched value is of type `NonEmptyEnum2`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~             _ if false => {}
+LL +             Foo(_) | Bar => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
   --> $DIR/empty-match.rs:94:24
    |
-LL | / enum NonEmptyEnum5 {
-LL | |     V1, V2, V3, V4, V5,
-LL | | }
-   | |_- `NonEmptyEnum5` defined here
-...
-LL |       match_guarded_arm!(NonEmptyEnum5::V1);
-   |                          ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |     match_guarded_arm!(NonEmptyEnum5::V1);
+   |                        ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+   |
+note: `NonEmptyEnum5` defined here
+  --> $DIR/empty-match.rs:30:6
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum NonEmptyEnum5 {
+   |      ^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyEnum5`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~             _ if false => {}
+LL +             _ => todo!()
+   |
 
 error: aborting due to 22 previous errors
 
index 464bfbdb2c3b2a864d72c0ed341b097ef6cd9d7c..c926e50b3580bd58d0b003d833588687e0c05dd8 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0.0 {
    |           ^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `f64`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~       0.0..=1.0 => {}
+LL +       _ => todo!()
+   |
 
 error: unreachable pattern
   --> $DIR/floats.rs:16:7
index 61f7facb330da959681c000eb5bd0f0600ad0352..0c1563c160c1c092928918ed492b2b5e358a468b 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
 LL |     match 0u8 {
    |           ^^^ pattern `128_u8..=u8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         128 ..= 255 if true => {}
+LL +         128_u8..=u8::MAX => todo!()
+   |
 
 error: aborting due to previous error
 
index ef573db8210469a38dab99a9fc3b12c2a0bd8f9d..0f5f49c4ca4731cd6daae00c5364a127bf084a7d 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(exclusive_range_pattern)]
-#![feature(assoc_char_consts)]
 #![allow(overlapping_range_endpoints)]
 #![deny(unreachable_patterns)]
 
index b1440375494b1697c19200a6335d54fb7ad2f8be..fec54e89d63cf091f175dd0ea06581584e6bced9 100644 (file)
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:48:8
+  --> $DIR/exhaustiveness.rs:47:8
    |
 LL |     m!(0u8, 0..255);
    |        ^^^ pattern `u8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:49:8
+  --> $DIR/exhaustiveness.rs:48:8
    |
 LL |     m!(0u8, 0..=254);
    |        ^^^ pattern `u8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_u8` not covered
-  --> $DIR/exhaustiveness.rs:50:8
+  --> $DIR/exhaustiveness.rs:49:8
    |
 LL |     m!(0u8, 1..=255);
    |        ^^^ pattern `0_u8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         0_u8 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `42_u8` not covered
-  --> $DIR/exhaustiveness.rs:51:8
+  --> $DIR/exhaustiveness.rs:50:8
    |
 LL |     m!(0u8, 0..42 | 43..=255);
    |        ^^^ pattern `42_u8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         42_u8 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:52:8
+  --> $DIR/exhaustiveness.rs:51:8
    |
 LL |     m!(0i8, -128..127);
    |        ^^^ pattern `i8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:53:8
+  --> $DIR/exhaustiveness.rs:52:8
    |
 LL |     m!(0i8, -128..=126);
    |        ^^^ pattern `i8::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i8::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
-  --> $DIR/exhaustiveness.rs:54:8
+  --> $DIR/exhaustiveness.rs:53:8
    |
 LL |     m!(0i8, -127..=127);
    |        ^^^ pattern `i8::MIN` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         i8::MIN => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_i8` not covered
-  --> $DIR/exhaustiveness.rs:55:11
+  --> $DIR/exhaustiveness.rs:54:11
    |
 LL |     match 0i8 {
    |           ^^^ pattern `0_i8` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         1 ..= i8::MAX => {}
+LL +         0_i8 => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/exhaustiveness.rs:60:8
+  --> $DIR/exhaustiveness.rs:59:8
    |
 LL |     m!(0u128, 0..=ALMOST_MAX);
    |        ^^^^^ pattern `u128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         u128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered
-  --> $DIR/exhaustiveness.rs:61:8
+  --> $DIR/exhaustiveness.rs:60:8
    |
 LL |     m!(0u128, 0..=4);
    |        ^^^^^ pattern `5_u128..=u128::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         5_u128..=u128::MAX => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `0_u128` not covered
-  --> $DIR/exhaustiveness.rs:62:8
+  --> $DIR/exhaustiveness.rs:61:8
    |
 LL |     m!(0u128, 1..=u128::MAX);
    |        ^^^^^ pattern `0_u128` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         0_u128 => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered
-  --> $DIR/exhaustiveness.rs:70:11
+  --> $DIR/exhaustiveness.rs:69:11
    |
 LL |     match (0u8, true) {
    |           ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(u8, bool)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         (0 ..= 255, true) => {}
+LL +         (126_u8..=127_u8, false) => todo!()
+   |
 
 error: aborting due to 12 previous errors
 
index 2563293458379588806282642f8ba03488a4b968..9f277fa1e1800a1cf3da3cf816f2bd79b3419dd2 100644 (file)
@@ -4,8 +4,13 @@ error[E0004]: non-exhaustive patterns: type `usize` is non-empty
 LL |     match 7usize {}
    |           ^^^^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match 7usize {
+LL +         _ => todo!(),
+LL +     }
+   |
 
 error: aborting due to previous error
 
index e8ac9f3cfe15633697828c909169053894fd1950..fa4146a7ad892268d13713830f79cabd45d42d95 100644 (file)
@@ -4,10 +4,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0usize {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
    = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         0 ..= usize::MAX => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:17:11
@@ -15,10 +19,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
    = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         isize::MIN ..= isize::MAX => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:22:8
@@ -26,10 +34,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0usize, 0..=usize::MAX);
    |        ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
    = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:24:8
@@ -37,10 +49,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0usize, 0..5 | 5..=usize::MAX);
    |        ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
    = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:26:8
@@ -48,10 +64,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0usize, 0..usize::MAX | usize::MAX);
    |        ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
    = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `(_, _)` not covered
   --> $DIR/pointer-sized-int.rs:28:8
@@ -59,8 +79,12 @@ error[E0004]: non-exhaustive patterns: `(_, _)` not covered
 LL |     m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
    |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(usize, bool)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         (_, _) => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:31:8
@@ -68,10 +92,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0isize, isize::MIN..=isize::MAX);
    |        ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
    = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:33:8
@@ -79,10 +107,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0isize, isize::MIN..5 | 5..=isize::MAX);
    |        ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
    = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:35:8
@@ -90,10 +122,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     m!(0isize, isize::MIN..isize::MAX | isize::MAX);
    |        ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
    = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         _ => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `(_, _)` not covered
   --> $DIR/pointer-sized-int.rs:37:8
@@ -101,8 +137,12 @@ error[E0004]: non-exhaustive patterns: `(_, _)` not covered
 LL |     m!((0isize, true), (isize::MIN..5, true)
    |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(isize, bool)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         match $s { $($t)+ => {}
+LL ~         (_, _) => todo!() }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/pointer-sized-int.rs:41:11
@@ -110,10 +150,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
    = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         1 ..= isize::MAX => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: type `usize` is non-empty
   --> $DIR/pointer-sized-int.rs:48:11
@@ -121,8 +165,13 @@ error[E0004]: non-exhaustive patterns: type `usize` is non-empty
 LL |     match 7usize {}
    |           ^^^^^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match 7usize {
+LL +         _ => todo!(),
+LL +     }
+   |
 
 error: aborting due to 12 previous errors
 
index 37e73a68f22bb005a707afcba4f4dae662687abd..30492c98206c90729923710f265f482976963a5c 100644 (file)
@@ -4,10 +4,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0usize {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
    = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         0..=usize::MAX => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/precise_pointer_matching-message.rs:11:11
@@ -15,10 +19,14 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
    = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         isize::MIN..=isize::MAX => {}
+LL +         _ => todo!()
+   |
 
 error: aborting due to 2 previous errors
 
index 79a77240937ac7803fe7096ed662a099d70ee1bf..af60f3ff50bf37583622e13c2b3472b8e3155f91 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` and `(T2(()), V1(_))` n
 LL |     match (T::T1(()), V::V2(true)) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(T, V)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         (T::T2(()), V::V2(b)) => (),
+LL ~         (T1(()), V2(_)) | (T2(()), V1(_)) => todo!(),
+   |
 
 error: aborting due to previous error
 
index 60d9b8514b7fbfe9115b84a0e56611b19af8a516..01890b73cbdd8a77875e2f677b976717f880197c 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` n
 LL |     match (a, b) {
    |           ^^^^^^ patterns `(None, None)` and `(Some(_), Some(_))` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(Option<usize>, Option<usize>)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         (Some(_), None) | (None, Some(_)) => {}
+LL +         (None, None) | (Some(_), Some(_)) => todo!()
+   |
 
 error: aborting due to previous error
 
index a2c58d6e051b54214ddd332fa42edf8feca04d2e..759fdeafe4eb545202f947b8e7e78d3a7bf61f64 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `&_` not covered
 LL |     match "world" {
    |           ^^^^^^^ pattern `&_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&str`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         "hello" => {}
+LL +         &_ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&_` not covered
   --> $DIR/issue-30240.rs:6:11
@@ -13,8 +17,12 @@ error[E0004]: non-exhaustive patterns: `&_` not covered
 LL |     match "world" {
    |           ^^^^^^^ pattern `&_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&str`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         "hello" => {}
+LL +         &_ => todo!()
+   |
 
 error: aborting due to 2 previous errors
 
index 97c34755189de9115a62fcaad0267619ae3d06fb..d8884394f8e9619a0b501090c18a7ea865cc48a5 100644 (file)
@@ -4,8 +4,13 @@ error[E0004]: non-exhaustive patterns: type `()` is non-empty
 LL |     match () { }
    |           ^^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `()`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match () {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error: aborting due to previous error
 
index 472d1a91e6a15835c94e5b936c43119ed0543c84..2df8911badcda230b55b572dbd8f7355658bffe8 100644 (file)
@@ -4,8 +4,13 @@ error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty
 LL |     match x { }
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `*const Bottom`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error: aborting due to previous error
 
index 2f562b23692deffc3128c6a612eb893d436977b5..dffcfc016072f28d78c769ea47d0292ce2601ae6 100644 (file)
@@ -1,20 +1,21 @@
 error[E0005]: refutable pattern in local binding: `Bar` and `Baz` not covered
   --> $DIR/issue-31561.rs:8:9
    |
-LL | / enum Thing {
-LL | |     Foo(u8),
-LL | |     Bar,
-   | |     --- not covered
-LL | |     Baz
-   | |     --- not covered
-LL | | }
-   | |_- `Thing` defined here
-...
-LL |       let Thing::Foo(y) = Thing::Foo(1);
-   |           ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered
+LL |     let Thing::Foo(y) = Thing::Foo(1);
+   |         ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Thing` defined here
+  --> $DIR/issue-31561.rs:3:5
+   |
+LL | enum Thing {
+   |      -----
+LL |     Foo(u8),
+LL |     Bar,
+   |     ^^^ not covered
+LL |     Baz
+   |     ^^^ not covered
    = note: the matched value is of type `Thing`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index 0598c8d6f38c574b263700206d8955bb5b53d9b7..717bb53c32750e0df2dfc527505bb4d3296b1494 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `(B, _)`, `(C, _)`, `(D, _)` and 2 more n
 LL |     match (A, ()) {
    |           ^^^^^^^ patterns `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(Enum, ())`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         (A, _) => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
   --> $DIR/issue-35609.rs:14:11
@@ -13,8 +17,12 @@ error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more n
 LL |     match (A, A) {
    |           ^^^^^^ patterns `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(Enum, Enum)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         (_, A) => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
   --> $DIR/issue-35609.rs:18:11
@@ -22,8 +30,12 @@ error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _
 LL |     match ((A, ()), ()) {
    |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `((Enum, ()), ())`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         ((A, ()), _) => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
   --> $DIR/issue-35609.rs:22:11
@@ -31,8 +43,12 @@ error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _
 LL |     match ((A, ()), A) {
    |           ^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `((Enum, ()), Enum)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         ((A, ()), _) => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
   --> $DIR/issue-35609.rs:26:11
@@ -40,32 +56,48 @@ error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _
 LL |     match ((A, ()), ()) {
    |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `((Enum, ()), ())`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         ((A, _), _) => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
   --> $DIR/issue-35609.rs:31:11
    |
-LL | struct S(Enum, ());
-   | ------------------- `S` defined here
-...
 LL |     match S(A, ()) {
    |           ^^^^^^^^ patterns `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `S` defined here
+  --> $DIR/issue-35609.rs:6:8
+   |
+LL | struct S(Enum, ());
+   |        ^
    = note: the matched value is of type `S`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         S(A, _) => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
   --> $DIR/issue-35609.rs:35:11
    |
-LL | struct Sd { x: Enum, y: () }
-   | ---------------------------- `Sd` defined here
-...
 LL |     match (Sd { x: A, y: () }) {
    |           ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Sd` defined here
+  --> $DIR/issue-35609.rs:7:8
+   |
+LL | struct Sd { x: Enum, y: () }
+   |        ^^
    = note: the matched value is of type `Sd`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         Sd { x: A, y: _ } => {}
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
   --> $DIR/issue-35609.rs:39:11
@@ -73,8 +105,23 @@ error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 mor
 LL |     match Some(A) {
    |           ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Option<Enum>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+LL | | }
+   | |_^
    = note: the matched value is of type `Option<Enum>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         None => (),
+LL +         _ => todo!()
+   |
 
 error: aborting due to 8 previous errors
 
index 48ed14915084a5d607ae44e57b8a0cedcc4a6d3b..4e0adcc1ba2a538af4aaa509610a9deb3ce432d0 100644 (file)
@@ -4,8 +4,20 @@ error[E0004]: non-exhaustive patterns: `box _` not covered
 LL |         box NodeKind::Element(ed) => match ed.kind {
    |                                            ^^^^^^^ pattern `box _` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Box<ElementKind>` defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+   |
+LL | / pub struct Box<
+LL | |     T: ?Sized,
+LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+LL | | >(Unique<T>, A);
+   | |________________^
    = note: the matched value is of type `Box<ElementKind>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
+LL +             box _ => todo!()
+   |
 
 error: aborting due to previous error
 
index 8c162e55619e005b5e6aac41e9970f510d64c9ba..ca37af6fb809540f6e0e42f9f546332a72131154 100644 (file)
@@ -1,16 +1,22 @@
 error[E0004]: non-exhaustive patterns: `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
   --> $DIR/issue-39362.rs:10:11
    |
-LL | / enum Foo {
-LL | |     Bar { bar: Bar, id: usize }
-LL | | }
-   | |_- `Foo` defined here
-...
-LL |       match f {
-   |             ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+LL |     match f {
+   |           ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Foo` defined here
+  --> $DIR/issue-39362.rs:2:5
+   |
+LL | enum Foo {
+   |      ---
+LL |     Bar { bar: Bar, id: usize }
+   |     ^^^ not covered
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         Foo::Bar { bar: Bar::B, .. } => (),
+LL ~         _ => todo!(),
+   |
 
 error: aborting due to previous error
 
index 98efe805a0b3491fde73c71445fa608e9119296a..c477e435335043274051e4ee041245a421b1ef44 100644 (file)
@@ -1,17 +1,22 @@
 error[E0004]: non-exhaustive patterns: `C(QA)` not covered
   --> $DIR/issue-40221.rs:11:11
    |
-LL | / enum P {
-LL | |     C(PC),
-   | |     - not covered
-LL | | }
-   | |_- `P` defined here
-...
-LL |       match proto {
-   |             ^^^^^ pattern `C(QA)` not covered
+LL |     match proto {
+   |           ^^^^^ pattern `C(QA)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `P` defined here
+  --> $DIR/issue-40221.rs:2:5
+   |
+LL | enum P {
+   |      -
+LL |     C(PC),
+   |     ^ not covered
    = note: the matched value is of type `P`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         P::C(PC::Q) => (),
+LL ~         C(QA) => todo!(),
+   |
 
 error: aborting due to previous error
 
index 1e8852556b161690c46dfb8ba5fdff3346c278d4..293273174101686bc4fd8e254d3009705eb56c9c 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered
 LL |     println!("foo {:}", match tup {
    |                               ^^^ pattern `(true, false)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(bool, bool)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         (true, true) => "baz",
+LL +         (true, false) => todo!()
+   |
 
 error: aborting due to previous error
 
index d378b6e8efe370a84ac92491ae3ceb4853ad9b55..2bdbecabbbea092375cf58da0bf79a7f3ae079ec 100644 (file)
@@ -1,14 +1,20 @@
 error[E0004]: non-exhaustive patterns: `Tag(Exif, _)` not covered
   --> $DIR/issue-50900.rs:15:11
    |
-LL | pub struct Tag(pub Context, pub u16);
-   | ------------------------------------- `Tag` defined here
-...
 LL |     match Tag::ExifIFDPointer {
    |           ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Exif, _)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Tag` defined here
+  --> $DIR/issue-50900.rs:2:12
+   |
+LL | pub struct Tag(pub Context, pub u16);
+   |            ^^^
    = note: the matched value is of type `Tag`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Tag::ExifIFDPointer => {}
+LL +         Tag(Exif, _) => todo!()
+   |
 
 error: aborting due to previous error
 
index 6a231b868c8c457f045c5d8a6d03f6290b3e105b..f6261001c5e0903f455ec3da533bff1cda3cc995 100644 (file)
@@ -1,21 +1,26 @@
 error[E0004]: non-exhaustive patterns: `A(false)`, `B(false)` and `C(false)` not covered
   --> $DIR/issue-56379.rs:8:11
    |
-LL | / enum Foo {
-LL | |     A(bool),
-   | |     - not covered
-LL | |     B(bool),
-   | |     - not covered
-LL | |     C(bool),
-   | |     - not covered
-LL | | }
-   | |_- `Foo` defined here
-...
-LL |       match Foo::A(true) {
-   |             ^^^^^^^^^^^^ patterns `A(false)`, `B(false)` and `C(false)` not covered
+LL |     match Foo::A(true) {
+   |           ^^^^^^^^^^^^ patterns `A(false)`, `B(false)` and `C(false)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Foo` defined here
+  --> $DIR/issue-56379.rs:2:5
+   |
+LL | enum Foo {
+   |      ---
+LL |     A(bool),
+   |     ^ not covered
+LL |     B(bool),
+   |     ^ not covered
+LL |     C(bool),
+   |     ^ not covered
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         Foo::C(true) => {}
+LL +         A(false) | B(false) | C(false) => todo!()
+   |
 
 error: aborting due to previous error
 
index b4a68333967b36b97d5ebf7c8284916c486c6d7b..20f002dd3db15c66d276335c80d09ea60844c7a6 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `(A, Some(A))`, `(A, Some(B))`, `(B, Some
 LL |     match (x, y) {
    |           ^^^^^^ patterns `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(X, Option<X>)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         (X::A, Some(X::C)) | (X::C, Some(X::A)) => false,
+LL ~         _ => todo!(),
+   |
 
 error: aborting due to previous error
 
index 6c5a331b4b564ebdc5e372b72e38242c75ccf53a..cbfcf0eafd4901032ddf5b67f6825592d3b9ed70 100644 (file)
@@ -1,5 +1,6 @@
 enum A {}
     //~^ NOTE `A` defined here
+    //~| NOTE
 
 fn f(a: &A) {
     match a {}
index e992632a91faf3dfdcac41901824f2dd4842400b..bf05d616d6ed1c2865ed46ccf21e3fa76c169e13 100644 (file)
@@ -1,15 +1,22 @@
 error[E0004]: non-exhaustive patterns: type `&A` is non-empty
-  --> $DIR/issue-78123-non-exhaustive-reference.rs:5:11
+  --> $DIR/issue-78123-non-exhaustive-reference.rs:6:11
    |
-LL | enum A {}
-   | --------- `A` defined here
-...
 LL |     match a {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `A` defined here
+  --> $DIR/issue-78123-non-exhaustive-reference.rs:1:6
+   |
+LL | enum A {}
+   |      ^
    = note: the matched value is of type `&A`
    = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match a {
+LL +         _ => todo!(),
+LL +     }
+   |
 
 error: aborting due to previous error
 
index 4a987cb6c0311c94dfb1e7e7887fd22052b897e0..3326e6b85a471734c11bd6e3930a368be393202c 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered
 LL |     match (true, false) {
    |           ^^^^^^^^^^^^^ pattern `(true, false)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(bool, bool)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         (false, true) => (),
+LL +         (true, false) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
   --> $DIR/match-arm-statics-2.rs:29:11
@@ -13,31 +17,45 @@ error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
 LL |     match Some(Some(North)) {
    |           ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
+note: `Option<Option<Direction>>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+   | |     ^^^^
+   | |     |
+   | |     not covered
+   | |     not covered
+LL | | }
+   | |_-
+   = note: the matched value is of type `Option<Option<Direction>>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ----
-   |     |
-   |     not covered
-   |     not covered
+LL ~         None => (),
+LL +         Some(Some(West)) => todo!()
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Option<Option<Direction>>`
 
 error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered
   --> $DIR/match-arm-statics-2.rs:48:11
    |
-LL | / struct Foo {
-LL | |     bar: Option<Direction>,
-LL | |     baz: NewBool
-LL | | }
-   | |_- `Foo` defined here
-...
-LL |       match (Foo { bar: Some(North), baz: NewBool(true) }) {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+LL |     match (Foo { bar: Some(North), baz: NewBool(true) }) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+   |
+note: `Foo` defined here
+  --> $DIR/match-arm-statics-2.rs:40:8
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | struct Foo {
+   |        ^^^
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Foo { bar: Some(EAST), .. } => (),
+LL +         Foo { bar: Some(North), baz: NewBool(true) } => todo!()
+   |
 
 error: aborting due to 3 previous errors
 
index ffc8433403fd59d96de8e2caa10fe9750c066106..a90f32f7aebf34e3bd99ba18d36dc5ded1077df7 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..
 LL |     match buf {
    |           ^^^ patterns `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..=u8::MAX, _, _, _]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[u8; 4]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         b"AAAA" => {}
+LL +         &[0_u8..=64_u8, _, _, _] | &[66_u8..=u8::MAX, _, _, _] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
   --> $DIR/match-byte-array-patterns-2.rs:10:11
@@ -13,8 +17,12 @@ error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not c
 LL |     match buf {
    |           ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[u8]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         b"AAAA" => {}
+LL +         _ => todo!()
+   |
 
 error: aborting due to 2 previous errors
 
index a35d61e4b710be63198d39488c98c71420218f0b..08dde523a15fb524e3aaa7367452432fc642a6bf 100644 (file)
@@ -4,8 +4,11 @@ error[E0004]: non-exhaustive patterns: `i32::MIN..=0_i32` and `2_i32..=i32::MAX`
 LL |     match 0 { 1 => () }
    |           ^ patterns `i32::MIN..=0_i32` and `2_i32..=i32::MAX` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL |     match 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() }
+   |                      ++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/match-non-exhaustive.rs:3:11
@@ -13,8 +16,11 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match 0 { 0 if false => () }
    |           ^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL |     match 0 { 0 if false => (), _ => todo!() }
+   |                               ++++++++++++++
 
 error: aborting due to 2 previous errors
 
index 4efb41978a241c08b722efe30c4c0e2d647664b3..88178d6429197eac5850ce0b9cc5c5d098ef3631 100644 (file)
@@ -4,13 +4,24 @@ error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not co
 LL |     match private::DATA {
    |           ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
+note: `Option<Private>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ---- not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+   | |     ^^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `Option<Private>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         }) => {}
+LL +         Some(Private { misc: true, .. }) => todo!()
+   |
 
 error: aborting due to previous error
 
index 88f27be0412aa550cd0be285a0da65f208788045..961dd5901196149b004bc627c8a01647beacf62d 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
 LL |     match list {
    |           ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[Option<()>]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &[.., Some(_), _] => {}
+LL ~         &[_, Some(_), .., None, _] => todo!(),
+   |
 
 error: aborting due to previous error
 
index 6f009acbdfe1818ac9984720917a2a5146f3e0d2..2e15bc2d2a5f534fbab024f30bcd94f0039345fa 100644 (file)
@@ -4,20 +4,26 @@
 
 #[derive(Clone)]
 enum E {
-//~^ `E` defined here
-//~| `E` defined here
-//~| `E` defined here
-//~| `E` defined here
-//~| `E` defined here
-//~| `E` defined here
+    //~^ NOTE
+    //~| NOTE
+    //~| NOTE
+    //~| NOTE
+    //~| NOTE
+    //~| NOTE
     A,
     B,
-    //~^ not covered
-    //~| not covered
-    //~| not covered
-    //~| not covered
-    //~| not covered
-    //~| not covered
+    //~^ NOTE `E` defined here
+    //~| NOTE `E` defined here
+    //~| NOTE `E` defined here
+    //~| NOTE `E` defined here
+    //~| NOTE `E` defined here
+    //~| NOTE `E` defined here
+    //~| NOTE  not covered
+    //~| NOTE  not covered
+    //~| NOTE  not covered
+    //~| NOTE  not covered
+    //~| NOTE  not covered
+    //~| NOTE  not covered
     C
     //~^ not covered
     //~| not covered
@@ -30,43 +36,70 @@ enum E {
 fn by_val(e: E) {
     let e1 = e.clone();
     match e1 { //~ ERROR non-exhaustive patterns: `B` and `C` not covered
+        //~^ NOTE patterns `B` and `C` not covered
+        //~| NOTE the matched value is of type `E`
         E::A => {}
     }
 
     let E::A = e; //~ ERROR refutable pattern in local binding: `B` and `C` not covered
+    //~^ NOTE patterns `B` and `C` not covered
+    //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+    //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+    //~| NOTE the matched value is of type `E`
 }
 
 fn by_ref_once(e: &E) {
     match e { //~ ERROR non-exhaustive patterns: `&B` and `&C` not covered
+    //~^ NOTE patterns `&B` and `&C` not covered
+    //~| NOTE the matched value is of type `&E`
         E::A => {}
     }
 
     let E::A = e; //~ ERROR refutable pattern in local binding: `&B` and `&C` not covered
+    //~^ NOTE patterns `&B` and `&C` not covered
+    //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+    //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+    //~| NOTE the matched value is of type `&E`
 }
 
 fn by_ref_thrice(e: & &mut &E) {
     match e { //~ ERROR non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
+    //~^ NOTE patterns `&&mut &B` and `&&mut &C` not covered
+    //~| NOTE the matched value is of type `&&mut &E`
         E::A => {}
     }
 
     let E::A = e;
     //~^ ERROR refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
+    //~| NOTE patterns `&&mut &B` and `&&mut &C` not covered
+    //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+    //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+    //~| NOTE the matched value is of type `&&mut &E`
 }
 
 enum Opt {
-//~^ `Opt` defined here
-//~| `Opt` defined here
+    //~^ NOTE
+    //~| NOTE
     Some(u8),
     None,
-    //~^ not covered
+    //~^ NOTE `Opt` defined here
+    //~| NOTE `Opt` defined here
+    //~| NOTE not covered
+    //~| NOTE not covered
 }
 
 fn ref_pat(e: Opt) {
     match e {//~ ERROR non-exhaustive patterns: `None` not covered
+        //~^ NOTE pattern `None` not covered
+        //~| NOTE the matched value is of type `Opt`
         Opt::Some(ref _x) => {}
     }
 
     let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `None` not covered
+    //~^ NOTE the matched value is of type `Opt`
+    //~| NOTE pattern `None` not covered
+    //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+    //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 }
 
 fn main() {}
index 02eff28015d178bd6f2152619d3dae40deaf1cf8..8f5adccea806db36ba27570cf92d19421e6e8502 100644 (file)
@@ -1,50 +1,46 @@
 error[E0004]: non-exhaustive patterns: `B` and `C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:32:11
-   |
-LL | / enum E {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     B,
-   | |     - not covered
-...  |
-LL | |     C
-   | |     - not covered
-...  |
-LL | |
-LL | | }
-   | |_- `E` defined here
-...
-LL |       match e1 {
-   |             ^^ patterns `B` and `C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:38:11
+   |
+LL |     match e1 {
+   |           ^^ patterns `B` and `C` not covered
+   |
+note: `E` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:14:5
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum E {
+   |      -
+...
+LL |     B,
+   |     ^ not covered
+...
+LL |     C
+   |     ^ not covered
    = note: the matched value is of type `E`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         E::A => {}
+LL +         B | C => todo!()
+   |
 
 error[E0005]: refutable pattern in local binding: `B` and `C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:36:9
-   |
-LL | / enum E {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     B,
-   | |     - not covered
-...  |
-LL | |     C
-   | |     - not covered
-...  |
-LL | |
-LL | | }
-   | |_- `E` defined here
-...
-LL |       let E::A = e;
-   |           ^^^^ patterns `B` and `C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:44:9
+   |
+LL |     let E::A = e;
+   |         ^^^^ patterns `B` and `C` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `E` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:14:5
+   |
+LL | enum E {
+   |      -
+...
+LL |     B,
+   |     ^ not covered
+...
+LL |     C
+   |     ^ not covered
    = note: the matched value is of type `E`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
@@ -52,52 +48,48 @@ LL |     if let E::A = e { /* */ }
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:40:11
-   |
-LL | / enum E {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     B,
-   | |     - not covered
-...  |
-LL | |     C
-   | |     - not covered
-...  |
-LL | |
-LL | | }
-   | |_- `E` defined here
-...
-LL |       match e {
-   |             ^ patterns `&B` and `&C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:52:11
+   |
+LL |     match e {
+   |           ^ patterns `&B` and `&C` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `E` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:14:5
+   |
+LL | enum E {
+   |      -
+...
+LL |     B,
+   |     ^ not covered
+...
+LL |     C
+   |     ^ not covered
    = note: the matched value is of type `&E`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         E::A => {}
+LL +         &B | &C => todo!()
+   |
 
 error[E0005]: refutable pattern in local binding: `&B` and `&C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:44:9
+  --> $DIR/non-exhaustive-defined-here.rs:58:9
    |
-LL | / enum E {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     B,
-   | |     - not covered
-...  |
-LL | |     C
-   | |     - not covered
-...  |
-LL | |
-LL | | }
-   | |_- `E` defined here
-...
-LL |       let E::A = e;
-   |           ^^^^ patterns `&B` and `&C` not covered
+LL |     let E::A = e;
+   |         ^^^^ patterns `&B` and `&C` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `E` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:14:5
+   |
+LL | enum E {
+   |      -
+...
+LL |     B,
+   |     ^ not covered
+...
+LL |     C
+   |     ^ not covered
    = note: the matched value is of type `&E`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
@@ -105,52 +97,48 @@ LL |     if let E::A = e { /* */ }
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:48:11
-   |
-LL | / enum E {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     B,
-   | |     - not covered
-...  |
-LL | |     C
-   | |     - not covered
-...  |
-LL | |
-LL | | }
-   | |_- `E` defined here
-...
-LL |       match e {
-   |             ^ patterns `&&mut &B` and `&&mut &C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:66:11
+   |
+LL |     match e {
+   |           ^ patterns `&&mut &B` and `&&mut &C` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `E` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:14:5
+   |
+LL | enum E {
+   |      -
+...
+LL |     B,
+   |     ^ not covered
+...
+LL |     C
+   |     ^ not covered
    = note: the matched value is of type `&&mut &E`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         E::A => {}
+LL +         &&mut &B | &&mut &C => todo!()
+   |
 
 error[E0005]: refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:52:9
-   |
-LL | / enum E {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     B,
-   | |     - not covered
-...  |
-LL | |     C
-   | |     - not covered
-...  |
-LL | |
-LL | | }
-   | |_- `E` defined here
-...
-LL |       let E::A = e;
-   |           ^^^^ patterns `&&mut &B` and `&&mut &C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:72:9
+   |
+LL |     let E::A = e;
+   |         ^^^^ patterns `&&mut &B` and `&&mut &C` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `E` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:14:5
+   |
+LL | enum E {
+   |      -
+...
+LL |     B,
+   |     ^ not covered
+...
+LL |     C
+   |     ^ not covered
    = note: the matched value is of type `&&mut &E`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
@@ -158,42 +146,42 @@ LL |     if let E::A = e { /* */ }
    |
 
 error[E0004]: non-exhaustive patterns: `None` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:65:11
-   |
-LL | / enum Opt {
-LL | |
-LL | |
-LL | |     Some(u8),
-LL | |     None,
-   | |     ---- not covered
-LL | |
-LL | | }
-   | |_- `Opt` defined here
-...
-LL |       match e {
-   |             ^ pattern `None` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:92:11
+   |
+LL |     match e {
+   |           ^ pattern `None` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Opt` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:84:5
+   |
+LL | enum Opt {
+   |      ---
+...
+LL |     None,
+   |     ^^^^ not covered
    = note: the matched value is of type `Opt`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Opt::Some(ref _x) => {}
+LL +         None => todo!()
+   |
 
 error[E0005]: refutable pattern in local binding: `None` not covered
-  --> $DIR/non-exhaustive-defined-here.rs:69:9
-   |
-LL | / enum Opt {
-LL | |
-LL | |
-LL | |     Some(u8),
-LL | |     None,
-   | |     ---- not covered
-LL | |
-LL | | }
-   | |_- `Opt` defined here
-...
-LL |       let Opt::Some(ref _x) = e;
-   |           ^^^^^^^^^^^^^^^^^ pattern `None` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:98:9
+   |
+LL |     let Opt::Some(ref _x) = e;
+   |         ^^^^^^^^^^^^^^^^^ pattern `None` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Opt` defined here
+  --> $DIR/non-exhaustive-defined-here.rs:84:5
+   |
+LL | enum Opt {
+   |      ---
+...
+LL |     None,
+   |     ^^^^ not covered
    = note: the matched value is of type `Opt`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index 928e9068266cd5cc7e9c9847ce34e68fea1a2476..cbbd544f943ba1f0f3488868e0dbcfe68bbc5004 100644 (file)
@@ -4,23 +4,30 @@ error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
 LL |     match (l1, l2) {
    |           ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(Option<&[T]>, Result<&[T], ()>)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)",
+LL +         (Some(&[]), Err(_)) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `A(C)` not covered
   --> $DIR/non-exhaustive-match-nested.rs:15:11
    |
-LL | enum T { A(U), B }
-   | ------------------
-   | |        |
-   | |        not covered
-   | `T` defined here
-...
 LL |     match x {
    |           ^ pattern `A(C)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `T` defined here
+  --> $DIR/non-exhaustive-match-nested.rs:1:10
+   |
+LL | enum T { A(U), B }
+   |      -   ^ not covered
    = note: the matched value is of type `T`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         T::B => { panic!("goodbye"); }
+LL +         A(C) => todo!()
+   |
 
 error: aborting due to 2 previous errors
 
index 1ca0a33bf37d90e03c7804d2fe53f4c067de86f1..e7fa6a7814f85358f8b7a7c59358eec5aac730a5 100644 (file)
@@ -1,17 +1,19 @@
 error[E0004]: non-exhaustive patterns: `A` not covered
   --> $DIR/non-exhaustive-match.rs:7:11
    |
-LL | enum T { A, B }
-   | ---------------
-   | |        |
-   | |        not covered
-   | `T` defined here
-...
 LL |     match x { T::B => { } }
    |           ^ pattern `A` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `T` defined here
+  --> $DIR/non-exhaustive-match.rs:3:10
+   |
+LL | enum T { A, B }
+   |      -   ^ not covered
    = note: the matched value is of type `T`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL |     match x { T::B => { } A => todo!() }
+   |                           ++++++++++++
 
 error[E0004]: non-exhaustive patterns: `false` not covered
   --> $DIR/non-exhaustive-match.rs:8:11
@@ -19,8 +21,12 @@ error[E0004]: non-exhaustive patterns: `false` not covered
 LL |     match true {
    |           ^^^^ pattern `false` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `bool`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~       true => {}
+LL +       false => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
   --> $DIR/non-exhaustive-match.rs:11:11
@@ -28,13 +34,24 @@ error[E0004]: non-exhaustive patterns: `Some(_)` not covered
 LL |     match Some(10) {
    |           ^^^^^^^^ pattern `Some(_)` not covered
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
+note: `Option<i32>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+LL | / pub enum Option<T> {
+LL | |     /// No value.
+LL | |     #[lang = "None"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+   | |     ^^^^ not covered
+LL | | }
+   | |_-
+   = note: the matched value is of type `Option<i32>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ---- not covered
+LL ~       None => {}
+LL +       Some(_) => todo!()
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Option<i32>`
 
 error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered
   --> $DIR/non-exhaustive-match.rs:14:11
@@ -42,8 +59,12 @@ error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_
 LL |     match (2, 3, 4) {
    |           ^^^^^^^^^ patterns `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(i32, i32, i32)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~       (_, _, 4) => {}
+LL +       (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `(A, A)` and `(B, B)` not covered
   --> $DIR/non-exhaustive-match.rs:18:11
@@ -51,23 +72,30 @@ error[E0004]: non-exhaustive patterns: `(A, A)` and `(B, B)` not covered
 LL |     match (T::A, T::A) {
    |           ^^^^^^^^^^^^ patterns `(A, A)` and `(B, B)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(T, T)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~       (T::B, T::A) => {}
+LL +       (A, A) | (B, B) => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `B` not covered
   --> $DIR/non-exhaustive-match.rs:22:11
    |
-LL | enum T { A, B }
-   | ---------------
-   | |           |
-   | |           not covered
-   | `T` defined here
-...
 LL |     match T::A {
    |           ^^^^ pattern `B` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `T` defined here
+  --> $DIR/non-exhaustive-match.rs:3:13
+   |
+LL | enum T { A, B }
+   |      -      ^ not covered
    = note: the matched value is of type `T`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~       T::A => {}
+LL +       B => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
   --> $DIR/non-exhaustive-match.rs:33:11
@@ -75,8 +103,12 @@ error[E0004]: non-exhaustive patterns: `[]` not covered
 LL |     match *vec {
    |           ^^^^ pattern `[]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `[Option<isize>]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [None] => {}
+LL +         [] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
   --> $DIR/non-exhaustive-match.rs:46:11
@@ -84,8 +116,12 @@ error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
 LL |     match *vec {
    |           ^^^^ pattern `[_, _, _, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `[f32]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [] => (),
+LL +         [_, _, _, _, ..] => todo!()
+   |
 
 error: aborting due to 8 previous errors
 
index c9ed12aae5fbc128c202799fe0c14d6950f30f6e..b0cfd631fb07ebd28c493bafa38dd3722d1fee3c 100644 (file)
 error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:7:11
    |
-LL | / struct Foo {
-LL | |     first: bool,
-LL | |     second: Option<[usize; 4]>
-LL | | }
-   | |_- `Foo` defined here
-...
-LL |       match (Foo { first: true, second: None }) {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+LL |     match (Foo { first: true, second: None }) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+   |
+note: `Foo` defined here
+  --> $DIR/non-exhaustive-pattern-witness.rs:1:8
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | struct Foo {
+   |        ^^^
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Foo { first: false, second: Some([1, 2, 3, 4]) } => (),
+LL +         Foo { first: false, second: Some([_, _, _, _]) } => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Red` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:23:11
    |
-LL | / enum Color {
-LL | |     Red,
-   | |     --- not covered
-LL | |     Green,
-LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
-LL | | }
-   | |_- `Color` defined here
-...
-LL |       match Color::Red {
-   |             ^^^^^^^^^^ pattern `Red` not covered
+LL |     match Color::Red {
+   |           ^^^^^^^^^^ pattern `Red` not covered
+   |
+note: `Color` defined here
+  --> $DIR/non-exhaustive-pattern-witness.rs:17:5
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum Color {
+   |      -----
+LL |     Red,
+   |     ^^^ not covered
    = note: the matched value is of type `Color`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Color::Green => (),
+LL +         Red => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:35:11
    |
-LL | / enum Direction {
-LL | |     North, East, South, West
-   | |            ----  -----  ---- not covered
-   | |            |     |
-   | |            |     not covered
-   | |            not covered
-LL | | }
-   | |_- `Direction` defined here
-...
-LL |       match Direction::North {
-   |             ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+LL |     match Direction::North {
+   |           ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+   |
+note: `Direction` defined here
+  --> $DIR/non-exhaustive-pattern-witness.rs:31:12
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum Direction {
+   |      ---------
+LL |     North, East, South, West
+   |            ^^^^  ^^^^^  ^^^^ not covered
+   |            |     |
+   |            |     not covered
+   |            not covered
    = note: the matched value is of type `Direction`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         Direction::North => (),
+LL +         East | South | West => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:46:11
    |
-LL | / enum ExcessiveEnum {
-LL | |     First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
-LL | | }
-   | |_- `ExcessiveEnum` defined here
-...
-LL |       match ExcessiveEnum::First {
-   |             ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
+LL |     match ExcessiveEnum::First {
+   |           ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `ExcessiveEnum` defined here
+  --> $DIR/non-exhaustive-pattern-witness.rs:41:6
+   |
+LL | enum ExcessiveEnum {
+   |      ^^^^^^^^^^^^^
    = note: the matched value is of type `ExcessiveEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         ExcessiveEnum::First => (),
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:54:11
    |
-LL | / enum Color {
-LL | |     Red,
-LL | |     Green,
-LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
-   | |     ---------- not covered
-LL | | }
-   | |_- `Color` defined here
-...
-LL |       match Color::Red {
-   |             ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+LL |     match Color::Red {
+   |           ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+   |
+note: `Color` defined here
+  --> $DIR/non-exhaustive-pattern-witness.rs:19:5
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | enum Color {
+   |      -----
+...
+LL |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+   |     ^^^^^^^^^^ not covered
    = note: the matched value is of type `Color`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (),
+LL +         CustomRGBA { a: true, .. } => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:70:11
@@ -85,8 +104,12 @@ error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not cover
 LL |     match *x {
    |           ^^ pattern `[Second(true), Second(false)]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `[Enum]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [_, _, ref tail @ .., _] => (),
+LL +         [Second(true), Second(false)] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `((), false)` not covered
   --> $DIR/non-exhaustive-pattern-witness.rs:83:11
@@ -94,8 +117,12 @@ error[E0004]: non-exhaustive patterns: `((), false)` not covered
 LL |     match ((), false) {
    |           ^^^^^^^^^^^ pattern `((), false)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `((), bool)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         ((), true) => (),
+LL +         ((), false) => todo!()
+   |
 
 error: aborting due to 7 previous errors
 
index e34770fb912e79437a0b98a901590bc3eaecacb8..5d1e170ae6c2b5739f4396f09cd1e09c2d55cb53 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `&[false, _]` not covered
 LL |     match s2 {
    |           ^^ pattern `&[false, _]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool; 2]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [true, .., true] => {}
+LL +         &[false, _] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:12:11
@@ -13,8 +17,12 @@ error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
 LL |     match s3 {
    |           ^^ pattern `&[false, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool; 3]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [true, .., true] => {}
+LL +         &[false, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:16:11
@@ -22,8 +30,12 @@ error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
 LL |     match s10 {
    |           ^^^ pattern `&[false, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool; 10]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [true, .., true] => {}
+LL +         &[false, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:25:11
@@ -31,8 +43,12 @@ error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
 LL |     match s2 {
    |           ^^ pattern `&[false, true]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool; 2]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [.., false] => {}
+LL +         &[false, true] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:30:11
@@ -40,8 +56,12 @@ error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
 LL |     match s3 {
    |           ^^ pattern `&[false, .., true]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool; 3]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [.., false] => {}
+LL +         &[false, .., true] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:35:11
@@ -49,8 +69,12 @@ error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
 LL |     match s {
    |           ^ pattern `&[false, .., true]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [.., false] => {}
+LL +         &[false, .., true] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:42:11
@@ -58,8 +82,12 @@ error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
 LL |     match s {
    |           ^ pattern `&[_, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [] => {}
+LL +         &[_, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:46:11
@@ -67,8 +95,12 @@ error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
 LL |     match s {
    |           ^ pattern `&[_, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [_] => {}
+LL +         &[_, _, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:51:11
@@ -76,8 +108,12 @@ error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
 LL |     match s {
    |           ^ pattern `&[false, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [true, ..] => {}
+LL +         &[false, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:56:11
@@ -85,8 +121,12 @@ error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
 LL |     match s {
    |           ^ pattern `&[false, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [true, ..] => {}
+LL +         &[false, _, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:62:11
@@ -94,8 +134,12 @@ error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
 LL |     match s {
    |           ^ pattern `&[_, .., false]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [.., true] => {}
+LL +         &[_, .., false] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:69:11
@@ -103,8 +147,12 @@ error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
 LL |     match s {
    |           ^ pattern `&[_, _, .., true]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [.., false] => {}
+LL +         &[_, _, .., true] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:76:11
@@ -112,8 +160,12 @@ error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
 LL |     match s {
    |           ^ pattern `&[true, _, .., _]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [false, .., false] => {}
+LL +         &[true, _, .., _] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:85:11
@@ -121,8 +173,12 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
 LL |     match s {
    |           ^ patterns `&[]` and `&[_, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         &[true] => {}
+LL +         &[] | &[_, _, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:89:11
@@ -130,8 +186,12 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
 LL |     match s {
    |           ^ patterns `&[]` and `&[_, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         CONST => {}
+LL +         &[] | &[_, _, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:93:11
@@ -139,8 +199,12 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
 LL |     match s {
    |           ^ patterns `&[]` and `&[_, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         &[false] => {}
+LL +         &[] | &[_, _, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:98:11
@@ -148,8 +212,12 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
 LL |     match s {
    |           ^ patterns `&[]` and `&[_, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         CONST => {}
+LL +         &[] | &[_, _, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:103:11
@@ -157,8 +225,12 @@ error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
 LL |     match s {
    |           ^ pattern `&[_, _, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         CONST => {}
+LL +         &[_, _, ..] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:108:11
@@ -166,8 +238,12 @@ error[E0004]: non-exhaustive patterns: `&[false]` not covered
 LL |     match s {
    |           ^ pattern `&[false]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &[_, _, ..] => {}
+LL +         &[false] => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `&[false]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:121:11
@@ -175,8 +251,12 @@ error[E0004]: non-exhaustive patterns: `&[false]` not covered
 LL |     match s1 {
    |           ^^ pattern `&[false]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool; 1]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         CONST1 => {}
+LL +         &[false] => todo!()
+   |
 
 error: aborting due to 20 previous errors
 
index 9b42565ac7342b96512ae368cd6315325b59a3c3..696ef9d8de9362d2ef539a56217077ec87403782 100644 (file)
@@ -4,13 +4,25 @@ error[E0004]: non-exhaustive patterns: `Stable2` and `_` not covered
 LL |     match Foo::Stable {
    |           ^^^^^^^^^^^ patterns `Stable2` and `_` not covered
    |
-  ::: $DIR/auxiliary/unstable.rs:9:5
+note: `Foo` defined here
+  --> $DIR/auxiliary/unstable.rs:9:5
    |
-LL |     Stable2,
-   |     ------- not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum Foo {
+LL | |     #[stable(feature = "stable_test_feature", since = "1.0.0")]
+LL | |     Stable,
+LL | |     #[stable(feature = "stable_test_feature", since = "1.0.0")]
+LL | |     Stable2,
+   | |     ^^^^^^^ not covered
+LL | |     #[unstable(feature = "unstable_test_feature", issue = "none")]
+LL | |     Unstable,
+LL | | }
+   | |_-
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         Foo::Stable => {}
+LL +         Stable2 | _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/stable-gated-patterns.rs:13:11
@@ -18,8 +30,23 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match Foo::Stable {
    |           ^^^^^^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Foo` defined here
+  --> $DIR/auxiliary/unstable.rs:5:1
+   |
+LL | / pub enum Foo {
+LL | |     #[stable(feature = "stable_test_feature", since = "1.0.0")]
+LL | |     Stable,
+LL | |     #[stable(feature = "stable_test_feature", since = "1.0.0")]
+...  |
+LL | |     Unstable,
+LL | | }
+   | |_^
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Foo::Stable2 => {}
+LL +         _ => todo!()
+   |
 
 error: aborting due to 2 previous errors
 
index 23ff6c626f759c63e078f810a4b0dfb1040de1b0..6127fad3f7d54410d144a5d218c6e100cf043366 100644 (file)
@@ -1,18 +1,22 @@
 error[E0004]: non-exhaustive patterns: `B { x: Some(_) }` not covered
   --> $DIR/struct-like-enum-nonexhaustive.rs:8:11
    |
-LL | / enum A {
-LL | |     B { x: Option<isize> },
-   | |     - not covered
-LL | |     C
-LL | | }
-   | |_- `A` defined here
-...
-LL |       match x {
-   |             ^ pattern `B { x: Some(_) }` not covered
+LL |     match x {
+   |           ^ pattern `B { x: Some(_) }` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `A` defined here
+  --> $DIR/struct-like-enum-nonexhaustive.rs:2:5
+   |
+LL | enum A {
+   |      -
+LL |     B { x: Option<isize> },
+   |     ^ not covered
    = note: the matched value is of type `A`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         A::B { x: None } => {}
+LL +         B { x: Some(_) } => todo!()
+   |
 
 error: aborting due to previous error
 
index ca8f67f3c8df2d88c0de7448da6b4207dc035bdd..fc0430d06fa1c03354a6875b6040d6793548f9b2 100644 (file)
@@ -1,14 +1,20 @@
 error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered
   --> $DIR/tuple-struct-nonexhaustive.rs:5:11
    |
-LL | struct Foo(isize, isize);
-   | ------------------------- `Foo` defined here
-...
 LL |     match x {
    |           ^ pattern `Foo(_, _)` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Foo` defined here
+  --> $DIR/tuple-struct-nonexhaustive.rs:1:8
+   |
+LL | struct Foo(isize, isize);
+   |        ^^^
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Foo(2, b) => println!("{}", b)
+LL +         Foo(_, _) => todo!()
+   |
 
 error: aborting due to previous error
 
index 6ce53a4f21ea21ed1402d490fdb54b34fef3ab8a..acae605dae3a870f60e58cb3ccbea349d8eb0441 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
 LL |     match data {
    |           ^^^^ pattern `&[_, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[u8]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         b"" => 1,
+LL ~         &[_, ..] => todo!(),
+   |
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
   --> $DIR/type_polymorphic_byte_str_literals.rs:23:11
@@ -13,8 +17,12 @@ error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not c
 LL |     match data {
    |           ^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[u8]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+   |
+LL ~         [_, _, _] => 1,
+LL ~         _ => todo!(),
+   |
 
 error: aborting due to 2 previous errors
 
index f9c0196b76598163c84e49234590bc0b09ff27c4..8487c9725da8332f6935291b7ec28b33454786a0 100644 (file)
@@ -4,13 +4,24 @@ error[E0004]: non-exhaustive patterns: `Unstable` not covered
 LL |     match Foo::Stable {
    |           ^^^^^^^^^^^ pattern `Unstable` not covered
    |
-  ::: $DIR/auxiliary/unstable.rs:11:5
+note: `Foo` defined here
+  --> $DIR/auxiliary/unstable.rs:11:5
    |
-LL |     Unstable,
-   |     -------- not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum Foo {
+LL | |     #[stable(feature = "stable_test_feature", since = "1.0.0")]
+LL | |     Stable,
+LL | |     #[stable(feature = "stable_test_feature", since = "1.0.0")]
+...  |
+LL | |     Unstable,
+   | |     ^^^^^^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Foo::Stable2 => {}
+LL +         Unstable => todo!()
+   |
 
 error: aborting due to previous error
 
index 30a112d2271b9d53ddb8979e5cef011cefefb3a3..60fce3f51b82f229abb97fa1165a8f6f9d0ff41d 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(pub_restricted)]
-
 struct Bar(pub(()));
 
 struct Foo {
index d856833d04fb19a421bdc81bdbd249ef5913b3b6..95bf498c7f7460684676a30bc6784934cf56b240 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found `(`
-  --> $DIR/pub-restricted-error.rs:6:16
+  --> $DIR/pub-restricted-error.rs:4:16
    |
 LL |     pub(crate) () foo: usize,
    |                ^ expected identifier
index b4bc4a08c7b6d94c1a3e2d66519d0aba355d1ce8..bcd21082f75c68f7804d080d9095bd33f3b5d7c9 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(pub_restricted)]
-
 mod a {}
 
 pub (a) fn afn() {} //~ incorrect visibility restriction
index 56ff104b4fed914a75f97f4ab71d1a759bc227e9..4694530e5486391cd62de5474aef9be0cf9910a0 100644 (file)
@@ -1,5 +1,5 @@
 error[E0704]: incorrect visibility restriction
-  --> $DIR/pub-restricted.rs:5:6
+  --> $DIR/pub-restricted.rs:3:6
    |
 LL | pub (a) fn afn() {}
    |      ^ help: make this visible only to module `a` with `in`: `in a`
@@ -10,7 +10,7 @@ LL | pub (a) fn afn() {}
            `pub(in path::to::module)`: visible only on the specified path
 
 error[E0704]: incorrect visibility restriction
-  --> $DIR/pub-restricted.rs:6:6
+  --> $DIR/pub-restricted.rs:4:6
    |
 LL | pub (b) fn bfn() {}
    |      ^ help: make this visible only to module `b` with `in`: `in b`
@@ -21,7 +21,7 @@ LL | pub (b) fn bfn() {}
            `pub(in path::to::module)`: visible only on the specified path
 
 error[E0704]: incorrect visibility restriction
-  --> $DIR/pub-restricted.rs:7:6
+  --> $DIR/pub-restricted.rs:5:6
    |
 LL | pub (crate::a) fn cfn() {}
    |      ^^^^^^^^ help: make this visible only to module `crate::a` with `in`: `in crate::a`
@@ -32,7 +32,7 @@ LL | pub (crate::a) fn cfn() {}
            `pub(in path::to::module)`: visible only on the specified path
 
 error[E0704]: incorrect visibility restriction
-  --> $DIR/pub-restricted.rs:24:14
+  --> $DIR/pub-restricted.rs:22:14
    |
 LL |         pub (a) invalid: usize,
    |              ^ help: make this visible only to module `a` with `in`: `in a`
@@ -43,7 +43,7 @@ LL |         pub (a) invalid: usize,
            `pub(in path::to::module)`: visible only on the specified path
 
 error[E0704]: incorrect visibility restriction
-  --> $DIR/pub-restricted.rs:33:6
+  --> $DIR/pub-restricted.rs:31:6
    |
 LL | pub (xyz) fn xyz() {}
    |      ^^^ help: make this visible only to module `xyz` with `in`: `in xyz`
@@ -54,7 +54,7 @@ LL | pub (xyz) fn xyz() {}
            `pub(in path::to::module)`: visible only on the specified path
 
 error[E0742]: visibilities can only be restricted to ancestor modules
-  --> $DIR/pub-restricted.rs:25:17
+  --> $DIR/pub-restricted.rs:23:17
    |
 LL |         pub (in x) non_parent_invalid: usize,
    |                 ^
index f904a0ecd11cd135d94fafd7afdb0e71086add7f..ded3cf3ad1d44ab24ed3bd39afea4f634b965b7d 100644 (file)
@@ -4,13 +4,20 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered
 LL |     let Ok(x) = res;
    |         ^^^^^ pattern `Err(_)` not covered
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     --- not covered
-   |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Result<u32, &R>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | / pub enum Result<T, E> {
+LL | |     /// Contains the success value
+LL | |     #[lang = "Ok"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+   | |     ^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `Result<u32, &R>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/src/test/ui/repr/issue-83921-pretty.normal.stderr b/src/test/ui/repr/issue-83921-pretty.normal.stderr
deleted file mode 100644 (file)
index 6b7e831..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-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
deleted file mode 100644 (file)
index aaf3993..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#![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
deleted file mode 100644 (file)
index d5d3647..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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() {}
index e3671e7c49311b7ad800248f6f85d54dc293cdd6..0cd0edf32f2e55bc60e4aec0762a6dc45c1282a6 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(repr_align)]
-
 // See also repr-transparent.rs
 
 #[repr(transparent, C)] //~ ERROR cannot have other repr
index 9b48bb3a43d2a84f26c85008a974fb731f6ebbdd..d92c358110c601ecf02619da2accc2b1fef62d51 100644 (file)
@@ -1,23 +1,23 @@
 error[E0692]: transparent struct cannot have other repr hints
-  --> $DIR/repr-transparent-other-reprs.rs:5:8
+  --> $DIR/repr-transparent-other-reprs.rs:3:8
    |
 LL | #[repr(transparent, C)]
    |        ^^^^^^^^^^^  ^
 
 error[E0692]: transparent struct cannot have other repr hints
-  --> $DIR/repr-transparent-other-reprs.rs:10:8
+  --> $DIR/repr-transparent-other-reprs.rs:8:8
    |
 LL | #[repr(transparent, packed)]
    |        ^^^^^^^^^^^  ^^^^^^
 
 error[E0692]: transparent struct cannot have other repr hints
-  --> $DIR/repr-transparent-other-reprs.rs:13:8
+  --> $DIR/repr-transparent-other-reprs.rs:11:8
    |
 LL | #[repr(transparent, align(2))]
    |        ^^^^^^^^^^^  ^^^^^^^^
 
 error[E0692]: transparent struct cannot have other repr hints
-  --> $DIR/repr-transparent-other-reprs.rs:16:8
+  --> $DIR/repr-transparent-other-reprs.rs:14:8
    |
 LL | #[repr(transparent)]
    |        ^^^^^^^^^^^
index 18d8f5481c9fbf39aa7274b2587e524488ae71bc..60c1f5420f62c29322de982b95fc63ad28cdf9d8 100644 (file)
@@ -4,8 +4,12 @@ error[E0004]: non-exhaustive patterns: `&[]` not covered
 LL |     match sl {
    |           ^^ pattern `&[]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[u8]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [first, remainder @ ..] => {}
+LL ~         &[] => todo!(),
+   |
 
 error: aborting due to previous error
 
index cd9ded81e6a09e72c701039230308050a8293ba9..5ef078c20057df6faeb2dd592a53b16358fb7f21 100644 (file)
@@ -4,8 +4,18 @@ error[E0004]: non-exhaustive patterns: type `EmptyNonExhaustiveEnum` is non-empt
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `EmptyNonExhaustiveEnum` defined here
+  --> $DIR/auxiliary/enums.rs:18:1
+   |
+LL | pub enum EmptyNonExhaustiveEnum {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `EmptyNonExhaustiveEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/enum.rs:16:11
@@ -13,8 +23,21 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match enum_unit {
    |           ^^^^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonExhaustiveEnum` defined here
+  --> $DIR/auxiliary/enums.rs:4:1
+   |
+LL | / pub enum NonExhaustiveEnum {
+LL | |     Unit,
+LL | |     Tuple(u32),
+LL | |     Struct { field: u32 },
+LL | | }
+   | |_^
    = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         NonExhaustiveEnum::Struct { .. } => "third",
+LL +         _ => todo!()
+   |
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/enum.rs:23:11
@@ -22,8 +45,22 @@ error[E0004]: non-exhaustive patterns: `_` not covered
 LL |     match enum_unit {};
    |           ^^^^^^^^^ pattern `_` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `NonExhaustiveEnum` defined here
+  --> $DIR/auxiliary/enums.rs:4:1
+   |
+LL | / pub enum NonExhaustiveEnum {
+LL | |     Unit,
+LL | |     Tuple(u32),
+LL | |     Struct { field: u32 },
+LL | | }
+   | |_^
    = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~     match enum_unit {
+LL +         _ => todo!(),
+LL ~     };
+   |
 
 error: aborting due to 3 previous errors
 
index 966f3a2e414857f3e87aad7af9de953104b033d6..1f20904483fe755649f29eec70edd5d371ce43ce 100644 (file)
@@ -13,46 +13,56 @@ LL | #![deny(unreachable_patterns)]
 error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/enum_same_crate_empty_match.rs:33:11
    |
-LL | / pub enum NonExhaustiveEnum {
-LL | |     Unit,
-   | |     ---- not covered
-LL | |
-LL | |     Tuple(u32),
-   | |     ----- not covered
-LL | |
-LL | |     Struct { field: u32 }
-   | |     ------ not covered
-LL | |
-LL | | }
-   | |_- `NonExhaustiveEnum` defined here
-...
-LL |       match NonExhaustiveEnum::Unit {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match NonExhaustiveEnum::Unit {}
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+   |
+note: `NonExhaustiveEnum` defined here
+  --> $DIR/enum_same_crate_empty_match.rs:5:5
+   |
+LL | pub enum NonExhaustiveEnum {
+   |          -----------------
+LL |     Unit,
+   |     ^^^^ not covered
+LL |
+LL |     Tuple(u32),
+   |     ^^^^^ not covered
+LL |
+LL |     Struct { field: u32 }
+   |     ^^^^^^ not covered
    = note: the matched value is of type `NonExhaustiveEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match NonExhaustiveEnum::Unit {
+LL +         Unit | Tuple(_) | Struct { .. } => todo!(),
+LL +     }
+   |
 
 error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/enum_same_crate_empty_match.rs:35:11
    |
-LL | / pub enum NormalEnum {
-LL | |     Unit,
-   | |     ---- not covered
-LL | |
-LL | |     Tuple(u32),
-   | |     ----- not covered
-LL | |
-LL | |     Struct { field: u32 }
-   | |     ------ not covered
-LL | |
-LL | | }
-   | |_- `NormalEnum` defined here
-...
-LL |       match NormalEnum::Unit {}
-   |             ^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match NormalEnum::Unit {}
+   |           ^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered
+   |
+note: `NormalEnum` defined here
+  --> $DIR/enum_same_crate_empty_match.rs:14:5
+   |
+LL | pub enum NormalEnum {
+   |          ----------
+LL |     Unit,
+   |     ^^^^ not covered
+LL |
+LL |     Tuple(u32),
+   |     ^^^^^ not covered
+LL |
+LL |     Struct { field: u32 }
+   |     ^^^^^^ not covered
    = note: the matched value is of type `NormalEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match NormalEnum::Unit {
+LL +         Unit | Tuple(_) | Struct { .. } => todo!(),
+LL +     }
+   |
 
 error: aborting due to 3 previous errors
 
index c461302a366bdf2fe254f8bd5e093f20d1b85cf1..2dc4eabb8630a141b551cc9cb65cae9e40e399f7 100644 (file)
@@ -4,8 +4,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-emp
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedEnum` defined here
+  --> $DIR/auxiliary/uninhabited.rs:26:1
+   |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
   --> $DIR/indirect_match.rs:23:11
@@ -13,8 +23,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-e
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:28:1
+   |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
   --> $DIR/indirect_match.rs:27:11
@@ -22,8 +42,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedTupleStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:30:1
+   |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
   --> $DIR/indirect_match.rs:33:11
@@ -31,8 +61,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedVariants` defined here
+  --> $DIR/auxiliary/uninhabited.rs:32:1
+   |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error: aborting due to 4 previous errors
 
index 42bf67c0a45dfd06b8f63f7df373528074791033..c1219054140353175cb8cc802b1ec64366ba3850 100644 (file)
@@ -1,50 +1,78 @@
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
   --> $DIR/indirect_match_same_crate.rs:34:11
    |
-LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
-   | ---------------------------------------------------- `IndirectUninhabitedEnum` defined here
-...
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedEnum` defined here
+  --> $DIR/indirect_match_same_crate.rs:20:12
+   |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
   --> $DIR/indirect_match_same_crate.rs:38:11
    |
-LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
-   | -------------------------------------------------------- `IndirectUninhabitedStruct` defined here
-...
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedStruct` defined here
+  --> $DIR/indirect_match_same_crate.rs:22:12
+   |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
   --> $DIR/indirect_match_same_crate.rs:42:11
    |
-LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
-   | ------------------------------------------------------------------ `IndirectUninhabitedTupleStruct` defined here
-...
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedTupleStruct` defined here
+  --> $DIR/indirect_match_same_crate.rs:24:12
+   |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
   --> $DIR/indirect_match_same_crate.rs:48:11
    |
-LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
-   | ------------------------------------------------------------ `IndirectUninhabitedVariants` defined here
-...
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedVariants` defined here
+  --> $DIR/indirect_match_same_crate.rs:26:12
+   |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error: aborting due to 4 previous errors
 
index c397158c02495c1a2b0eb6b8202d745a1a5066a8..f0cb13de3f799b9043fd0aea3ba3afdfd46c1208 100644 (file)
@@ -4,8 +4,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-emp
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedEnum` defined here
+  --> $DIR/auxiliary/uninhabited.rs:26:1
+   |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
   --> $DIR/indirect_match_with_exhaustive_patterns.rs:27:11
@@ -13,8 +23,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-e
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:28:1
+   |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
   --> $DIR/indirect_match_with_exhaustive_patterns.rs:31:11
@@ -22,8 +42,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedTupleStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:30:1
+   |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
   --> $DIR/indirect_match_with_exhaustive_patterns.rs:37:11
@@ -31,8 +61,18 @@ error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `IndirectUninhabitedVariants` defined here
+  --> $DIR/auxiliary/uninhabited.rs:32:1
+   |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error: aborting due to 4 previous errors
 
index d21a94a0d6498ff76bf84681859c290aacfda54f..49febd9241dc6e9cceb1e5dd6511c8910b6afbae 100644 (file)
@@ -4,8 +4,19 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `UninhabitedEnum` defined here
+  --> $DIR/auxiliary/uninhabited.rs:5:1
+   |
+LL | / pub enum UninhabitedEnum {
+LL | | }
+   | |_^
    = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
   --> $DIR/match.rs:23:11
@@ -13,8 +24,20 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `UninhabitedStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:9:1
+   |
+LL | / pub struct UninhabitedStruct {
+LL | |     _priv: !,
+LL | | }
+   | |_^
    = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
   --> $DIR/match.rs:27:11
@@ -22,8 +45,18 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empt
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `UninhabitedTupleStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:14:1
+   |
+LL | pub struct UninhabitedTupleStruct(!);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/match.rs:31:11
@@ -31,15 +64,23 @@ error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covere
 LL |     match x {}
    |           ^ patterns `Tuple(_)` and `Struct { .. }` not covered
    |
-  ::: $DIR/auxiliary/uninhabited.rs:17:23
+note: `UninhabitedVariants` defined here
+  --> $DIR/auxiliary/uninhabited.rs:17:23
    |
-LL |     #[non_exhaustive] Tuple(!),
-   |                       ----- not covered
-LL |     #[non_exhaustive] Struct { x: ! }
-   |                       ------ not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum UninhabitedVariants {
+LL | |     #[non_exhaustive] Tuple(!),
+   | |                       ^^^^^ not covered
+LL | |     #[non_exhaustive] Struct { x: ! }
+   | |                       ^^^^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match x {
+LL +         Tuple(_) | Struct { .. } => todo!(),
+LL ~     }
+   |
 
 error: aborting due to 4 previous errors
 
index e4d0c7022f3b41c9a86d9bec898cb2e65e1c6d7a..c89c70ae6cc1f9acc1272dff64396311eb669aba 100644 (file)
@@ -1,45 +1,63 @@
 error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
   --> $DIR/match_same_crate.rs:30:11
    |
-LL | / pub struct UninhabitedStruct {
-LL | |     _priv: !,
-LL | | }
-   | |_- `UninhabitedStruct` defined here
-...
-LL |       match x {}
-   |             ^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match x {}
+   |           ^
+   |
+note: `UninhabitedStruct` defined here
+  --> $DIR/match_same_crate.rs:8:12
+   |
+LL | pub struct UninhabitedStruct {
+   |            ^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
   --> $DIR/match_same_crate.rs:34:11
    |
-LL | pub struct UninhabitedTupleStruct(!);
-   | ------------------------------------- `UninhabitedTupleStruct` defined here
-...
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `UninhabitedTupleStruct` defined here
+  --> $DIR/match_same_crate.rs:13:12
+   |
+LL | pub struct UninhabitedTupleStruct(!);
+   |            ^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/match_same_crate.rs:38:11
    |
-LL | / pub enum UninhabitedVariants {
-LL | |     #[non_exhaustive] Tuple(!),
-   | |                       ----- not covered
-LL | |     #[non_exhaustive] Struct { x: ! }
-   | |                       ------ not covered
-LL | | }
-   | |_- `UninhabitedVariants` defined here
-...
-LL |       match x {}
-   |             ^ patterns `Tuple(_)` and `Struct { .. }` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL |     match x {}
+   |           ^ patterns `Tuple(_)` and `Struct { .. }` not covered
+   |
+note: `UninhabitedVariants` defined here
+  --> $DIR/match_same_crate.rs:16:23
+   |
+LL | pub enum UninhabitedVariants {
+   |          -------------------
+LL |     #[non_exhaustive] Tuple(!),
+   |                       ^^^^^ not covered
+LL |     #[non_exhaustive] Struct { x: ! }
+   |                       ^^^^^^ not covered
    = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match x {
+LL +         Tuple(_) | Struct { .. } => todo!(),
+LL ~     }
+   |
 
 error: aborting due to 3 previous errors
 
index cc3dc6c29b90461fad6f236e9c09b3261a5ecca4..e18c2678d323c2f4d60498067b71fc817171f02c 100644 (file)
@@ -4,8 +4,19 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `UninhabitedEnum` defined here
+  --> $DIR/auxiliary/uninhabited.rs:5:1
+   |
+LL | / pub enum UninhabitedEnum {
+LL | | }
+   | |_^
    = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
   --> $DIR/match_with_exhaustive_patterns.rs:26:11
@@ -13,8 +24,20 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `UninhabitedStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:9:1
+   |
+LL | / pub struct UninhabitedStruct {
+LL | |     _priv: !,
+LL | | }
+   | |_^
    = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
   --> $DIR/match_with_exhaustive_patterns.rs:30:11
@@ -22,8 +45,18 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empt
 LL |     match x {}
    |           ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `UninhabitedTupleStruct` defined here
+  --> $DIR/auxiliary/uninhabited.rs:14:1
+   |
+LL | pub struct UninhabitedTupleStruct(!);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match x {
+LL +         _ => todo!(),
+LL ~     }
+   |
 
 error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered
   --> $DIR/match_with_exhaustive_patterns.rs:34:11
@@ -31,15 +64,23 @@ error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covere
 LL |     match x {}
    |           ^ patterns `Tuple(_)` and `Struct { .. }` not covered
    |
-  ::: $DIR/auxiliary/uninhabited.rs:17:23
+note: `UninhabitedVariants` defined here
+  --> $DIR/auxiliary/uninhabited.rs:17:23
    |
-LL |     #[non_exhaustive] Tuple(!),
-   |                       ----- not covered
-LL |     #[non_exhaustive] Struct { x: ! }
-   |                       ------ not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+LL | / pub enum UninhabitedVariants {
+LL | |     #[non_exhaustive] Tuple(!),
+   | |                       ^^^^^ not covered
+LL | |     #[non_exhaustive] Struct { x: ! }
+   | |                       ^^^^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match x {
+LL +         Tuple(_) | Struct { .. } => todo!(),
+LL ~     }
+   |
 
 error: aborting due to 4 previous errors
 
index 0291a52633358eeef277f3d4b32e06adf875a758..cf8ca57714c29e5b7ee68115a578ae3e32ed8a11 100644 (file)
@@ -1,27 +1,10 @@
 warning: skipping const checks
    |
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:20:9
-   |
-LL |     let ptr: fn() -> L = attributed;
-   |         ^^^
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5
-   |
-LL |     ptr()
-   |     ^^^
-help: skipping check for `const_fn_fn_ptr_basics` feature
-  --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:20:26
-   |
-LL |     let ptr: fn() -> L = attributed;
-   |                          ^^^^^^^^^^
 help: skipping check that does not even have a feature gate
   --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5
    |
 LL |     ptr()
    |     ^^^^^
 
-error: `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
-
-error: aborting due to previous error; 1 warning emitted
+warning: 1 warning emitted
 
index e33d57d642b32de6d41fefe26f822df60a917bb0..419fb0a0e45893697c44ce7525272b357d2462f0 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 trait Trait<'x, T> where T: 'x {
index adb718ad794a68a7ffa836e94f698ef79269e334..4608962c7c3f8bff490c21c3912989741d9500c0 100644 (file)
@@ -1,5 +1,5 @@
 error: rustc_outlives
-  --> $DIR/explicit-dyn.rs:8:1
+  --> $DIR/explicit-dyn.rs:7:1
    |
 LL | / struct Foo<'a, A>
 LL | | {
index aa1be144ff8769bea9678f0578822ab525fd6198..c53d6c18ff65aea3dcd593d3911608a1de3a5c2b 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 trait Trait<'x, 's, T> where T: 'x,
index 77577fe09457e65cced7671379c5e92a867655dd..7836b3f5aabedf0eed84b8bd851570a80aeb6763 100644 (file)
@@ -1,5 +1,5 @@
 error: rustc_outlives
-  --> $DIR/self-dyn.rs:9:1
+  --> $DIR/self-dyn.rs:8:1
    |
 LL | / struct Foo<'a, 'b, A>
 LL | | {
index 8f73d0120a0b8fea5bda4b4f3c81d98d9390d277..79f6b0dfe34ee0723294000ac2228f8ef36121db 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(crate_in_paths)]
-
 struct S;
 
 pub mod m {
index e4c47901455c9470964bde1efe17adf66d1fca77..7e7ee3ce03d77fd74ca8b31e2992bb19aa21bae6 100644 (file)
@@ -1,11 +1,11 @@
 error[E0433]: failed to resolve: `crate` in paths can only be used in start position
-  --> $DIR/crate-path-non-absolute.rs:7:22
+  --> $DIR/crate-path-non-absolute.rs:5:22
    |
 LL |         let s = ::m::crate::S;
    |                      ^^^^^ `crate` in paths can only be used in start position
 
 error[E0433]: failed to resolve: global paths cannot start with `crate`
-  --> $DIR/crate-path-non-absolute.rs:8:20
+  --> $DIR/crate-path-non-absolute.rs:6:20
    |
 LL |         let s1 = ::crate::S;
    |                    ^^^^^ global paths cannot start with `crate`
index d52ac7ec3c39db17d264091a78688921c2e59e28..019ef8e9dade77a12eac8593252ba2206738d457 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(crate_in_paths)]
-
 fn main() {
     let crate = 0;
     //~^ ERROR expected unit struct, unit variant or constant, found module `crate`
index acbb4cf1a6942d8ec1ffdda1c170027ab4626d48..c39a70f66a97ad03a9ca50213d2de2689abcc3c5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0532]: expected unit struct, unit variant or constant, found module `crate`
-  --> $DIR/keyword-crate-as-identifier.rs:4:9
+  --> $DIR/keyword-crate-as-identifier.rs:2:9
    |
 LL |     let crate = 0;
    |         ^^^^^ not a unit struct, unit variant or constant
index 2d049277d7fcf44e1950d2e0fd9804e98f20f1c4..34934d1e01dbd430c097ad50bce6a212e4fdea86 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_fn_trait_bound)]
 #![feature(const_trait_impl)]
 
 pub trait MyTrait {
index 4b706a190e65e5985a7a3e3048ff0c1fa90e9426..89dc47aad3dd7a47f38cf5b32aa9221abaf38b6b 100644 (file)
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(const_fn_trait_bound)]
 #![feature(const_trait_impl)]
 
 trait MyPartialEq {
index adf8d4f9ea565a208c3d92cd57416df8eb54b968..b00ff1f2fac2a0b8872e3a64b901d43a786b6b9b 100644 (file)
@@ -3,7 +3,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 struct S;
 
index cc24dbd96d2532ebc82c59a2e9fc4a7514891d86..c8ded0fa7ea32a4a6d5715663494d4df111a8683 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 struct S;
 
index e81e0d1e571c32283e6ad127683f2c8fb97d363c..8df68225d44cd34c1b448fbfb39e0ea2c2ec5ff1 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_fn_trait_bound)]
 #![feature(const_trait_impl)]
 
 pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
index 3963f64ad32b3b90b59cb9f2b9ae9b7588012b38..cf114334cc39187dbbbe1cbc5461cb8fa40bbd55 100644 (file)
@@ -1,17 +1,17 @@
 error[E0277]: can't compare `T` with `T` in const contexts
-  --> $DIR/call-generic-method-fail.rs:5:5
+  --> $DIR/call-generic-method-fail.rs:4:5
    |
 LL |     *t == *t
    |     ^^^^^^^^ no implementation for `T == T`
    |
 note: the trait `PartialEq` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/call-generic-method-fail.rs:5:5
+  --> $DIR/call-generic-method-fail.rs:4:5
    |
 LL |     *t == *t
    |     ^^^^^^^^
 
 error[E0015]: cannot call non-const operator in constant functions
-  --> $DIR/call-generic-method-fail.rs:5:5
+  --> $DIR/call-generic-method-fail.rs:4:5
    |
 LL |     *t == *t
    |     ^^^^^^^^
index 585b65988f390ade606315e687ef8895e48fad73..e197c8b73c535e43484fa5da23579abbf7ff225a 100644 (file)
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(const_fn_trait_bound)]
-
 struct S;
 
 impl PartialEq for S {
index 6881db0aa02c3cec75158117a2e856de518efd82..d3e14a53a2fc316e61632ed5cc9365f6995d2e09 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 struct S;
 
index 35b7fe8e401c3162b674e93169a3c6b9d3566ee5..b0af45acda1edc9a15fbf02bbfd1452ea7ef93c5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `S` with `S` in const contexts
-  --> $DIR/call-generic-method-nonconst.rs:19:34
+  --> $DIR/call-generic-method-nonconst.rs:18:34
    |
 LL | pub const EQ: bool = equals_self(&S);
    |                      ----------- ^^ no implementation for `S == S`
@@ -8,12 +8,12 @@ LL | pub const EQ: bool = equals_self(&S);
    |
    = help: the trait `~const PartialEq` is not implemented for `S`
 note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const`
-  --> $DIR/call-generic-method-nonconst.rs:19:34
+  --> $DIR/call-generic-method-nonconst.rs:18:34
    |
 LL | pub const EQ: bool = equals_self(&S);
    |                                  ^^
 note: required by a bound in `equals_self`
-  --> $DIR/call-generic-method-nonconst.rs:12:25
+  --> $DIR/call-generic-method-nonconst.rs:11:25
    |
 LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
    |                         ^^^^^^^^^^^^^^^^ required by this bound in `equals_self`
index aa9bd4d824e1704aba419008433985d59c7f7727..40565d1b76a9c1cfd21fef07e53f18c7eef52073 100644 (file)
@@ -3,7 +3,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 struct S;
 
index 99e608797ff650c2c2b943c83d04d4acdb8084f0..755d853983949fa8bc69b254198338edd7366f5a 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 const fn answer_p1<F>(f: &F) -> u8
     where
index 3e87787a09195aedbdbc0fe420f33aad50a95663..3c82fe1ad6c77f589fa5304c53a6f93d592a065d 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)] // FIXME is this needed?
 
 trait ConstDefaultFn: Sized {
     fn b(self);
index 948830d6def58f7388ccf8d5859f74fe410947cd..fe788b43a5416b4330279af3a43c805930b8dfa9 100644 (file)
@@ -1,17 +1,17 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:25:18
+  --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
    |                  ^^^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
-  --> $DIR/const-default-method-bodies.rs:25:18
+  --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
    |                  ^^^
 
 error[E0015]: cannot call non-const fn `<NonConstImpl as ConstDefaultFn>::a` in constant functions
-  --> $DIR/const-default-method-bodies.rs:25:18
+  --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
    |                  ^^^
index 83fa32bf092bb9140c8404d06cf893e5f0e75bd9..a1cfee6b6e7827a0af36f3ec6d9f08502835caa8 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 #![feature(const_precise_live_drops)]
 
 const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Drop {
index d280cd2556f06f6c0eeed84d923930f512e3b6a1..d88bcdc89ad2b617f760178abff15364983a7b90 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied
-  --> $DIR/const-drop-fail.rs:44:5
+  --> $DIR/const-drop-fail.rs:43:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,7 +8,7 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop`
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+  --> $DIR/const-drop-fail.rs:34:19
    |
 LL | const fn check<T: ~const Drop>(_: T) {}
    |                   ^^^^^^^^^^^ required by this bound in `check`
@@ -20,7 +20,7 @@ LL |     &mut NonTrivialDrop,
    |     ++++
 
 error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied in `ConstImplWithDropGlue`
-  --> $DIR/const-drop-fail.rs:46:5
+  --> $DIR/const-drop-fail.rs:45:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -29,23 +29,23 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop`
    |
 note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const`
-  --> $DIR/const-drop-fail.rs:46:5
+  --> $DIR/const-drop-fail.rs:45:5
    |
 LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it appears within the type `ConstImplWithDropGlue`
-  --> $DIR/const-drop-fail.rs:17:8
+  --> $DIR/const-drop-fail.rs:16:8
    |
 LL | struct ConstImplWithDropGlue(NonTrivialDrop);
    |        ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+  --> $DIR/const-drop-fail.rs:34:19
    |
 LL | const fn check<T: ~const Drop>(_: T) {}
    |                   ^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Drop` is not satisfied
-  --> $DIR/const-drop-fail.rs:48:5
+  --> $DIR/const-drop-fail.rs:47:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -54,12 +54,12 @@ LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop`
    |
 note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds<NonTrivialDrop>`
-  --> $DIR/const-drop-fail.rs:29:25
+  --> $DIR/const-drop-fail.rs:28:25
    |
 LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
    |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+  --> $DIR/const-drop-fail.rs:34:19
    |
 LL | const fn check<T: ~const Drop>(_: T) {}
    |                   ^^^^^^^^^^^ required by this bound in `check`
index 4622723c1891e7da872d12cb091b82ce4f82b612..49968b47dbeb0df4307e0fb94668077c1069bae5 100644 (file)
@@ -1,7 +1,6 @@
 // revisions: stock precise
 #![feature(const_trait_impl)]
 #![feature(const_mut_refs)]
-#![feature(const_fn_trait_bound)]
 #![cfg_attr(precise, feature(const_precise_live_drops))]
 
 use std::marker::PhantomData;
index d280cd2556f06f6c0eeed84d923930f512e3b6a1..d88bcdc89ad2b617f760178abff15364983a7b90 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied
-  --> $DIR/const-drop-fail.rs:44:5
+  --> $DIR/const-drop-fail.rs:43:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,7 +8,7 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop`
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+  --> $DIR/const-drop-fail.rs:34:19
    |
 LL | const fn check<T: ~const Drop>(_: T) {}
    |                   ^^^^^^^^^^^ required by this bound in `check`
@@ -20,7 +20,7 @@ LL |     &mut NonTrivialDrop,
    |     ++++
 
 error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied in `ConstImplWithDropGlue`
-  --> $DIR/const-drop-fail.rs:46:5
+  --> $DIR/const-drop-fail.rs:45:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -29,23 +29,23 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop`
    |
 note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const`
-  --> $DIR/const-drop-fail.rs:46:5
+  --> $DIR/const-drop-fail.rs:45:5
    |
 LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it appears within the type `ConstImplWithDropGlue`
-  --> $DIR/const-drop-fail.rs:17:8
+  --> $DIR/const-drop-fail.rs:16:8
    |
 LL | struct ConstImplWithDropGlue(NonTrivialDrop);
    |        ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+  --> $DIR/const-drop-fail.rs:34:19
    |
 LL | const fn check<T: ~const Drop>(_: T) {}
    |                   ^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Drop` is not satisfied
-  --> $DIR/const-drop-fail.rs:48:5
+  --> $DIR/const-drop-fail.rs:47:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -54,12 +54,12 @@ LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop`
    |
 note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds<NonTrivialDrop>`
-  --> $DIR/const-drop-fail.rs:29:25
+  --> $DIR/const-drop-fail.rs:28:25
    |
 LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
    |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:35:19
+  --> $DIR/const-drop-fail.rs:34:19
    |
 LL | const fn check<T: ~const Drop>(_: T) {}
    |                   ^^^^^^^^^^^ required by this bound in `check`
index 13363c506d54e573dbaed08a99f8604f85e680e6..20b9d7721472cb4cb29054785fb795f434c9fc24 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 // revisions: stock precise
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 #![feature(const_mut_refs)]
 #![feature(never_type)]
 #![cfg_attr(precise, feature(const_precise_live_drops))]
index bc807507fd6683fbf8deda4b6db4cc9aea466547..668e166c29897c2dd47e82b4b49ed6f7de638755 100644 (file)
@@ -1,16 +1,16 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-body-checking.rs:12:15
+  --> $DIR/default-method-body-is-const-body-checking.rs:11:15
    |
 LL |         foo::<()>();
    |               ^^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
-  --> $DIR/default-method-body-is-const-body-checking.rs:12:15
+  --> $DIR/default-method-body-is-const-body-checking.rs:11:15
    |
 LL |         foo::<()>();
    |               ^^
 note: required by a bound in `foo`
-  --> $DIR/default-method-body-is-const-body-checking.rs:7:28
+  --> $DIR/default-method-body-is-const-body-checking.rs:6:28
    |
 LL | const fn foo<T>() where T: ~const Tr {}
    |                            ^^^^^^^^^ required by this bound in `foo`
index db4d61f88ab2f08a85e66bae320e31da06633aa5..cf357971951df5aeef4d4276a4f19ec31927f513 100644 (file)
@@ -1,17 +1,17 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:12
    |
 LL |         ().a()
    |            ^^^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:12
    |
 LL |         ().a()
    |            ^^^
 
 error[E0015]: cannot call non-const fn `<() as Tr>::a` in constant functions
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:12
    |
 LL |         ().a()
    |            ^^^
index d5b1a9073acea92b177c663d134bb5e154401f1b..7f6d86d337582fc6c860435eac518717c48336dc 100644 (file)
@@ -7,7 +7,6 @@
 
 #![feature(staged_api)]
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 #![stable(since = "1", feature = "foo")]
 
 trait Tr {
index 91c3d2d5920bc6675b625f86ace4209f335d169a..5495b531cff56c85978b8870ee0a4960f1a0afdc 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 use std::marker::PhantomData;
 
index 8eefb375b8c1b9346b1520f9a7c7abeb6c6996bd..eba8b665ceb0ec10299f7a9791dcfb84af1173d1 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 trait Tr {
     fn req(&self);
index a0916797041114b373ce94bbf1a541db340269fb..4ec6f929ffcd9a1bd99e6f6d479789bc395afc3e 100644 (file)
@@ -1,5 +1,5 @@
 error: const trait implementations may not use non-const default functions
-  --> $DIR/impl-with-default-fn-fail.rs:18:1
+  --> $DIR/impl-with-default-fn-fail.rs:17:1
    |
 LL | / impl const Tr for S {
 LL | |     fn req(&self) {}
@@ -9,7 +9,7 @@ LL | | }
    = note: `prov` not implemented
 
 error: const trait implementations may not use non-const default functions
-  --> $DIR/impl-with-default-fn-fail.rs:28:1
+  --> $DIR/impl-with-default-fn-fail.rs:27:1
    |
 LL | / impl const Tr for u32 {
 LL | |     fn req(&self) {}
@@ -20,7 +20,7 @@ LL | | }
    = note: `prov` not implemented
 
 error[E0046]: not all trait items implemented, missing: `req`
-  --> $DIR/impl-with-default-fn-fail.rs:22:1
+  --> $DIR/impl-with-default-fn-fail.rs:21:1
    |
 LL |     fn req(&self);
    |     -------------- `req` from trait
index ba3fec0882b02e306b3fd9919cfb1ca83d477a71..2e4664714a70ab8e74f9c6595488cba1ec276c37 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 trait Tr {
     fn req(&self);
index fe1015b3bf7ee0549f7471612b01cc74f290a936..2cef803a90e0764ed7e96596643c7b230e7df38c 100644 (file)
@@ -1,6 +1,5 @@
 // check-pass
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 struct S;
 
index cbe3fe0ce5f3f461be5606e7687de5ef0ce92459..b132c395ac7b4f208bc6cdfc3a6b468d81f6e1d1 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_fn_trait_bound)]
 #![feature(const_trait_impl)]
 
 pub trait A {
index 931c0b3658fd9d4f0d26e30a29ca46fbc36b0256..955923505200a136397ba3a03bcfbde7da7dc3e6 100644 (file)
@@ -1,17 +1,17 @@
 error[E0277]: the trait bound `T: ~const A` is not satisfied
-  --> $DIR/issue-88155.rs:9:5
+  --> $DIR/issue-88155.rs:8:5
    |
 LL |     T::assoc()
    |     ^^^^^^^^^^ the trait `~const A` is not implemented for `T`
    |
 note: the trait `A` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/issue-88155.rs:9:5
+  --> $DIR/issue-88155.rs:8:5
    |
 LL |     T::assoc()
    |     ^^^^^^^^^^
 
 error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions
-  --> $DIR/issue-88155.rs:9:5
+  --> $DIR/issue-88155.rs:8:5
    |
 LL |     T::assoc()
    |     ^^^^^^^^^^
index 9bf0886084f912e577c0fe980560a5f1ed213ed9..da7147acdd7e9afe9b9fe45ac62357f18e56892b 100644 (file)
@@ -10,7 +10,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 pub trait Tr {}
 
index 158c628c3e0cb1638cdc4f62924fd163fc882cc3..97c27ce1a1cfa05cc1b783d150aa4583aa3238f0 100644 (file)
@@ -2,7 +2,6 @@
 //
 // check-pass
 
-#![feature(const_fn_trait_bound)]
 #![feature(const_trait_impl)]
 
 pub trait Super {}
index ef74ef8e426201133e055af0b4015ab3a80943c3..defef9e04098e55b43153e1389d4a2418ddd40a7 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 trait Convert<T> {
     fn to(self) -> T;
index 6b54a9eab5205bb904bfb9474b30d7f44f773962..906956f5eba49613034cb3fe00d86ad2140d1f31 100644 (file)
@@ -2,7 +2,9 @@
 #![feature(const_add)]
 #![feature(const_trait_impl)]
 #![feature(staged_api)]
+#![stable(feature = "rust1", since = "1.0.0")]
 
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Int(i32);
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -16,6 +18,7 @@ fn sub(self, rhs: Self) -> Self {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_add", issue = "none")]
 impl const std::ops::Add for Int {
     type Output = Self;
index 5649f688fe7c6211c762abae3f7e75b66c65f57a..7473b801cce63127f3fa609594d438e70f9acad0 100644 (file)
@@ -1,5 +1,5 @@
 error: trait methods cannot be stable const fn
-  --> $DIR/stability.rs:13:5
+  --> $DIR/stability.rs:15:5
    |
 LL | /     fn sub(self, rhs: Self) -> Self {
 LL | |
@@ -8,7 +8,7 @@ LL | |     }
    | |_____^
 
 error: `<Int as Add>::add` is not yet stable as a const fn
-  --> $DIR/stability.rs:31:5
+  --> $DIR/stability.rs:34:5
    |
 LL |     Int(1i32) + Int(2i32)
    |     ^^^^^^^^^^^^^^^^^^^^^
index cbfdf89b7bd191817c4080cd2cce8b6bc7c9cfac..f4a5d0133ce89666af369f11b9ec9fe4f9d781db 100644 (file)
@@ -2,7 +2,6 @@
 
 #![feature(staged_api)]
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 #![feature(const_t_try)]
 #![feature(const_try)]
 #![feature(try_trait_v2)]
index 0cde5b6f84218951370ff4b47730b7659be77ef8..e47c5c7bd6665b1168d5a9aab997d3791f7926f5 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 trait Bar {
     fn bar() -> u8;
index ae9ab26cdc04ad708706007e9bc19e9dc742f512..acea58eaecb9ae9dc6725144e1b6086c9d5ce83d 100644 (file)
@@ -1,7 +1,6 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_fn_trait_bound)]
 
 trait Foo {
     fn bar() where Self: ~const Foo;
index d64822d7ce8af77a4d5296a668dfffe0c8551f5d..d37ed3bb8dd9a640ac9907f49e082772f653a9de 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_fn_trait_bound)]
 #![feature(const_trait_impl)]
 
 trait Bar {}
index f9b5d81c63b85a420c3c591456a1e8cc60fe8655..d5b2d269730967bdbcef68fce42a968058c8508e 100644 (file)
@@ -1,16 +1,16 @@
 error[E0277]: the trait bound `T: ~const Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:14:5
+  --> $DIR/trait-where-clause.rs:13:5
    |
 LL |     T::b();
    |     ^^^^ the trait `~const Bar` is not implemented for `T`
    |
 note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/trait-where-clause.rs:14:5
+  --> $DIR/trait-where-clause.rs:13:5
    |
 LL |     T::b();
    |     ^^^^
 note: required by a bound in `Foo::b`
-  --> $DIR/trait-where-clause.rs:8:24
+  --> $DIR/trait-where-clause.rs:7:24
    |
 LL |     fn b() where Self: ~const Bar;
    |                        ^^^^^^^^^^ required by this bound in `Foo::b`
@@ -20,18 +20,18 @@ LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
    |                                    ++++++++++++
 
 error[E0277]: the trait bound `T: ~const Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:16:5
+  --> $DIR/trait-where-clause.rs:15:5
    |
 LL |     T::c::<T>();
    |     ^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
    |
 note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/trait-where-clause.rs:16:5
+  --> $DIR/trait-where-clause.rs:15:5
    |
 LL |     T::c::<T>();
    |     ^^^^^^^^^
 note: required by a bound in `Foo::c`
-  --> $DIR/trait-where-clause.rs:9:13
+  --> $DIR/trait-where-clause.rs:8:13
    |
 LL |     fn c<T: ~const Bar>();
    |             ^^^^^^^^^^ required by this bound in `Foo::c`
@@ -41,13 +41,13 @@ LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
    |                                    ++++++++++++
 
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:28:5
+  --> $DIR/trait-where-clause.rs:27:5
    |
 LL |     T::b();
    |     ^^^^ the trait `Bar` is not implemented for `T`
    |
 note: required by a bound in `Foo::b`
-  --> $DIR/trait-where-clause.rs:8:24
+  --> $DIR/trait-where-clause.rs:7:24
    |
 LL |     fn b() where Self: ~const Bar;
    |                        ^^^^^^^^^^ required by this bound in `Foo::b`
@@ -57,13 +57,13 @@ LL | fn test3<T: Foo + Bar>() {
    |                 +++++
 
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:30:5
+  --> $DIR/trait-where-clause.rs:29:5
    |
 LL |     T::c::<T>();
    |     ^^^^^^^^^ the trait `Bar` is not implemented for `T`
    |
 note: required by a bound in `Foo::c`
-  --> $DIR/trait-where-clause.rs:9:13
+  --> $DIR/trait-where-clause.rs:8:13
    |
 LL |     fn c<T: ~const Bar>();
    |             ^^^^^^^^^^ required by this bound in `Foo::c`
index 5c40d78d81c29f9a00d215a8dec3e1f310272a6b..ec5bb656ad4e717a1cfaca5ab319071c732df8b8 100644 (file)
@@ -2,8 +2,6 @@
 // compile-flags: --extern issue_56596
 // aux-build:issue-56596.rs
 
-#![feature(uniform_paths)]
-
 mod m {
     pub mod issue_56596 {}
 }
index d2297385f33deb8f007027f16460f011a4e6fd8d..8b8ab26dce2242d3b0d04f81b1be198b9ba7ede2 100644 (file)
@@ -1,5 +1,5 @@
 error[E0659]: `issue_56596` is ambiguous
-  --> $DIR/issue-56596.rs:12:5
+  --> $DIR/issue-56596.rs:10:5
    |
 LL | use issue_56596;
    |     ^^^^^^^^^^^ ambiguous name
@@ -8,7 +8,7 @@ LL | use issue_56596;
    = note: `issue_56596` could refer to a crate passed with `--extern`
    = help: use `::issue_56596` to refer to this crate unambiguously
 note: `issue_56596` could also refer to the module imported here
-  --> $DIR/issue-56596.rs:11:5
+  --> $DIR/issue-56596.rs:9:5
    |
 LL | use m::*;
    |     ^^^^
diff --git a/src/test/ui/rust-2018/unresolved-asterisk-imports.rs b/src/test/ui/rust-2018/unresolved-asterisk-imports.rs
new file mode 100644 (file)
index 0000000..ad10645
--- /dev/null
@@ -0,0 +1,6 @@
+// edition:2018
+
+use not_existing_crate::*; //~ ERROR unresolved import `not_existing_crate
+use std as foo;
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/unresolved-asterisk-imports.stderr b/src/test/ui/rust-2018/unresolved-asterisk-imports.stderr
new file mode 100644 (file)
index 0000000..09e9edc
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `not_existing_crate`
+  --> $DIR/unresolved-asterisk-imports.rs:3:5
+   |
+LL | use not_existing_crate::*;
+   |     ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `not_existing_crate`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
index 22b9dde8cbe5c9e1107d39a452b7dfe982ccccaf..6b065bf6cbff299035595904e39b2cbf4b4e1e5e 100644 (file)
@@ -1,6 +1,6 @@
 // Regression test for #23827
 
-#![feature(core, fn_traits, unboxed_closures)]
+#![feature(fn_traits, unboxed_closures)]
 
 pub struct Prototype {
     pub target: u32
index 1f0a7a8f8a5e6e816de626710dbc2d6ac150885b..1627d1d3f9f19312f3a125ae42cd996414d21b4f 100644 (file)
@@ -3,4 +3,5 @@
 #[unstable()] //~ ERROR: stability attributes may not be used
 #[stable()] //~ ERROR: stability attributes may not be used
 #[rustc_deprecated()] //~ ERROR: stability attributes may not be used
-fn main() { }
+//~^ ERROR missing 'since'
+fn main() {}
index 32b0f405d6fb0a1319f01462665cd3f351f47e3e..a2b2d3cbe595196388c8bf8ac4c470638e2082e0 100644 (file)
@@ -16,6 +16,13 @@ error[E0734]: stability attributes may not be used outside of the standard libra
 LL | #[rustc_deprecated()]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error[E0542]: missing 'since'
+  --> $DIR/stability-attribute-non-staged-force-unstable.rs:5:1
+   |
+LL | #[rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0734`.
+Some errors have detailed explanations: E0542, E0734.
+For more information about an error, try `rustc --explain E0542`.
index fc2c2b587fead19bda22cd7ece39b3b61e0f2971..dfbd9ea5ebf2e5150c4a91a90dd2d0200f1674a0 100644 (file)
@@ -1,4 +1,5 @@
 #[unstable()] //~ ERROR: stability attributes may not be used
 #[stable()] //~ ERROR: stability attributes may not be used
 #[rustc_deprecated()] //~ ERROR: stability attributes may not be used
-fn main() { }
+//~^ ERROR missing 'since'
+fn main() {}
index 7648effc480b54397d8da2e7204330d57ae3b150..9af8d1df4ea040bb390700f56b4dd78d033f4ac9 100644 (file)
@@ -16,6 +16,13 @@ error[E0734]: stability attributes may not be used outside of the standard libra
 LL | #[rustc_deprecated()]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error[E0542]: missing 'since'
+  --> $DIR/stability-attribute-non-staged.rs:3:1
+   |
+LL | #[rustc_deprecated()]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0734`.
+Some errors have detailed explanations: E0542, E0734.
+For more information about an error, try `rustc --explain E0542`.
index c64899c1e9240db697ce0a715d3dbd6c23c43f3a..b85f9342045a01cf9a1a5448a123bc462dca5e2b 100644 (file)
@@ -19,10 +19,12 @@ fn f4() { }
 
     #[stable(feature = "a", since = "b")]
     #[rustc_deprecated] //~ ERROR malformed `rustc_deprecated` attribute
+                        //~^ ERROR missing 'since'
     fn f5() { }
 
     #[stable(feature = "a", since = "b")]
     #[rustc_deprecated = "a"] //~ ERROR malformed `rustc_deprecated` attribute
+                              //~^ ERROR missing 'since'
     fn f6() { }
 }
 
index 9d23b344ed15e07e83b27c81fdf668211321a8f1..651f293ff519e31e92b6a37258a132bf6f00ba45 100644 (file)
@@ -29,10 +29,23 @@ LL |     #[rustc_deprecated]
    |     ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_deprecated(since = "version", reason = "...")]`
 
 error: malformed `rustc_deprecated` attribute input
-  --> $DIR/stability-attribute-sanity-4.rs:25:5
+  --> $DIR/stability-attribute-sanity-4.rs:26:5
    |
 LL |     #[rustc_deprecated = "a"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_deprecated(since = "version", reason = "...")]`
 
-error: aborting due to 6 previous errors
+error[E0542]: missing 'since'
+  --> $DIR/stability-attribute-sanity-4.rs:21:5
+   |
+LL |     #[rustc_deprecated]
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error[E0542]: missing 'since'
+  --> $DIR/stability-attribute-sanity-4.rs:26:5
+   |
+LL |     #[rustc_deprecated = "a"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0542`.
index d7cb66d9c84ec72657e53a69a519c5fb9f9c6f20..fe8079dbc3701d5c7c2a708c93b1fb4afa6e4f33 100644 (file)
@@ -65,6 +65,7 @@ fn multiple3() { }
 pub const fn multiple4() { }
 
 #[stable(feature = "a", since = "1.0.0")] //~ ERROR invalid deprecation version found
+//~^ ERROR feature `a` is declared stable since 1.0.0
 #[rustc_deprecated(since = "invalid", reason = "text")]
 fn invalid_deprecation_version() {}
 
index 4dc68662033bb7f427463a99c0fa6546a6e070b4..b4e8fc78815497d2b5e5eb63d98b2946b97fd35f 100644 (file)
@@ -110,17 +110,23 @@ error: invalid deprecation version found
    |
 LL | #[stable(feature = "a", since = "1.0.0")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid deprecation version
-LL | #[rustc_deprecated(since = "invalid", reason = "text")]
+...
 LL | fn invalid_deprecation_version() {}
    | ----------------------------------- the stability attribute annotates this item
 
 error[E0549]: rustc_deprecated attribute must be paired with either stable or unstable attribute
-  --> $DIR/stability-attribute-sanity.rs:71:1
+  --> $DIR/stability-attribute-sanity.rs:72:1
    |
 LL | #[rustc_deprecated(since = "a", reason = "text")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 19 previous errors
+error[E0711]: feature `a` is declared stable since 1.0.0, but was previously declared stable since b
+  --> $DIR/stability-attribute-sanity.rs:67:1
+   |
+LL | #[stable(feature = "a", since = "1.0.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 20 previous errors
 
 Some errors have detailed explanations: E0539, E0541, E0542, E0543, E0544, E0546, E0547, E0549, E0550.
 For more information about an error, try `rustc --explain E0539`.
index 4aaac2d95d44793907e0fb459cc79a19405d66c5..ce847c86bedde078bf1190e1127ba9f86d8fa6d8 100644 (file)
@@ -45,6 +45,7 @@ trait Tar<'t, 'k, I> {}
     //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
     //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
     //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
 }
 thread_local! {
     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -52,6 +53,7 @@ trait Tar<'t, 'k, I> {}
     //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
     //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
     //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+    //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
     //~| ERROR missing lifetime
     //~| ERROR missing lifetime
 }
index bf546384124c061a83d2529ea7b435b67b5ff4c1..b04ea1c9158df41d7692e79859099fb46c3dca15 100644 (file)
@@ -13,14 +13,15 @@ LL |     static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefC
 error[E0106]: missing lifetime specifiers
   --> $DIR/missing-lifetime-specifier.rs:18:44
    |
-LL |     static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^ expected 2 lifetime parameters
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefCell::new(HashMap::new());
-   |                                            ~~~~~~~~~~~~~~~~~~~~~
+LL | / thread_local! {
+LL | |     static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
+   | |                                            ^^^ expected 2 lifetime parameters
+LL | |
+LL | |
+LL | | }
+   | |_-
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
 
 error[E0106]: missing lifetime specifier
   --> $DIR/missing-lifetime-specifier.rs:23:44
@@ -49,26 +50,32 @@ LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar<'static, 'static>>>>> = Ref
 error[E0106]: missing lifetime specifier
   --> $DIR/missing-lifetime-specifier.rs:23:44
    |
-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
-   |                                            ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&'static Bar>>>> = RefCell::new(HashMap::new());
-   |                                            ~~~~~~~~
+LL | / thread_local! {
+LL | |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
+   | |                                            ^ expected named lifetime parameter
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_-
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
 
 error[E0106]: missing lifetime specifiers
   --> $DIR/missing-lifetime-specifier.rs:23:45
    |
-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^ expected 2 lifetime parameters
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar<'static, 'static>>>>> = RefCell::new(HashMap::new());
-   |                                             ~~~~~~~~~~~~~~~~~~~~~
+LL | / thread_local! {
+LL | |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
+   | |                                             ^^^ expected 2 lifetime parameters
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_-
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
 
 error[E0106]: missing lifetime specifiers
   --> $DIR/missing-lifetime-specifier.rs:30:48
@@ -85,14 +92,15 @@ LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> =
 error[E0106]: missing lifetime specifiers
   --> $DIR/missing-lifetime-specifier.rs:30:48
    |
-LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
-   |                                                ^ expected 2 lifetime parameters
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
+LL | / thread_local! {
+LL | |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
+   | |                                                ^ expected 2 lifetime parameters
+LL | |
+LL | |
+LL | | }
+   | |_-
    |
-LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                +++++++++++++++++
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
 
 error[E0106]: missing lifetime specifier
   --> $DIR/missing-lifetime-specifier.rs:35:44
@@ -121,26 +129,50 @@ LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>>
 error[E0106]: missing lifetime specifier
   --> $DIR/missing-lifetime-specifier.rs:35:44
    |
-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ~~~~~~~~
+LL | / thread_local! {
+LL | |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
+   | |                                            ^ expected named lifetime parameter
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_-
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
 
 error[E0106]: missing lifetime specifiers
   --> $DIR/missing-lifetime-specifier.rs:35:49
    |
-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
-   |                                                 ^ expected 2 lifetime parameters
+LL | / thread_local! {
+LL | |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
+   | |                                                 ^ expected 2 lifetime parameters
+LL | |
+LL | |
+LL | |
+LL | |
+LL | | }
+   | |_-
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
+
+error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/missing-lifetime-specifier.rs:43:44
    |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^^^ ------- supplied 1 lifetime argument
+   |                                            |
+   |                                            expected 2 lifetime arguments
    |
-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                 +++++++++++++++++
+note: union defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:11:11
+   |
+LL | pub union Qux<'t, 'k, I> {
+   |           ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, '_, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       ++++
 
 error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
@@ -157,7 +189,7 @@ LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
 help: add missing lifetime argument
    |
-LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, '_, i32>>>>> = RefCell::new(HashMap::new());
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
    |                                                       ++++
 
 error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
@@ -215,7 +247,7 @@ LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, '_, i32>>>>> = RefC
    |                                                       ++++
 
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing-lifetime-specifier.rs:50:45
+  --> $DIR/missing-lifetime-specifier.rs:51:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^ ------- supplied 1 lifetime argument
@@ -233,7 +265,7 @@ LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, '_, i32>>>>> = Ref
    |                                                        ++++
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:50:44
+  --> $DIR/missing-lifetime-specifier.rs:51:44
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^ expected named lifetime parameter
@@ -245,7 +277,7 @@ LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> =
    |                                            ~~~~~~~~
 
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing-lifetime-specifier.rs:50:45
+  --> $DIR/missing-lifetime-specifier.rs:51:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^ ------- supplied 1 lifetime argument
@@ -263,19 +295,40 @@ LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = Ref
    |                                                        ++++
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:50:44
+  --> $DIR/missing-lifetime-specifier.rs:51:44
+   |
+LL | / thread_local! {
+LL | |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   | |                                            ^ expected named lifetime parameter
+LL | |
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_-
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
+
+error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/missing-lifetime-specifier.rs:51:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^ expected named lifetime parameter
+   |                                             ^^^ ------- supplied 1 lifetime argument
+   |                                             |
+   |                                             expected 2 lifetime arguments
    |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
+note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
+  --> $DIR/missing-lifetime-specifier.rs:15:7
    |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ~~~~~~~~
+LL | trait Tar<'t, 'k, I> {}
+   |       ^^^ --  --
+help: add missing lifetime argument
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        ++++
 
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing-lifetime-specifier.rs:50:45
+  --> $DIR/missing-lifetime-specifier.rs:51:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^ ------- supplied 1 lifetime argument
@@ -293,7 +346,7 @@ LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = Ref
    |                                                        ++++
 
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing-lifetime-specifier.rs:50:45
+  --> $DIR/missing-lifetime-specifier.rs:51:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^ ------- supplied 1 lifetime argument
@@ -310,7 +363,7 @@ help: add missing lifetime argument
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, '_, i32>>>>> = RefCell::new(HashMap::new());
    |                                                        ++++
 
-error: aborting due to 22 previous errors
+error: aborting due to 24 previous errors
 
 Some errors have detailed explanations: E0106, E0107.
 For more information about an error, try `rustc --explain E0106`.
index 5ea7821554300958907045ee83c100290c447930..ad1b6e96be6249e3184faace63c44be54d28e871 100644 (file)
@@ -12,7 +12,6 @@
 // ignore-sparc
 // ignore-sparc64
 
-#![feature(target_feature)]
 #![warn(unused_attributes)]
 
 #[target_feature = "+sse2"]
index 8c8e24ccc55ccc7b19d7a98cdf15f2caf72efe01..25a2c1975e7b2d9f7f510c15961578828f00d009 100644 (file)
@@ -1,29 +1,29 @@
 error: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:18:1
+  --> $DIR/invalid-attribute.rs:17:1
    |
 LL | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]`
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/invalid-attribute.rs:20:18
+  --> $DIR/invalid-attribute.rs:19:18
    |
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^ `foo` is not valid for this target
 
 error: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:23:18
+  --> $DIR/invalid-attribute.rs:22:18
    |
 LL | #[target_feature(bar)]
    |                  ^^^ help: must be of the form: `enable = ".."`
 
 error: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:25:18
+  --> $DIR/invalid-attribute.rs:24:18
    |
 LL | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
 
 error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
-  --> $DIR/invalid-attribute.rs:29:1
+  --> $DIR/invalid-attribute.rs:28:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ LL | fn bar() {}
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:35:1
+  --> $DIR/invalid-attribute.rs:34:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL | mod another {}
    | -------------- not a function
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:40:1
+  --> $DIR/invalid-attribute.rs:39:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | const FOO: usize = 7;
    | --------------------- not a function
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:45:1
+  --> $DIR/invalid-attribute.rs:44:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL | struct Foo;
    | ----------- not a function
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:50:1
+  --> $DIR/invalid-attribute.rs:49:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL | enum Bar {}
    | ----------- not a function
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:55:1
+  --> $DIR/invalid-attribute.rs:54:1
    |
 LL |   #[target_feature(enable = "sse2")]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,7 +84,7 @@ LL | | }
    | |_- not a function
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:63:1
+  --> $DIR/invalid-attribute.rs:62:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -93,13 +93,13 @@ LL | trait Baz {}
    | ------------ not a function
 
 error: cannot use `#[inline(always)]` with `#[target_feature]`
-  --> $DIR/invalid-attribute.rs:68:1
+  --> $DIR/invalid-attribute.rs:67:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:86:5
+  --> $DIR/invalid-attribute.rs:85:5
    |
 LL |       #[target_feature(enable = "sse2")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -111,7 +111,7 @@ LL | |     }
    | |_____- not a function
 
 error: attribute should be applied to a function
-  --> $DIR/invalid-attribute.rs:94:5
+  --> $DIR/invalid-attribute.rs:93:5
    |
 LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL |     || {};
    |     ----- not a function
 
 error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
-  --> $DIR/invalid-attribute.rs:78:5
+  --> $DIR/invalid-attribute.rs:77:5
    |
 LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index b2f681c01d156c12553b9403f305eb21335c5627..a460480afb157efb7e030c3087dfa19da80b53e3 100644 (file)
@@ -58,7 +58,7 @@ macro_rules! foo {
     () => {};
 }
 
-#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function
+#[test] //~ WARN: the `#[test]` attribute may only be used on a non-associated function
 foo!();
 
 // make sure it doesn't erroneously trigger on a real test
index dd693cf316dc7c87561f8be1e045db311ce22f59..23efd5bc0d9faee37fc5571f80e92eed55c6f3d0 100644 (file)
@@ -2,11 +2,10 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:3:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | mod test {}
    | ----------- expected a non-associated function, found a module
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -16,7 +15,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:6:1
    |
 LL |   #[test]
-   |   ^^^^^^^
+   |   ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | / mod loooooooooooooong_teeeeeeeeeest {
 LL | |     /*
 LL | |     this is a comment
@@ -26,7 +25,6 @@ LL | |     */
 LL | | }
    | |_- expected a non-associated function, found a module
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -36,11 +34,10 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:20:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | extern "C" {}
    | ------------- expected a non-associated function, found an extern block
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -50,11 +47,10 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:23:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | trait Foo {}
    | ------------ expected a non-associated function, found a trait
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -64,11 +60,10 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:26:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | impl Foo for i32 {}
    | ------------------- expected a non-associated function, found an implementation
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -78,11 +73,10 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:29:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | const FOO: i32 = -1_i32;
    | ------------------------ expected a non-associated function, found a constant item
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -92,11 +86,10 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:32:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | static BAR: u64 = 10_000_u64;
    | ----------------------------- expected a non-associated function, found a static item
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -106,13 +99,12 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:35:1
    |
 LL |   #[test]
-   |   ^^^^^^^
+   |   ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | / enum MyUnit {
 LL | |     Unit,
 LL | | }
    | |_- expected a non-associated function, found an enum
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -122,11 +114,10 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:40:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | struct NewI32(i32);
    | ------------------- expected a non-associated function, found a struct
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -136,14 +127,13 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:43:1
    |
 LL |   #[test]
-   |   ^^^^^^^
+   |   ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | / union Spooky {
 LL | |     x: i32,
 LL | |     y: u32,
 LL | | }
    | |_- expected a non-associated function, found a union
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
@@ -153,7 +143,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:50:1
    |
 LL |   #[test]
-   |   ^^^^^^^
+   |   ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL |   #[derive(Copy, Clone, Debug)]
 LL | / struct MoreAttrs {
 LL | |     a: i32,
@@ -161,25 +151,23 @@ LL | |     b: u64,
 LL | | }
    | |_- expected a non-associated function, found a struct
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
    | ~~~~~~~~~~~~
 
-error: the `#[test]` attribute may only be used on a non-associated function
+warning: the `#[test]` attribute may only be used on a non-associated function
   --> $DIR/test-on-not-fn.rs:61:1
    |
 LL | #[test]
-   | ^^^^^^^
+   | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 LL | foo!();
    | ------- expected a non-associated function, found an item macro invocation
    |
-   = note: the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
 help: replace with conditional compilation to make the item only exist when tests are being run
    |
 LL | #[cfg(test)]
    | ~~~~~~~~~~~~
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors; 1 warning emitted
 
index 0f4b5936dd015ac61941045e9ed0903c91843428..8dc0e75f1af22467dc3f416b3f48439d5b07f228 100644 (file)
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/issue-43733.rs:17:5
+  --> $DIR/issue-43733.rs:19:5
    |
 LL |     __KEY.get(Default::default)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     __KEY.get(Default::default)
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/issue-43733.rs:20:42
+  --> $DIR/issue-43733.rs:22:42
    |
 LL | static FOO: std::thread::LocalKey<Foo> = std::thread::LocalKey::new(__getit);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
index 5434140cd61280b7bc7f6d06eed501b815aac9f3..9926ed09bb4a84088a35e520f0bcd0124fef0a4b 100644 (file)
@@ -4,6 +4,8 @@
 #![feature(thread_local)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
+use std::cell::RefCell;
+
 type Foo = std::cell::RefCell<String>;
 
 #[cfg(target_thread_local)]
@@ -13,7 +15,7 @@
 #[cfg(not(target_thread_local))]
 static __KEY: std::thread::__OsLocalKeyInner<Foo> = std::thread::__OsLocalKeyInner::new();
 
-fn __getit() -> std::option::Option<&'static Foo> {
+fn __getit(_: Option<&mut Option<RefCell<String>>>) -> std::option::Option<&'static Foo> {
     __KEY.get(Default::default) //~ ERROR call to unsafe function is unsafe
 }
 
index 0f4b5936dd015ac61941045e9ed0903c91843428..8dc0e75f1af22467dc3f416b3f48439d5b07f228 100644 (file)
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/issue-43733.rs:17:5
+  --> $DIR/issue-43733.rs:19:5
    |
 LL |     __KEY.get(Default::default)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     __KEY.get(Default::default)
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/issue-43733.rs:20:42
+  --> $DIR/issue-43733.rs:22:42
    |
 LL | static FOO: std::thread::LocalKey<Foo> = std::thread::LocalKey::new(__getit);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
index 63d17414c313bab96f509f4f12ed99b2dbf61a54..7ffa0de6c0fcc034960393377ececdc20191b9f0 100644 (file)
@@ -1,5 +1,5 @@
-#![feature(try_trait)]
 // edition:2018
+
 fn main() {}
 
 fn a_function() -> u32 {
index f2012936a1174394daaf77eabbcbb32650895b1e..8519932a634150dfc4ccbbc8adee1b24f67eff42 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(try_trait)]
-
 fn main() {}
 
 fn foo() -> Result<u32, ()> {
index 27e33bc022efb1fddf8f2218b69e7f866415227a..24db9f524370351d6ee6d68f9e2e8594468025b7 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
-  --> $DIR/try-on-option.rs:7:6
+  --> $DIR/try-on-option.rs:5:6
    |
 LL | / fn foo() -> Result<u32, ()> {
 LL | |     let x: Option<u32> = None;
@@ -12,7 +12,7 @@ LL | | }
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
 
 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
+  --> $DIR/try-on-option.rs:11:6
    |
 LL | / fn bar() -> u32 {
 LL | |     let x: Option<u32> = None;
diff --git a/src/test/ui/tuple/wrong_argument_ice-3.rs b/src/test/ui/tuple/wrong_argument_ice-3.rs
new file mode 100644 (file)
index 0000000..951687c
--- /dev/null
@@ -0,0 +1,17 @@
+struct Process;
+
+pub type Group = (Vec<String>, Vec<Process>);
+
+fn test(process: &Process, groups: Vec<Group>) -> Vec<Group> {
+    let new_group = vec![String::new()];
+
+    if groups.capacity() == 0 {
+        groups.push(new_group, vec![process]);
+        //~^ ERROR this function takes 1 argument but 2 arguments were supplied
+        return groups;
+    }
+
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr
new file mode 100644 (file)
index 0000000..f0d64d2
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/wrong_argument_ice-3.rs:9:16
+   |
+LL |         groups.push(new_group, vec![process]);
+   |                ^^^^ ---------  ------------- supplied 2 arguments
+   |                |
+   |                expected 1 argument
+   |
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL |     pub fn push(&mut self, value: T) {
+   |            ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/tuple/wrong_argument_ice-4.rs b/src/test/ui/tuple/wrong_argument_ice-4.rs
new file mode 100644 (file)
index 0000000..479bd0d
--- /dev/null
@@ -0,0 +1,6 @@
+fn main() {
+    (|| {})(|| {
+        //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+        let b = 1;
+    });
+}
diff --git a/src/test/ui/tuple/wrong_argument_ice-4.stderr b/src/test/ui/tuple/wrong_argument_ice-4.stderr
new file mode 100644 (file)
index 0000000..fef5dca
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0057]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/wrong_argument_ice-4.rs:2:5
+   |
+LL |       (|| {})(|| {
+   |  _____^^^^^^^_-
+   | |     |
+   | |     expected 0 arguments
+LL | |
+LL | |         let b = 1;
+LL | |     });
+   | |_____- supplied 1 argument
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0057`.
index 747081933172b50aca38ca1e5efeaca93a347e5b..4baf198b12fae9251139cd00db67c64a0fec14d5 100644 (file)
@@ -5,7 +5,7 @@
 fn main() {}
 
 type Two<A, B> = impl Debug;
-//~^ ERROR the trait bound `A: Foo` is not satisfied in `(A, B, <A as Foo>::Bar)`
+//~^ ERROR the trait bound `A: Foo` is not satisfied
 //~| ERROR `A` doesn't implement `Debug`
 //~| ERROR `B` doesn't implement `Debug`
 
index a8eb53a50e38bb33d99f2256d7c3d58739878055..43471f980b2afe545f3eba8392b8e5d8bc54a044 100644 (file)
@@ -10,13 +10,12 @@ note: previous use here
 LL | fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `A: Foo` is not satisfied in `(A, B, <A as Foo>::Bar)`
+error[E0277]: the trait bound `A: Foo` is not satisfied
   --> $DIR/generic_duplicate_param_use9.rs:7:18
    |
 LL | type Two<A, B> = impl Debug;
-   |                  ^^^^^^^^^^ within `(A, B, <A as Foo>::Bar)`, the trait `Foo` is not implemented for `A`
+   |                  ^^^^^^^^^^ the trait `Foo` is not implemented for `A`
    |
-   = note: required because it appears within the type `(A, B, <A as Foo>::Bar)`
 help: consider restricting type parameter `A`
    |
 LL | type Two<A: Foo, B> = impl Debug;
@@ -28,7 +27,7 @@ error[E0277]: `A` doesn't implement `Debug`
 LL | type Two<A, B> = impl Debug;
    |                  ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)`
+   = note: required because of the requirements on the impl of `Debug` for `(A, B, _)`
 help: consider restricting type parameter `A`
    |
 LL | type Two<A: std::fmt::Debug, B> = impl Debug;
@@ -40,7 +39,7 @@ error[E0277]: `B` doesn't implement `Debug`
 LL | type Two<A, B> = impl Debug;
    |                  ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)`
+   = note: required because of the requirements on the impl of `Debug` for `(A, B, _)`
 help: consider restricting type parameter `B`
    |
 LL | type Two<A, B: std::fmt::Debug> = impl Debug;
index 792bd16527be83bde6ac9a00826a3c3ee037e6fc..007dcf3bcb6800d466d3f466909c0a1a7437e7bc 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_impl_trait, const_fn_fn_ptr_basics, rustc_attrs)]
+#![feature(rustc_attrs)]
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl Fn() -> usize;
index 176118200e5eda77159ddc43e42ed367e3934fb7..a3f126d56cf204c6cc704a636b389d85d73ef99f 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_impl_trait, generators, generator_trait, rustc_attrs)]
+#![feature(generators, generator_trait, rustc_attrs)]
 #![feature(type_alias_impl_trait)]
 
 use std::ops::Generator;
index ff4fd5dcec73c87b4a5763888470ee0513caa328..9f617153e3fd5fc5489bf4e755441150ed07474a 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(type_alias_impl_trait)]
-#![feature(type_alias_impl_trait)]
 #![allow(incomplete_features)]
 
 pub trait Foo {}
index 6fc6b4bfe1f0048cff2e0fe98fd8c080646e7984..2dbd5a55a625f966c9efd04c1636aa1858733ada 100644 (file)
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<() as Bar>::Foo == ()`
-  --> $DIR/issue-63355.rs:34:20
+  --> $DIR/issue-63355.rs:33:20
    |
 LL | pub type FooImpl = impl Foo;
    |                    -------- the found opaque type
@@ -7,7 +7,7 @@ LL | pub type BarImpl = impl Bar<Foo = FooImpl>;
    |                    ^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Bar>::Foo == ()`
    |
 note: expected this to be `()`
-  --> $DIR/issue-63355.rs:24:16
+  --> $DIR/issue-63355.rs:23:16
    |
 LL |     type Foo = FooImpl;
    |                ^^^^^^^
index 273928c4d663dbddaab863eced50c441b8f6c721..9a119c4d2e0aa76f542c9e3ff30bdb58a42d94d8 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(type_alias_impl_trait)]
-#![feature(type_alias_impl_trait)]
 #![allow(incomplete_features)]
 
 trait MyTrait {}
index 01d037266ec60d36b8ddce50f8040f0ed75edbbe..27680f0ad75accdd360abc00d9462ebdf8cb7496 100644 (file)
@@ -1,11 +1,11 @@
 error: cannot implement trait on type alias impl trait
-  --> $DIR/issue-65384.rs:11:1
+  --> $DIR/issue-65384.rs:10:1
    |
 LL | impl MyTrait for Bar {}
    | ^^^^^^^^^^^^^^^^^^^^
    |
 note: type alias impl trait defined here
-  --> $DIR/issue-65384.rs:9:12
+  --> $DIR/issue-65384.rs:8:12
    |
 LL | type Bar = impl MyTrait;
    |            ^^^^^^^^^^^^
index 5878b26fddbc78453ae0dde1501c75a310f9a9d3..f058653dde3389a2a75a3889993d068b74e01939 100644 (file)
@@ -5,8 +5,7 @@
 use std::future::Future;
 
 type G<'a, T> = impl Future<Output = ()>;
-//~^ ERROR: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
-//~| ERROR: the trait bound `T: Trait` is not satisfied
+//~^ ERROR: the trait bound `T: Trait` is not satisfied
 
 trait Trait {
     type F: Future<Output = ()>;
index 19ed9a7476c1b872bded84d1f988665a2067bfca..0df5a809ebb4748908995fc6e66da8039fef9b91 100644 (file)
@@ -1,22 +1,3 @@
-error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == ()`
-  --> $DIR/issue-89686.rs:7:17
-   |
-LL | type G<'a, T> = impl Future<Output = ()>;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
-...
-LL |         async move { self.f().await }
-   |                    ------------------ the found `async` block
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
-   |
-   = note:    expected unit type `()`
-           found associated type `<impl Future<Output = [async output]> as Future>::Output`
-   = help: consider constraining the associated type `<impl Future<Output = [async output]> as Future>::Output` to `()`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
-
 error[E0277]: the trait bound `T: Trait` is not satisfied
   --> $DIR/issue-89686.rs:7:17
    |
@@ -28,7 +9,6 @@ help: consider restricting type parameter `T`
 LL | type G<'a, T: Trait> = impl Future<Output = ()>;
    |             +++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
index 51a7b6454c35ef3189deb551f1a578b3e16d2dda..219837aa04baba2ff3ac12c8a835792215660ce9 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_impl_trait)]
 #![feature(type_alias_impl_trait)]
 
 type Bar = impl Send;
index 7e41b374452a3c2a9f99a40c9096e3e9cd51f1a5..889c4fd4b040556184b8dca4d8019f5486144b22 100644 (file)
@@ -1,5 +1,5 @@
 error: `impl Send` cannot be used in patterns
-  --> $DIR/structural-match-no-leak.rs:15:9
+  --> $DIR/structural-match-no-leak.rs:14:9
    |
 LL |         LEAK_FREE => (),
    |         ^^^^^^^^^
index 73558d39ad56163a69a0fa30840a9f31885d8414..c9e669cad603a963639d3b22ae96924fffa4c0b5 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_impl_trait)]
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl Send;
index b43f2148dea5ec84c4abe5e24a08a38325286aa8..262fd0726137e63c9547b43ea4977c99070bd147 100644 (file)
@@ -1,5 +1,5 @@
 error: `impl Send` cannot be used in patterns
-  --> $DIR/structural-match.rs:16:9
+  --> $DIR/structural-match.rs:15:9
    |
 LL |         VALUE => (),
    |         ^^^^^
index a4c59dced029a89db7514e82d9e3f0242230fd86..e5c81556e26b327b8390a1ddb8b9fee0ec80a136 100644 (file)
@@ -1,8 +1,6 @@
 // Test a default that references `Self` which is then used in an object type.
 // Issue #18956.
 
-#![feature(default_type_params)]
-
 trait Foo<T=Self> {
     fn method(&self);
 }
index eafd3cf79dbb0b588cd565ebaa44f8655ee5eaa9..4fc21bd7af230650a82fefb6214402d807c9d108 100644 (file)
@@ -1,5 +1,5 @@
 error[E0393]: the type parameter `T` must be explicitly specified
-  --> $DIR/type-parameter-defaults-referencing-Self.rs:10:16
+  --> $DIR/type-parameter-defaults-referencing-Self.rs:8:16
    |
 LL | / trait Foo<T=Self> {
 LL | |     fn method(&self);
index 5c82a56e77e141731ded61892979bc2829a5f485..ea1edf7d45073bba79f19dc573111079c4eb6aab 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 #![feature(unboxed_closures)]
 
 trait Lt<'a> {
@@ -10,6 +12,5 @@ impl<'a> Lt<'a> for () {
 fn main() {
     let v: <() as Lt<'_>>::T = ();
     let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: <() as Lt<'_>>::T| {};
-    //~^ ERROR: the size for values of type `<() as Lt<'_>>::T` cannot be known
     f(v);
 }
diff --git a/src/test/ui/unboxed-closures/issue-53448.stderr b/src/test/ui/unboxed-closures/issue-53448.stderr
deleted file mode 100644 (file)
index 8f9d918..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0277]: the size for values of type `<() as Lt<'_>>::T` cannot be known at compilation time
-  --> $DIR/issue-53448.rs:12:54
-   |
-LL |     let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: <() as Lt<'_>>::T| {};
-   |                                                      ^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `<() as Lt<'_>>::T`
-   = help: unsized fn params are gated as an unstable feature
-help: consider further restricting the associated type
-   |
-LL | fn main() where <() as Lt<'_>>::T: Sized {
-   |           ++++++++++++++++++++++++++++++
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL |     let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: &<() as Lt<'_>>::T| {};
-   |                                                         +
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
index 9f1c4c1a9e76c048c7574e3a58f4dd8901858f45..867e5fb1de7591f75507f06eab31df5ba68af3e3 100644 (file)
@@ -2,7 +2,6 @@
 // Fn to be used where FnMut is implemented.
 
 #![feature(fn_traits, unboxed_closures)]
-#![feature(overloaded_calls)]
 
 use std::ops::{Fn,FnMut,FnOnce};
 
index c8ce3091cf611f54d71be90a106296a2f9afc3ce..f379d73eecff723c39044f9af0424cfd86525ee6 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: expected a `Fn<(isize,)>` closure, found `S`
-  --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:21
+  --> $DIR/unboxed-closures-fnmut-as-fn.rs:27:21
    |
 LL |     let x = call_it(&S, 22);
    |             ------- ^^ expected an `Fn<(isize,)>` closure, found `S`
@@ -8,7 +8,7 @@ LL |     let x = call_it(&S, 22);
    |
    = help: the trait `Fn<(isize,)>` is not implemented for `S`
 note: required by a bound in `call_it`
-  --> $DIR/unboxed-closures-fnmut-as-fn.rs:23:14
+  --> $DIR/unboxed-closures-fnmut-as-fn.rs:22:14
    |
 LL | fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
    |              ^^^^^^^^^^^^^^^^ required by this bound in `call_it`
index 6a707b2096d442ea2156bf49d9f579939c4a661b..5e354cb6fce25355fca54d739c74c1dbb8bf3647 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(core, fn_traits, unboxed_closures)]
+#![feature(fn_traits, unboxed_closures)]
 
 use std::marker::PhantomData;
 
index 3cb9955674800e3d095cfc39649925a873394205..ad19c34a40a110237acf2eba71de2aa30ea23c74 100644 (file)
@@ -1,20 +1,18 @@
 error[E0005]: refutable pattern in local binding: `A(_)` not covered
   --> $DIR/uninhabited-irrefutable.rs:27:9
    |
-LL | / enum Foo {
-LL | |     A(foo::SecretlyEmpty),
-   | |     - not covered
-LL | |     B(foo::NotSoSecretlyEmpty),
-LL | |     C(NotSoSecretlyEmpty),
-LL | |     D(u32),
-LL | | }
-   | |_- `Foo` defined here
-...
-LL |       let Foo::D(_y) = x;
-   |           ^^^^^^^^^^ pattern `A(_)` not covered
+LL |     let Foo::D(_y) = x;
+   |         ^^^^^^^^^^ pattern `A(_)` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Foo` defined here
+  --> $DIR/uninhabited-irrefutable.rs:19:5
+   |
+LL | enum Foo {
+   |      ---
+LL |     A(foo::SecretlyEmpty),
+   |     ^ not covered
    = note: the matched value is of type `Foo`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index b92ceb479bd3b3b2c15a05fbb0698b12c02348a1..d90075d82f47b37defdc1e6a6d67b240ece67c86 100644 (file)
@@ -4,26 +4,44 @@ error[E0004]: non-exhaustive patterns: `Err(_)` not covered
 LL |     let _ = match x {
    |                   ^ pattern `Err(_)` not covered
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
+note: `Result<u32, &Void>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | / pub enum Result<T, E> {
+LL | |     /// Contains the success value
+LL | |     #[lang = "Ok"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+   | |     ^^^ not covered
+LL | | }
+   | |_-
+   = note: the matched value is of type `Result<u32, &Void>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     --- not covered
+LL ~         Ok(n) => n,
+LL ~         Err(_) => todo!(),
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Result<u32, &Void>`
 
 error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:15:19
    |
-LL | enum Void {}
-   | ------------ `Void` defined here
-...
 LL |     let _ = match x {};
    |                   ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+note: `Void` defined here
+  --> $DIR/uninhabited-matches-feature-gated.rs:2:6
+   |
+LL | enum Void {}
+   |      ^^^^
    = note: the matched value is of type `&Void`
    = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     let _ = match x {
+LL +         _ => todo!(),
+LL ~     };
+   |
 
 error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:18:19
@@ -31,8 +49,13 @@ error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
 LL |     let _ = match x {};
    |                   ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(Void,)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     let _ = match x {
+LL +         _ => todo!(),
+LL ~     };
+   |
 
 error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:21:19
@@ -40,8 +63,13 @@ error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
 LL |     let _ = match x {};
    |                   ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `[Void; 1]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     let _ = match x {
+LL +         _ => todo!(),
+LL ~     };
+   |
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
   --> $DIR/uninhabited-matches-feature-gated.rs:24:19
@@ -49,8 +77,12 @@ error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
 LL |     let _ = match x {
    |                   ^ pattern `&[_, ..]` not covered
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[Void]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &[] => (),
+LL ~         &[_, ..] => todo!(),
+   |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
   --> $DIR/uninhabited-matches-feature-gated.rs:32:19
@@ -58,13 +90,24 @@ error[E0004]: non-exhaustive patterns: `Err(_)` not covered
 LL |     let _ = match x {
    |                   ^ pattern `Err(_)` not covered
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
+note: `Result<u32, Void>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | / pub enum Result<T, E> {
+LL | |     /// Contains the success value
+LL | |     #[lang = "Ok"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+   | |     ^^^ not covered
+LL | | }
+   | |_-
+   = note: the matched value is of type `Result<u32, Void>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     --- not covered
+LL ~         Ok(x) => x,
+LL ~         Err(_) => todo!(),
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Result<u32, Void>`
 
 error[E0005]: refutable pattern in local binding: `Err(_)` not covered
   --> $DIR/uninhabited-matches-feature-gated.rs:37:9
@@ -72,13 +115,20 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered
 LL |     let Ok(x) = x;
    |         ^^^^^ pattern `Err(_)` not covered
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     --- not covered
-   |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Result<u32, Void>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+LL | / pub enum Result<T, E> {
+LL | |     /// Contains the success value
+LL | |     #[lang = "Ok"]
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+...  |
+LL | |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
+   | |     ^^^ not covered
+LL | | }
+   | |_-
    = note: the matched value is of type `Result<u32, Void>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
diff --git a/src/test/ui/unresolved/unresolved-asterisk-imports.rs b/src/test/ui/unresolved/unresolved-asterisk-imports.rs
new file mode 100644 (file)
index 0000000..2d853a6
--- /dev/null
@@ -0,0 +1,4 @@
+use not_existing_crate::*; //~ ERROR unresolved import `not_existing_crate
+use std as foo;
+
+fn main() {}
diff --git a/src/test/ui/unresolved/unresolved-asterisk-imports.stderr b/src/test/ui/unresolved/unresolved-asterisk-imports.stderr
new file mode 100644 (file)
index 0000000..a789179
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `not_existing_crate`
+  --> $DIR/unresolved-asterisk-imports.rs:1:5
+   |
+LL | use not_existing_crate::*;
+   |     ^^^^^^^^^^^^^^^^^^ maybe a missing crate `not_existing_crate`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
index c022d3aa0acd7ca18c18add8b97507f9a7678f6e..c437bde5ae69a47233ef3a16678dac8aff9d51a3 100644 (file)
@@ -13,4 +13,3 @@ tar = "0.4.29"
 sha2 = "0.10.1"
 rayon = "1.5.1"
 hex = "0.4.2"
-num_cpus = "1.13.0"
index 8a62146abfc4e47e3a1d16cf91fc31e4bb0b3dfa..378efeb644375a41b7fa0b9a7940a8bcb01dc7d2 100644 (file)
@@ -208,7 +208,7 @@ fn main() {
     let num_threads = if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") {
         num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS")
     } else {
-        num_cpus::get()
+        std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
     };
     rayon::ThreadPoolBuilder::new()
         .num_threads(num_threads)
index 3d6970d50e30e797b8e26b2b9b1bdf92dc381f34..65c82664263feddc5fe2d424be0993c28d46377a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3d6970d50e30e797b8e26b2b9b1bdf92dc381f34
+Subproject commit 65c82664263feddc5fe2d424be0993c28d46377a
index 5cc5530f874dd63e275f54d8832bf33ffd003e44..d4ca9480bec6231158a5e6eceab4503dbb42512e 100644 (file)
@@ -43,7 +43,7 @@ rustc-workspace-hack = "1.0"
 clippy_utils = { path = "clippy_utils" }
 derive-new = "0.5"
 if_chain = "1.0"
-itertools = "0.10"
+itertools = "0.10.1"
 quote = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 syn = { version = "1.0", features = ["full"] }
index d350d9a001827e899b183fc19bcf5952eb43bb29..d133e8cddabc729b96ec2d2617401a771883660a 100644 (file)
@@ -7,7 +7,7 @@ edition = "2021"
 bytecount = "0.6"
 clap = "2.33"
 indoc = "1.0"
-itertools = "0.10"
+itertools = "0.10.1"
 opener = "0.5"
 regex = "1.5"
 shell-escape = "0.1"
index 40d7dd702628f77c47475290ad312c3e5b0160d1..66e61660d313aa150e1fcbb9106fce4d83bc7ffe 100644 (file)
@@ -12,7 +12,7 @@ edition = "2021"
 cargo_metadata = "0.14"
 clippy_utils = { path = "../clippy_utils" }
 if_chain = "1.0"
-itertools = "0.10"
+itertools = "0.10.1"
 pulldown-cmark = { version = "0.9", default-features = false }
 quine-mc_cluskey = "0.2"
 regex-syntax = "0.6"
index bad9e0be82e61e026a25b715d2b20e50d18c960a..ecc9acf4445d03681bfc1a0e28ce1257abf99974 100644 (file)
@@ -3,6 +3,7 @@
 use clippy_utils::ty::has_drop;
 use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, meets_msrv, msrvs, trait_ref_of_method};
 use rustc_hir as hir;
+use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
 use rustc_lint::{LateContext, LateLintPass};
@@ -131,6 +132,18 @@ fn check_fn(
             FnKind::Closure => return,
         }
 
+        // Const fns are not allowed as methods in a trait.
+        {
+            let parent = cx.tcx.hir().get_parent_item(hir_id);
+            if parent != CRATE_DEF_ID {
+                if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent) {
+                    if let hir::ItemKind::Trait(..) = &item.kind {
+                        return;
+                    }
+                }
+            }
+        }
+
         let mir = cx.tcx.optimized_mir(def_id);
 
         if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, self.msrv.as_ref()) {
index 05eadab3e6ccdcc500f881b62668bbc1a53a2a08..81076776ed3d333ad00dc1271fa17ff199a6fc70 100644 (file)
@@ -326,7 +326,7 @@ fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty);
         if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty));
         then {
-            layout.layout.size.bytes() == 0
+            layout.layout.size().bytes() == 0
         } else {
             false
         }
index 3f4043ad052a034279ec979ea0e67590dde0a19d..3a47845ec82cef0deae5785d5de9c0764526b2d6 100644 (file)
@@ -279,20 +279,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (ForeignMod(l), ForeignMod(r)) => {
             both(&l.abi, &r.abi, eq_str_lit) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
         },
-        (
-            TyAlias(box ast::TyAlias {
-                defaultness: ld,
-                generics: lg,
-                bounds: lb,
-                ty: lt,
-            }),
-            TyAlias(box ast::TyAlias {
-                defaultness: rd,
-                generics: rg,
-                bounds: rb,
-                ty: rt,
-            }),
-        ) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt, .. }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt, .. })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
@@ -382,20 +370,8 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
-        (
-            TyAlias(box ast::TyAlias {
-                defaultness: ld,
-                generics: lg,
-                bounds: lb,
-                ty: lt,
-            }),
-            TyAlias(box ast::TyAlias {
-                defaultness: rd,
-                generics: rg,
-                bounds: rb,
-                ty: rt,
-            }),
-        ) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt, .. }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt, .. })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
@@ -426,20 +402,8 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
-        (
-            TyAlias(box ast::TyAlias {
-                defaultness: ld,
-                generics: lg,
-                bounds: lb,
-                ty: lt,
-            }),
-            TyAlias(box ast::TyAlias {
-                defaultness: rd,
-                generics: rg,
-                bounds: rb,
-                ty: rt,
-            }),
-        ) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt, .. }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt, .. })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
index d40583c47dd7074a8c069c0656652fdcf4652509..42b9e692d3ff4cbcf5198ffd29f3a8ef49805ca4 100644 (file)
@@ -593,7 +593,7 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
         ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty().kind() {
             ty::Ref(_, tam, _) => match tam.kind() {
                 ty::Str => String::from_utf8(
-                    data.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
+                    data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end)
                         .to_owned(),
                 )
                 .ok()
@@ -605,7 +605,7 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
         ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty().kind() {
             ty::Array(sub_type, len) => match sub_type.kind() {
                 ty::Float(FloatTy::F32) => match miri_to_const(*len) {
-                    Some(Constant::Int(len)) => alloc
+                    Some(Constant::Int(len)) => alloc.inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
                         .to_owned()
                         .chunks(4)
@@ -619,7 +619,7 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
                     _ => None,
                 },
                 ty::Float(FloatTy::F64) => match miri_to_const(*len) {
-                    Some(Constant::Int(len)) => alloc
+                    Some(Constant::Int(len)) => alloc.inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
                         .to_owned()
                         .chunks(8)
index c039fec955db9d2641fc86e43ce772da69f04021..891531951c1a03c0f6f5a3947544a04297151fcf 100644 (file)
@@ -32,32 +32,12 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
                 | ty::PredicateKind::Projection(_)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..)
+                | ty::PredicateKind::Trait(..)
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
                 ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
                 ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
                 ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
                 ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {:#?}", predicate),
-                ty::PredicateKind::Trait(pred) => {
-                    if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
-                        continue;
-                    }
-                    match pred.self_ty().kind() {
-                        ty::Param(ref p) => {
-                            let generics = tcx.generics_of(current);
-                            let def = generics.type_param(p, tcx);
-                            let span = tcx.def_span(def.def_id);
-                            return Err((
-                                span,
-                                "trait bounds other than `Sized` \
-                                 on const fn parameters are unstable"
-                                    .into(),
-                            ));
-                        },
-                        // other kinds of bounds are either tautologies
-                        // or cause errors in other passes
-                        _ => continue,
-                    }
-                },
             }
         }
         match predicates.parent {
index 7ffbd7a64b341fdb9cf27bddd90b50a49edec5d9..878897c410cf5e5c7014b75199df8ba15c964006 100644 (file)
@@ -1,14 +1,8 @@
 error[E0601]: `main` function not found in crate `ice_6250`
-  --> $DIR/ice-6250.rs:4:1
+  --> $DIR/ice-6250.rs:16:2
    |
-LL | / pub struct Cache {
-LL | |     data: Vec<i32>,
-LL | | }
-LL | |
-...  |
-LL | |     }
-LL | | }
-   | |_^ consider adding a `main` function to `$DIR/ice-6250.rs`
+LL | }
+   |  ^ consider adding a `main` function to `$DIR/ice-6250.rs`
 
 error[E0308]: mismatched types
   --> $DIR/ice-6250.rs:12:14
index 14c71e884b6ea9779cc867b6104d156e6821bf2c..77a3c2ba4ad09ba0286e9dc34a19e1b847e83805 100644 (file)
@@ -1,10 +1,8 @@
 error[E0601]: `main` function not found in crate `ice_6251`
-  --> $DIR/ice-6251.rs:4:1
+  --> $DIR/ice-6251.rs:6:2
    |
-LL | / fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
-LL | |     std::iter::empty()
-LL | | }
-   | |_^ consider adding a `main` function to `$DIR/ice-6251.rs`
+LL | }
+   |  ^ consider adding a `main` function to `$DIR/ice-6251.rs`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/ice-6251.rs:4:45
index baa7eec05462ebad8baea0762ed76b51ae7dfa2d..88f6935d224aec502122cc5ebf5e06d8b70a0a7f 100644 (file)
@@ -49,8 +49,6 @@ fn sub(x: u32) -> usize {
     unsafe { transmute(&x) }
 }
 
-// NOTE: This is currently not yet allowed to be const
-// Once implemented, Clippy should be able to suggest this as const, too.
 fn generic_arr<T: Copy>(t: [T; 1]) -> T {
     t[0]
 }
index b89cc6451bb592c5f3f6fbbab1daa194953d5101..3eb52b6827475d1b52f189cb0f876c68e6dc8191 100644 (file)
@@ -58,7 +58,15 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:67:9
+  --> $DIR/could_be_const.rs:52:1
+   |
+LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T {
+LL | |     t[0]
+LL | | }
+   | |_^
+
+error: this could be a `const fn`
+  --> $DIR/could_be_const.rs:65:9
    |
 LL | /         pub fn b(self, a: &A) -> B {
 LL | |             B
@@ -66,12 +74,12 @@ LL | |         }
    | |_________^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:77:5
+  --> $DIR/could_be_const.rs:75:5
    |
 LL | /     fn const_fn_stabilized_before_msrv(byte: u8) {
 LL | |         byte.is_ascii_digit();
 LL | |     }
    | |_____^
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
index 82fe790a576ab04c8fccc84af8bb1ebc1c1fcdb1..1bf6e6d011e5c125a2be7e7f64c5c3c54cbc15e5 100644 (file)
@@ -357,6 +357,7 @@ pub struct Config {
     pub cc: String,
     pub cxx: String,
     pub cflags: String,
+    pub cxxflags: String,
     pub ar: String,
     pub linker: Option<String>,
     pub llvm_components: String,
index 157b42e2d17f5a52f3bfdb8870178c7a0f28c7ba..5b144a1020f4c3e0f9baeb51299b3875c8e0a0af 100644 (file)
@@ -52,6 +52,7 @@ fn config() -> Config {
         "--cc=c",
         "--cxx=c++",
         "--cflags=",
+        "--cxxflags=",
         "--llvm-components=",
         "--android-cross-path=",
         "--target=x86_64-unknown-linux-gnu",
index 58cde108b33221987b025fd0e5dcae64f8c5e8ff..3f2cd3ae232ba5822452816d8dd8524fecea1e00 100644 (file)
@@ -126,6 +126,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .reqopt("", "cc", "path to a C compiler", "PATH")
         .reqopt("", "cxx", "path to a C++ compiler", "PATH")
         .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
+        .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
         .optopt("", "ar", "path to an archiver", "PATH")
         .optopt("", "linker", "path to a linker", "PATH")
         .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
@@ -288,6 +289,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         cc: matches.opt_str("cc").unwrap(),
         cxx: matches.opt_str("cxx").unwrap(),
         cflags: matches.opt_str("cflags").unwrap(),
+        cxxflags: matches.opt_str("cxxflags").unwrap(),
         ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
         linker: matches.opt_str("linker"),
         llvm_components: matches.opt_str("llvm-components").unwrap(),
index 3f67a64971b678193185769eee00d9eeab0f96e8..8431aa7b818df7b71b1dcd1ea1e4afd9c6872c5a 100644 (file)
@@ -2919,15 +2919,22 @@ fn run_rmake_test(&self) {
                 .map(|s| s.replace("/", "-"))
                 .collect::<Vec<_>>()
                 .join(" ");
+            let cxxflags = self
+                .config
+                .cxxflags
+                .split(' ')
+                .map(|s| s.replace("/", "-"))
+                .collect::<Vec<_>>()
+                .join(" ");
 
             cmd.env("IS_MSVC", "1")
                 .env("IS_WINDOWS", "1")
                 .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
                 .env("CC", format!("'{}' {}", self.config.cc, cflags))
-                .env("CXX", format!("'{}'", &self.config.cxx));
+                .env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
         } else {
             cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
-                .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags))
+                .env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
                 .env("AR", &self.config.ar);
 
             if self.config.target.contains("windows") {
index c6b3f687d5d9917b626f80a730552a185052ff28..722475ccc143d2dbf9fad5891207dcb5576e3d17 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c6b3f687d5d9917b626f80a730552a185052ff28
+Subproject commit 722475ccc143d2dbf9fad5891207dcb5576e3d17
index 4e72700e38421a12993fe5fa5c33d712652bc6c8..5fae65dd28b450a437ebc800a410164c3af1d516 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4e72700e38421a12993fe5fa5c33d712652bc6c8
+Subproject commit 5fae65dd28b450a437ebc800a410164c3af1d516
index 8d9c4a7fb20cd93264f5459a7997cb9ca7cbc4df..764714638a9787c214227c4580ea4203442f071f 100644 (file)
@@ -33,7 +33,7 @@ rustfmt-format-diff = []
 generic-simd = ["bytecount/generic-simd"]
 
 [dependencies]
-itertools = "0.9"
+itertools = "0.10.1"
 toml = "0.5"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
index babc56f86edc6db1a23ce47472563b9a2d71d10e..8498cb6addaa17375217846b654e2c842db16cd6 100644 (file)
@@ -694,7 +694,8 @@ pub(crate) fn format_impl(
     let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{");
     let where_clause_str = rewrite_where_clause(
         context,
-        &generics.where_clause,
+        &generics.where_clause.predicates,
+        generics.where_clause.span,
         context.config.brace_style(),
         Shape::legacy(where_budget, offset.block_only()),
         false,
@@ -1059,7 +1060,8 @@ pub(crate) fn format_trait(
             let option = WhereClauseOption::snuggled(&generics_str);
             let where_clause_str = rewrite_where_clause(
                 context,
-                &generics.where_clause,
+                &generics.where_clause.predicates,
+                generics.where_clause.span,
                 context.config.brace_style(),
                 Shape::legacy(where_budget, offset.block_only()),
                 where_on_new_line,
@@ -1178,7 +1180,8 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
 
         let where_str = rewrite_where_clause(
             context,
-            &self.generics.where_clause,
+            &self.generics.where_clause.predicates,
+            self.generics.where_clause.span,
             context.config.brace_style(),
             shape,
             false,
@@ -1437,7 +1440,8 @@ fn format_tuple_struct(
             let option = WhereClauseOption::new(true, WhereClauseSpace::Newline);
             rewrite_where_clause(
                 context,
-                &generics.where_clause,
+                &generics.where_clause.predicates,
+                generics.where_clause.span,
                 context.config.brace_style(),
                 Shape::legacy(where_budget, offset.block_only()),
                 false,
@@ -1503,6 +1507,8 @@ struct TyAliasRewriteInfo<'c, 'g>(
     &'c RewriteContext<'c>,
     Indent,
     &'g ast::Generics,
+    (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
+    usize,
     symbol::Ident,
     Span,
 );
@@ -1521,6 +1527,8 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         ref generics,
         ref bounds,
         ref ty,
+        where_clauses,
+        where_predicates_split,
     } = *ty_alias_kind;
     let ty_opt = ty.as_ref();
     let (ident, vis) = match visitor_kind {
@@ -1528,7 +1536,15 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
         ForeignItem(i) => (i.ident, &i.vis),
     };
-    let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span);
+    let rw_info = &TyAliasRewriteInfo(
+        context,
+        indent,
+        generics,
+        where_clauses,
+        where_predicates_split,
+        ident,
+        span,
+    );
     let op_ty = opaque_ty(ty);
     // Type Aliases are formatted slightly differently depending on the context
     // in which they appear, whether they are opaque, and whether they are associated.
@@ -1564,7 +1580,22 @@ fn rewrite_ty<R: Rewrite>(
     vis: &ast::Visibility,
 ) -> Option<String> {
     let mut result = String::with_capacity(128);
-    let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info;
+    let TyAliasRewriteInfo(
+        context,
+        indent,
+        generics,
+        where_clauses,
+        where_predicates_split,
+        ident,
+        span,
+    ) = *rw_info;
+    let (before_where_predicates, after_where_predicates) = generics
+        .where_clause
+        .predicates
+        .split_at(where_predicates_split);
+    if !after_where_predicates.is_empty() {
+        return None;
+    }
     result.push_str(&format!("{}type ", format_visibility(context, vis)));
     let ident_str = rewrite_ident(context, ident);
 
@@ -1595,7 +1626,8 @@ fn rewrite_ty<R: Rewrite>(
     }
     let where_clause_str = rewrite_where_clause(
         context,
-        &generics.where_clause,
+        before_where_predicates,
+        where_clauses.0.1,
         context.config.brace_style(),
         Shape::legacy(where_budget, indent),
         false,
@@ -1609,7 +1641,7 @@ fn rewrite_ty<R: Rewrite>(
     if let Some(ty) = rhs {
         // If there's a where clause, add a newline before the assignment. Otherwise just add a
         // space.
-        let has_where = !generics.where_clause.predicates.is_empty();
+        let has_where = !before_where_predicates.is_empty();
         if has_where {
             result.push_str(&indent.to_string_with_newline(context.config));
         } else {
@@ -1619,7 +1651,7 @@ fn rewrite_ty<R: Rewrite>(
         let comment_span = context
             .snippet_provider
             .opt_span_before(span, "=")
-            .map(|op_lo| mk_sp(generics.where_clause.span.hi(), op_lo));
+            .map(|op_lo| mk_sp(where_clauses.0.1.hi(), op_lo));
 
         let lhs = match comment_span {
             Some(comment_span)
@@ -2176,7 +2208,7 @@ fn rewrite_fn_base(
     let generics_str = rewrite_generics(
         context,
         rewrite_ident(context, ident),
-        fn_sig.generics,
+        &fn_sig.generics,
         shape,
     )?;
     result.push_str(&generics_str);
@@ -2416,7 +2448,8 @@ fn rewrite_fn_base(
     }
     let where_clause_str = rewrite_where_clause(
         context,
-        where_clause,
+        &where_clause.predicates,
+        where_clause.span,
         context.config.brace_style(),
         Shape::indented(indent, context.config),
         true,
@@ -2692,7 +2725,8 @@ fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> O
 
 fn rewrite_where_clause_rfc_style(
     context: &RewriteContext<'_>,
-    where_clause: &ast::WhereClause,
+    predicates: &[ast::WherePredicate],
+    where_span: Span,
     shape: Shape,
     terminator: &str,
     span_end: Option<BytePos>,
@@ -2701,7 +2735,8 @@ fn rewrite_where_clause_rfc_style(
 ) -> Option<String> {
     let (where_keyword, allow_single_line) = rewrite_where_keyword(
         context,
-        where_clause,
+        predicates,
+        where_span,
         shape,
         span_end_before_where,
         where_clause_option,
@@ -2714,12 +2749,12 @@ fn rewrite_where_clause_rfc_style(
         .block_left(context.config.tab_spaces())?
         .sub_width(1)?;
     let force_single_line = context.config.where_single_line()
-        && where_clause.predicates.len() == 1
+        && predicates.len() == 1
         && !where_clause_option.veto_single_line;
 
     let preds_str = rewrite_bounds_on_where_clause(
         context,
-        where_clause,
+        predicates,
         clause_shape,
         terminator,
         span_end,
@@ -2743,7 +2778,8 @@ fn rewrite_where_clause_rfc_style(
 /// Rewrite `where` and comment around it.
 fn rewrite_where_keyword(
     context: &RewriteContext<'_>,
-    where_clause: &ast::WhereClause,
+    predicates: &[ast::WherePredicate],
+    where_span: Span,
     shape: Shape,
     span_end_before_where: BytePos,
     where_clause_option: WhereClauseOption,
@@ -2763,7 +2799,7 @@ fn rewrite_where_keyword(
     };
 
     let (span_before, span_after) =
-        missing_span_before_after_where(span_end_before_where, where_clause);
+        missing_span_before_after_where(span_end_before_where, predicates, where_span);
     let (comment_before, comment_after) =
         rewrite_comments_before_after_where(context, span_before, span_after, shape)?;
 
@@ -2789,22 +2825,22 @@ fn rewrite_where_keyword(
 /// Rewrite bounds on a where clause.
 fn rewrite_bounds_on_where_clause(
     context: &RewriteContext<'_>,
-    where_clause: &ast::WhereClause,
+    predicates: &[ast::WherePredicate],
     shape: Shape,
     terminator: &str,
     span_end: Option<BytePos>,
     where_clause_option: WhereClauseOption,
     force_single_line: bool,
 ) -> Option<String> {
-    let span_start = where_clause.predicates[0].span().lo();
+    let span_start = predicates[0].span().lo();
     // If we don't have the start of the next span, then use the end of the
     // predicates, but that means we miss comments.
-    let len = where_clause.predicates.len();
-    let end_of_preds = where_clause.predicates[len - 1].span().hi();
+    let len = predicates.len();
+    let end_of_preds = predicates[len - 1].span().hi();
     let span_end = span_end.unwrap_or(end_of_preds);
     let items = itemize_list(
         context.snippet_provider,
-        where_clause.predicates.iter(),
+        predicates.iter(),
         terminator,
         ",",
         |pred| pred.span().lo(),
@@ -2837,7 +2873,8 @@ fn rewrite_bounds_on_where_clause(
 
 fn rewrite_where_clause(
     context: &RewriteContext<'_>,
-    where_clause: &ast::WhereClause,
+    predicates: &[ast::WherePredicate],
+    where_span: Span,
     brace_style: BraceStyle,
     shape: Shape,
     on_new_line: bool,
@@ -2846,14 +2883,15 @@ fn rewrite_where_clause(
     span_end_before_where: BytePos,
     where_clause_option: WhereClauseOption,
 ) -> Option<String> {
-    if where_clause.predicates.is_empty() {
+    if predicates.is_empty() {
         return Some(String::new());
     }
 
     if context.config.indent_style() == IndentStyle::Block {
         return rewrite_where_clause_rfc_style(
             context,
-            where_clause,
+            predicates,
+            where_span,
             shape,
             terminator,
             span_end,
@@ -2873,15 +2911,15 @@ fn rewrite_where_clause(
     // be out by a char or two.
 
     let budget = context.config.max_width() - offset.width();
-    let span_start = where_clause.predicates[0].span().lo();
+    let span_start = predicates[0].span().lo();
     // If we don't have the start of the next span, then use the end of the
     // predicates, but that means we miss comments.
-    let len = where_clause.predicates.len();
-    let end_of_preds = where_clause.predicates[len - 1].span().hi();
+    let len = predicates.len();
+    let end_of_preds = predicates[len - 1].span().hi();
     let span_end = span_end.unwrap_or(end_of_preds);
     let items = itemize_list(
         context.snippet_provider,
-        where_clause.predicates.iter(),
+        predicates.iter(),
         terminator,
         ",",
         |pred| pred.span().lo(),
@@ -2936,12 +2974,13 @@ fn rewrite_where_clause(
 
 fn missing_span_before_after_where(
     before_item_span_end: BytePos,
-    where_clause: &ast::WhereClause,
+    predicates: &[ast::WherePredicate],
+    where_span: Span,
 ) -> (Span, Span) {
-    let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo());
+    let missing_span_before = mk_sp(before_item_span_end, where_span.lo());
     // 5 = `where`
-    let pos_after_where = where_clause.span.lo() + BytePos(5);
-    let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo());
+    let pos_after_where = where_span.lo() + BytePos(5);
+    let missing_span_after = mk_sp(pos_after_where, predicates[0].span().lo());
     (missing_span_before, missing_span_after)
 }
 
@@ -3030,7 +3069,8 @@ fn format_generics(
         }
         let where_clause_str = rewrite_where_clause(
             context,
-            &generics.where_clause,
+            &generics.where_clause.predicates,
+            generics.where_clause.span,
             brace_style,
             Shape::legacy(budget, offset.block_only()),
             true,
index 276587e7f13fb44357688411c4a2b3f3316bdcf7..f6f1b918f061f30a107e5c1ae71ea556f852d7c4 100644 (file)
@@ -73,6 +73,13 @@ Thanks! <3
 """
 label = "O-riscv"
 
+[ping.fuchsia]
+message = """\
+Hey friends of Fuchsia! This issue could use some guidance on how this should be
+resolved/implemented on Fuchsia. Could one of you weigh in?
+"""
+label = "O-fuchsia"
+
 [prioritize]
 label = "I-prioritize"